]> git.saurik.com Git - cydia.git/blob - UICaboodle/BrowserView.mm
Massive fixes for 3.x.
[cydia.git] / UICaboodle / BrowserView.mm
1 #include <UICaboodle/BrowserView.h>
2 #include <UICaboodle/UCLocalize.h>
3
4 #import <QuartzCore/CALayer.h>
5 // XXX: fix the minimum requirement
6 extern NSString * const kCAFilterNearest;
7
8 #include <WebCore/WebCoreThread.h>
9 #include <WebKit/WebPreferences-WebPrivate.h>
10
11 #include "substrate.h"
12
13 static CFArrayRef (*$GSSystemCopyCapability)(CFStringRef);
14 static CFArrayRef (*$GSSystemGetCapability)(CFStringRef);
15
16 @interface NSString (UIKit)
17 - (NSString *) stringByAddingPercentEscapes;
18 @end
19
20 /* Indirect Delegate {{{ */
21 @interface IndirectDelegate : NSObject {
22 _transient volatile id delegate_;
23 }
24
25 - (void) setDelegate:(id)delegate;
26 - (id) initWithDelegate:(id)delegate;
27 @end
28
29 @implementation IndirectDelegate
30
31 - (void) setDelegate:(id)delegate {
32 delegate_ = delegate;
33 }
34
35 - (id) initWithDelegate:(id)delegate {
36 delegate_ = delegate;
37 return self;
38 }
39
40 - (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
41 if (delegate_ != nil)
42 return [delegate_ webView:sender didClearWindowObject:window forFrame:frame];
43 }
44
45 - (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {
46 if (delegate_ != nil)
47 return [delegate_ webView:sender didCommitLoadForFrame:frame];
48 }
49
50 - (void) webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
51 if (delegate_ != nil)
52 return [delegate_ webView:sender didFailLoadWithError:error forFrame:frame];
53 }
54
55 - (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
56 if (delegate_ != nil)
57 return [delegate_ webView:sender didFailProvisionalLoadWithError:error forFrame:frame];
58 }
59
60 - (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
61 if (delegate_ != nil)
62 return [delegate_ webView:sender didFinishLoadForFrame:frame];
63 }
64
65 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
66 if (delegate_ != nil)
67 return [delegate_ webView:sender didReceiveTitle:title forFrame:frame];
68 }
69
70 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
71 if (delegate_ != nil)
72 return [delegate_ webView:sender didStartProvisionalLoadForFrame:frame];
73 }
74
75 - (void) webView:(WebView *)sender resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)source {
76 if (delegate_ != nil)
77 return [delegate_ webView:sender resource:identifier didReceiveAuthenticationChallenge:challenge fromDataSource:source];
78 }
79
80 - (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
81 if (delegate_ != nil)
82 return [delegate_ webView:sender resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:source];
83 return nil;
84 }
85
86 - (IMP) methodForSelector:(SEL)sel {
87 if (IMP method = [super methodForSelector:sel])
88 return method;
89 fprintf(stderr, "methodForSelector:[%s] == NULL\n", sel_getName(sel));
90 return NULL;
91 }
92
93 - (BOOL) respondsToSelector:(SEL)sel {
94 if ([super respondsToSelector:sel])
95 return YES;
96 // XXX: WebThreadCreateNSInvocation returns nil
97 //fprintf(stderr, "[%s]R?%s\n", class_getName(self->isa), sel_getName(sel));
98 return delegate_ == nil ? NO : [delegate_ respondsToSelector:sel];
99 }
100
101 - (NSMethodSignature *) methodSignatureForSelector:(SEL)sel {
102 if (NSMethodSignature *method = [super methodSignatureForSelector:sel])
103 return method;
104 //fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel));
105 if (delegate_ != nil)
106 if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel])
107 return sig;
108 // XXX: I fucking hate Apple so very very bad
109 return [NSMethodSignature signatureWithObjCTypes:"v@:"];
110 }
111
112 - (void) forwardInvocation:(NSInvocation *)inv {
113 SEL sel = [inv selector];
114 if (delegate_ != nil && [delegate_ respondsToSelector:sel])
115 [inv invokeWithTarget:delegate_];
116 }
117
118 @end
119 /* }}} */
120
121 @interface WebView (UICaboodle)
122 - (void) setScriptDebugDelegate:(id)delegate;
123 - (void) _setFormDelegate:(id)delegate;
124 - (void) _setUIKitDelegate:(id)delegate;
125 - (void) setWebMailDelegate:(id)delegate;
126 - (void) _setLayoutInterval:(float)interval;
127 @end
128
129 @implementation WebScriptObject (UICaboodle)
130
131 - (unsigned) count {
132 id length([self valueForKey:@"length"]);
133 if ([length respondsToSelector:@selector(intValue)])
134 return [length intValue];
135 else
136 return 0;
137 }
138
139 - (id) objectAtIndex:(unsigned)index {
140 return [self webScriptValueAtIndex:index];
141 }
142
143 @end
144
145 #if 0
146 /* Mail Composition {{{ */
147 @interface MailToView : PopUpView {
148 MailComposeController *controller_;
149 }
150
151 - (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url;
152
153 @end
154
155 @implementation MailToView
156
157 - (void) dealloc {
158 [controller_ release];
159 [super dealloc];
160 }
161
162 - (void) mailComposeControllerWillAttemptToSend:(MailComposeController *)controller {
163 NSLog(@"will");
164 }
165
166 - (void) mailComposeControllerDidAttemptToSend:(MailComposeController *)controller mailDelivery:(id)delivery {
167 NSLog(@"did:%@", delivery);
168 // [UIApp setStatusBarShowsProgress:NO];
169 if ([controller error]){
170 NSArray *buttons = [NSArray arrayWithObjects:UCLocalize("OK"), nil];
171 UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:UCLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
172 [mailAlertSheet setBodyText:[controller error]];
173 [mailAlertSheet popupAlertAnimated:YES];
174 }
175 }
176
177 - (void) showError {
178 NSLog(@"%@", [controller_ error]);
179 NSArray *buttons = [NSArray arrayWithObjects:UCLocalize("OK"), nil];
180 UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:UCLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
181 [mailAlertSheet setBodyText:[controller_ error]];
182 [mailAlertSheet popupAlertAnimated:YES];
183 }
184
185 - (void) deliverMessage { _pooled
186 setuid(501);
187 setgid(501);
188
189 if (![controller_ deliverMessage])
190 [self performSelectorOnMainThread:@selector(showError) withObject:nil waitUntilDone:NO];
191 }
192
193 - (void) mailComposeControllerCompositionFinished:(MailComposeController *)controller {
194 if ([controller_ needsDelivery])
195 [NSThread detachNewThreadSelector:@selector(deliverMessage) toTarget:self withObject:nil];
196 else
197 [self cancel];
198 }
199
200 - (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url {
201 if ((self = [super initWithView:view delegate:delegate]) != nil) {
202 controller_ = [[MailComposeController alloc] initForContentSize:[overlay_ bounds].size];
203 [controller_ setDelegate:self];
204 [controller_ initializeUI];
205 [controller_ setupForURL:url];
206
207 UIView *view([controller_ view]);
208 [overlay_ addSubview:view];
209 } return self;
210 }
211
212 @end
213 /* }}} */
214 #endif
215
216 #define ShowInternals 0
217 #define LogBrowser 0
218
219 #define lprintf(args...) fprintf(stderr, args)
220
221 @implementation BrowserView
222
223 #if ShowInternals
224 #include "UICaboodle/UCInternal.h"
225 #endif
226
227 + (void) _initialize {
228 [WebView enableWebThread];
229
230 WebPreferences *preferences([WebPreferences standardPreferences]);
231 [preferences setCacheModel:WebCacheModelDocumentBrowser];
232 [preferences setOfflineWebApplicationCacheEnabled:YES];
233
234 [WebPreferences _setInitialDefaultTextEncodingToSystemEncoding];
235
236 $GSSystemCopyCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemCopyCapability"));
237 $GSSystemGetCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemGetCapability"));
238 }
239
240 - (void) dealloc {
241 #if LogBrowser
242 NSLog(@"[BrowserView dealloc]");
243 #endif
244
245 if (challenge_ != nil)
246 [challenge_ release];
247
248 WebThreadLock();
249
250 WebView *webview = [webview_ webView];
251 [webview setFrameLoadDelegate:nil];
252 [webview setResourceLoadDelegate:nil];
253 [webview setUIDelegate:nil];
254 [webview setScriptDebugDelegate:nil];
255 [webview setPolicyDelegate:nil];
256
257 /* XXX: these are set by UIWebDocumentView
258 [webview setDownloadDelegate:nil];
259 [webview _setFormDelegate:nil];
260 [webview _setUIKitDelegate:nil];
261 [webview setEditingDelegate:nil];*/
262
263 /* XXX: no one sets this, ever
264 [webview setWebMailDelegate:nil];*/
265
266 [webview_ setDelegate:nil];
267 [webview_ setGestureDelegate:nil];
268 [webview_ setFormEditingDelegate:nil];
269 [webview_ setInteractionDelegate:nil];
270
271 [indirect_ setDelegate:nil];
272
273 //NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
274
275 [webview close];
276
277 #if RecycleWebViews
278 [webview_ removeFromSuperview];
279 [Documents_ addObject:[webview_ autorelease]];
280 #else
281 [webview_ release];
282 #endif
283
284 [indirect_ release];
285
286 WebThreadUnlock();
287
288 [scroller_ setDelegate:nil];
289
290 if (button_ != nil)
291 [button_ release];
292 if (style_ != nil)
293 [style_ release];
294 if (function_ != nil)
295 [function_ release];
296 if (finish_ != nil)
297 [finish_ release];
298 if (closer_ != nil)
299 [closer_ release];
300 if (special_ != nil)
301 [special_ release];
302
303 [scroller_ release];
304 [indicator_ release];
305 if (confirm_ != nil)
306 [confirm_ release];
307 if (sensitive_ != nil)
308 [sensitive_ release];
309 if (title_ != nil)
310 [title_ release];
311 [super dealloc];
312 }
313
314 - (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy {
315 [self loadRequest:[NSURLRequest
316 requestWithURL:url
317 cachePolicy:policy
318 timeoutInterval:30.0
319 ]];
320 }
321
322 - (void) loadURL:(NSURL *)url {
323 [self loadURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy];
324 }
325
326 - (void) loadRequest:(NSURLRequest *)request {
327 pushed_ = true;
328 error_ = false;
329
330 WebThreadLock();
331 [webview_ loadRequest:request];
332 WebThreadUnlock();
333 }
334
335 - (void) reloadURL {
336 if (request_ == nil)
337 return;
338
339 if ([request_ HTTPBody] == nil && [request_ HTTPBodyStream] == nil)
340 [self loadRequest:request_];
341 else {
342 UIActionSheet *sheet = [[[UIActionSheet alloc]
343 initWithTitle:UCLocalize("RESUBMIT_FORM")
344 buttons:[NSArray arrayWithObjects:UCLocalize("CANCEL"), UCLocalize("SUBMIT"), nil]
345 defaultButtonIndex:0
346 delegate:self
347 context:@"submit"
348 ] autorelease];
349
350 [sheet setNumberOfRows:1];
351 [sheet popupAlertAnimated:YES];
352 }
353 }
354
355 - (WebView *) webView {
356 return [webview_ webView];
357 }
358
359 - (UIWebDocumentView *) documentView {
360 return webview_;
361 }
362
363 /* XXX: WebThreadLock? */
364 - (void) _fixScroller:(CGRect)bounds {
365 float extra;
366 if (!editing_)
367 extra = 0;
368 else {
369 UIFormAssistant *assistant([UIFormAssistant sharedFormAssistant]);
370 CGRect peripheral([assistant peripheralFrame]);
371 #if LogBrowser
372 NSLog(@"per:%f", peripheral.size.height);
373 #endif
374 extra = peripheral.size.height;
375 }
376
377 CGRect subrect([scroller_ frame]);
378 subrect.size.height -= extra;
379 [scroller_ setScrollerIndicatorSubrect:subrect];
380
381 NSSize visible(NSMakeSize(subrect.size.width, subrect.size.height));
382 [webview_ setValue:[NSValue valueWithSize:visible] forGestureAttribute:UIGestureAttributeVisibleSize];
383
384 CGSize size(size_);
385 size.height += extra;
386 [scroller_ setContentSize:size];
387
388 [scroller_ releaseRubberBandIfNecessary];
389 }
390
391 - (void) fixScroller {
392 CGRect bounds([webview_ documentBounds]);
393 #if TrackResize
394 NSLog(@"_fs:(%f,%f+%f,%f)", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
395 #endif
396 [self _fixScroller:bounds];
397 }
398
399 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame {
400 size_ = frame.size;
401 #if TrackResize
402 NSLog(@"dsf:(%f,%f+%f,%f)", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
403 #endif
404 [self _fixScroller:frame];
405 }
406
407 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
408 [self view:sender didSetFrame:frame];
409 }
410
411 - (void) pushPage:(RVPage *)page {
412 [page setDelegate:delegate_];
413 [self setBackButtonTitle:title_];
414 [book_ pushPage:page];
415 }
416
417 - (void) _pushPage {
418 if (pushed_)
419 return;
420 // WTR: [self autorelease];
421 pushed_ = true;
422 [book_ pushPage:self];
423 }
424
425 - (void) swapPage:(RVPage *)page {
426 [page setDelegate:delegate_];
427 if (pushed_)
428 [book_ swapPage:page];
429 else
430 [book_ pushPage:page];
431 }
432
433 - (BOOL) getSpecial:(NSURL *)url swap:(BOOL)swap {
434 #if LogBrowser
435 NSLog(@"getSpecial:%@", url);
436 #endif
437
438 if (RVPage *page = [delegate_ pageForURL:url hasTag:NULL]) {
439 if (swap)
440 [self swapPage:page];
441 else
442 [self pushPage:page];
443
444 return true;
445 } else
446 return false;
447 }
448
449 - (void) formAssistant:(id)sender didBeginEditingFormNode:(id)node {
450 }
451
452 - (void) formAssistant:(id)sender didEndEditingFormNode:(id)node {
453 [self fixScroller];
454 }
455
456 - (void) webViewShow:(WebView *)sender {
457 /* XXX: this is where I cry myself to sleep */
458 }
459
460 - (bool) _allowJavaScriptPanel {
461 return true;
462 }
463
464 - (bool) allowSensitiveRequests {
465 return [self _allowJavaScriptPanel];
466 }
467
468 - (void) _promptForSensitive:(NSMutableArray *)array {
469 NSString *name([array objectAtIndex:0]);
470
471 UIActionSheet *sheet = [[[UIActionSheet alloc]
472 initWithTitle:nil
473 buttons:[NSArray arrayWithObjects:UCLocalize("YES"), UCLocalize("NO"), nil]
474 defaultButtonIndex:0
475 delegate:indirect_
476 context:@"sensitive"
477 ] autorelease];
478
479 NSString *host(@"XXX");
480
481 [sheet setNumberOfRows:1];
482 [sheet setBodyText:[NSString stringWithFormat:@"The website at %@ is requesting your phone's %@. This is almost certainly for product licensing purposes. Will you allow this?", host, name]];
483 [sheet popupAlertAnimated:YES];
484
485 NSRunLoop *loop([NSRunLoop currentRunLoop]);
486 NSDate *future([NSDate distantFuture]);
487
488 while (sensitive_ == nil && [loop runMode:NSDefaultRunLoopMode beforeDate:future]);
489
490 NSNumber *sensitive([sensitive_ autorelease]);
491 sensitive_ = nil;
492
493 [self autorelease];
494 [array replaceObjectAtIndex:0 withObject:sensitive];
495 }
496
497 - (bool) promptForSensitive:(NSString *)name {
498 if (![self allowSensitiveRequests])
499 return false;
500
501 NSMutableArray *array([NSMutableArray arrayWithCapacity:1]);
502 [array addObject:name];
503
504 [self performSelectorOnMainThread:@selector(_promptForSensitive:) withObject:array waitUntilDone:YES];
505 return [[array lastObject] boolValue];
506 }
507
508 - (void) webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
509 if (![self _allowJavaScriptPanel])
510 return;
511 [self retain];
512
513 UIActionSheet *sheet = [[[UIActionSheet alloc]
514 initWithTitle:nil
515 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil]
516 defaultButtonIndex:0
517 delegate:self
518 context:@"alert"
519 ] autorelease];
520
521 [sheet setBodyText:message];
522 [sheet popupAlertAnimated:YES];
523 }
524
525 - (BOOL) webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
526 if (![self _allowJavaScriptPanel])
527 return NO;
528 [self retain];
529
530 UIActionSheet *sheet = [[[UIActionSheet alloc]
531 initWithTitle:nil
532 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), UCLocalize("CANCEL"), nil]
533 defaultButtonIndex:0
534 delegate:indirect_
535 context:@"confirm"
536 ] autorelease];
537
538 [sheet setNumberOfRows:1];
539 [sheet setBodyText:message];
540 [sheet popupAlertAnimated:YES];
541
542 NSRunLoop *loop([NSRunLoop currentRunLoop]);
543 NSDate *future([NSDate distantFuture]);
544
545 while (confirm_ == nil && [loop runMode:NSDefaultRunLoopMode beforeDate:future]);
546
547 NSNumber *confirm([confirm_ autorelease]);
548 confirm_ = nil;
549
550 [self autorelease];
551 return [confirm boolValue];
552 }
553
554 - (void) setAutoPopup:(BOOL)popup {
555 popup_ = popup;
556 }
557
558 - (void) setSpecial:(id)function {
559 if (special_ != nil)
560 [special_ autorelease];
561 special_ = function == nil ? nil : [function retain];
562 }
563
564 - (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
565 if (button_ != nil)
566 [button_ autorelease];
567 button_ = button == nil ? nil : [[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:button]]] retain];
568
569 if (style_ != nil)
570 [style_ autorelease];
571 style_ = style == nil ? nil : [style retain];
572
573 if (function_ != nil)
574 [function_ autorelease];
575 function_ = function == nil ? nil : [function retain];
576
577 [self reloadButtons];
578 }
579
580 - (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
581 if (button_ != nil)
582 [button_ autorelease];
583 button_ = button == nil ? nil : [button retain];
584
585 if (style_ != nil)
586 [style_ autorelease];
587 style_ = style == nil ? nil : [style retain];
588
589 if (function_ != nil)
590 [function_ autorelease];
591 function_ = function == nil ? nil : [function retain];
592
593 [self reloadButtons];
594 }
595
596 - (void) setFinishHook:(id)function {
597 if (finish_ != nil)
598 [finish_ autorelease];
599 finish_ = function == nil ? nil : [function retain];
600 }
601
602 - (void) setPopupHook:(id)function {
603 if (closer_ != nil)
604 [closer_ autorelease];
605 closer_ = function == nil ? nil : [function retain];
606 }
607
608 - (void) _openMailToURL:(NSURL *)url {
609 // XXX: this makes me sad
610 #if 0
611 [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease];
612 #else
613 [UIApp openURL:url];// asPanel:YES];
614 #endif
615 }
616
617 - (void) webView:(WebView *)sender willBeginEditingFormElement:(id)element {
618 editing_ = true;
619 }
620
621 - (void) webView:(WebView *)sender didBeginEditingFormElement:(id)element {
622 [self fixScroller];
623 }
624
625 - (void) webViewDidEndEditingFormElements:(WebView *)sender {
626 editing_ = false;
627 [self fixScroller];
628 }
629
630 - (void) webViewClose:(WebView *)sender {
631 [book_ close];
632 }
633
634 - (void) close {
635 [book_ close];
636 }
637
638 - (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
639 }
640
641 - (void) webView:(WebView *)sender unableToImplementPolicyWithError:(NSError *)error frame:(WebFrame *)frame {
642 NSLog(@"err:%@", error);
643 }
644
645 - (void) webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)action request:(NSURLRequest *)request newFrameName:(NSString *)name decisionListener:(id<WebPolicyDecisionListener>)listener {
646 #if LogBrowser
647 NSLog(@"nwa:%@", name);
648 #endif
649
650 if (NSURL *url = [request URL]) {
651 if (name == nil) unknown: {
652 if (![self getSpecial:url swap:NO]) {
653 NSString *scheme([[url scheme] lowercaseString]);
654 if ([scheme isEqualToString:@"mailto"])
655 [self _openMailToURL:url];
656 else goto use;
657 }
658 } else if ([name isEqualToString:@"_open"])
659 [delegate_ openURL:url];
660 else if ([name isEqualToString:@"_popup"]) {
661 NSString *scheme([[url scheme] lowercaseString]);
662 if ([scheme isEqualToString:@"mailto"])
663 [self _openMailToURL:url];
664 else {
665 RVBook *book([[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
666 [book setHook:indirect_];
667
668 RVPage *page([delegate_ pageForURL:url hasTag:NULL]);
669 if (page == nil) {
670 /* XXX: call createWebViewWithRequest instead? */
671
672 [self setBackButtonTitle:title_];
673
674 BrowserView *browser([[[class_ alloc] initWithBook:book] autorelease]);
675 [browser loadURL:url];
676 page = browser;
677 }
678
679 [book setDelegate:delegate_];
680 [page setDelegate:delegate_];
681
682 [book setPage:page];
683 [book_ pushBook:book];
684 }
685 } else goto unknown;
686
687 [listener ignore];
688 } else use:
689 [listener use];
690 }
691
692 - (void) webView:(WebView *)sender decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
693 if ([WebView canShowMIMEType:type])
694 [listener use];
695 else {
696 // XXX: handle more mime types!
697 [listener ignore];
698
699 WebView *webview([webview_ webView]);
700 if (frame == [webview mainFrame])
701 [UIApp openURL:[request URL]];
702 }
703 }
704
705 - (void) webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
706 if (request == nil) ignore: {
707 [listener ignore];
708 return;
709 }
710
711 NSURL *url([request URL]);
712 NSString *host([url host]);
713
714 if (url == nil) use: {
715 if (!error_ && [frame parentFrame] == nil) {
716 if (request_ != nil)
717 [request_ autorelease];
718 request_ = [request retain];
719 #if LogBrowser
720 NSLog(@"dpn:%@", request_);
721 #endif
722 }
723
724 [listener use];
725
726 WebView *webview([webview_ webView]);
727 if (frame == [webview mainFrame])
728 [self _pushPage];
729 return;
730 }
731 #if LogBrowser
732 else NSLog(@"nav:%@:%@", url, [action description]);
733 #endif
734
735 const NSArray *capability;
736
737 if ($GSSystemCopyCapability != NULL) {
738 capability = reinterpret_cast<const NSArray *>((*$GSSystemCopyCapability)(kGSDisplayIdentifiersCapability));
739 capability = [capability autorelease];
740 } else if ($GSSystemGetCapability != NULL) {
741 capability = reinterpret_cast<const NSArray *>((*$GSSystemGetCapability)(kGSDisplayIdentifiersCapability));
742 } else
743 capability = nil;
744
745 NSURL *open(nil);
746
747 if (capability != nil && (
748 [url isGoogleMapsURL] && [capability containsObject:@"com.apple.Maps"] && (open = [url mapsURL]) != nil||
749 [host hasSuffix:@"youtube.com"] && [capability containsObject:@"com.apple.youtube"] && (open = [url youTubeURL]) != nil ||
750 [url respondsToSelector:@selector(phobosURL)] && (open = [url phobosURL]) != nil
751 )) {
752 url = open;
753 open:
754 [UIApp openURL:url];
755 goto ignore;
756 }
757
758 int store(_not(int));
759 if (NSURL *itms = [url itmsURL:&store]) {
760 #if LogBrowser
761 NSLog(@"itms#%@#%u#%@", url, store, itms);
762 #endif
763
764 if (capability != nil && (
765 store == 1 && [capability containsObject:@"com.apple.MobileStore"] ||
766 store == 2 && [capability containsObject:@"com.apple.AppStore"]
767 )) {
768 url = itms;
769 goto open;
770 }
771 }
772
773 NSString *scheme([[url scheme] lowercaseString]);
774
775 if ([scheme isEqualToString:@"tel"]) {
776 // XXX: intelligence
777 goto open;
778 }
779
780 if ([scheme isEqualToString:@"mailto"]) {
781 [self _openMailToURL:url];
782 goto ignore;
783 }
784
785 if ([self getSpecial:url swap:YES])
786 goto ignore;
787 else if ([WebView _canHandleRequest:request])
788 goto use;
789 else if ([url isSpringboardHandledURL])
790 goto open;
791 else
792 goto use;
793 }
794
795 - (void) webView:(WebView *)sender setStatusText:(NSString *)text {
796 //lprintf("Status:%s\n", [text UTF8String]);
797 }
798
799 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
800 NSString *context([sheet context]);
801
802 if ([context isEqualToString:@"alert"]) {
803 [self autorelease];
804 [sheet dismiss];
805 } else if ([context isEqualToString:@"confirm"]) {
806 switch (button) {
807 case 1:
808 confirm_ = [NSNumber numberWithBool:YES];
809 break;
810
811 case 2:
812 confirm_ = [NSNumber numberWithBool:NO];
813 break;
814 }
815
816 [sheet dismiss];
817 } else if ([context isEqualToString:@"sensitive"]) {
818 switch (button) {
819 case 1:
820 sensitive_ = [NSNumber numberWithBool:YES];
821 break;
822
823 case 2:
824 sensitive_ = [NSNumber numberWithBool:NO];
825 break;
826 }
827
828 [sheet dismiss];
829 } else if ([context isEqualToString:@"challenge"]) {
830 id<NSURLAuthenticationChallengeSender> sender([challenge_ sender]);
831
832 switch (button) {
833 case 1: {
834 NSString *username([[sheet textFieldAtIndex:0] text]);
835 NSString *password([[sheet textFieldAtIndex:1] text]);
836
837 NSURLCredential *credential([NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceForSession]);
838
839 [sender useCredential:credential forAuthenticationChallenge:challenge_];
840 } break;
841
842 case 2:
843 [sender cancelAuthenticationChallenge:challenge_];
844 break;
845
846 default:
847 _assert(false);
848 }
849
850 [challenge_ release];
851 challenge_ = nil;
852
853 [sheet dismiss];
854 } else if ([context isEqualToString:@"submit"]) {
855 switch (button) {
856 case 1:
857 break;
858
859 case 2:
860 if (request_ != nil) {
861 WebThreadLock();
862 [webview_ loadRequest:request_];
863 WebThreadUnlock();
864 }
865 break;
866
867 default:
868 _assert(false);
869 }
870
871 [sheet dismiss];
872 }
873 }
874
875 - (void) webView:(WebView *)sender resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)source {
876 challenge_ = [challenge retain];
877
878 NSURLProtectionSpace *space([challenge protectionSpace]);
879 NSString *realm([space realm]);
880 if (realm == nil)
881 realm = @"";
882
883 UIActionSheet *sheet = [[[UIActionSheet alloc]
884 initWithTitle:realm
885 buttons:[NSArray arrayWithObjects:UCLocalize("LOGIN"), UCLocalize("CANCEL"), nil]
886 defaultButtonIndex:0
887 delegate:self
888 context:@"challenge"
889 ] autorelease];
890
891 [sheet setNumberOfRows:1];
892
893 [sheet addTextFieldWithValue:@"" label:UCLocalize("USERNAME")];
894 [sheet addTextFieldWithValue:@"" label:UCLocalize("PASSWORD")];
895
896 UITextField *username([sheet textFieldAtIndex:0]); {
897 UITextInputTraits *traits([username textInputTraits]);
898 [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
899 [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
900 [traits setKeyboardType:UIKeyboardTypeASCIICapable];
901 [traits setReturnKeyType:UIReturnKeyNext];
902 }
903
904 UITextField *password([sheet textFieldAtIndex:1]); {
905 UITextInputTraits *traits([password textInputTraits]);
906 [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
907 [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
908 [traits setKeyboardType:UIKeyboardTypeASCIICapable];
909 // XXX: UIReturnKeyDone
910 [traits setReturnKeyType:UIReturnKeyNext];
911 [traits setSecureTextEntry:YES];
912 }
913
914 [sheet popupAlertAnimated:YES];
915 }
916
917 - (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
918 return request;
919 }
920
921 - (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features {
922 //- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request userGesture:(BOOL)gesture {
923 #if LogBrowser
924 NSLog(@"cwv:%@ (%@): %@", request, title_, features == nil ? @"{}" : [features description]);
925 //NSLog(@"cwv:%@ (%@): %@", request, title_, gesture ? @"Yes" : @"No");
926 #endif
927
928 NSNumber *value([features objectForKey:@"width"]);
929 float width(value == nil ? 0 : [value floatValue]);
930
931 RVBook *book(!popup_ ? book_ : [[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
932
933 /* XXX: deal with cydia:// pages */
934 BrowserView *browser([[[class_ alloc] initWithBook:book forWidth:width] autorelease]);
935
936 if (features != nil && popup_) {
937 [book setDelegate:delegate_];
938 [book setHook:indirect_];
939 [browser setDelegate:delegate_];
940
941 [browser loadRequest:request];
942
943 [book setPage:browser];
944 [book_ pushBook:book];
945 } else if (request == nil) {
946 [self setBackButtonTitle:title_];
947 [browser setDelegate:delegate_];
948 [browser retain];
949 } else {
950 [self pushPage:browser];
951 [browser loadRequest:request];
952 }
953
954 return [browser webView];
955 }
956
957 - (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
958 return [self webView:sender createWebViewWithRequest:request windowFeatures:nil];
959 //return [self webView:sender createWebViewWithRequest:request userGesture:YES];
960 }
961
962 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
963 if ([frame parentFrame] != nil)
964 return;
965
966 title_ = [title retain];
967 [book_ reloadTitleForPage:self];
968 }
969
970 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
971 if ([loading_ count] == 0)
972 [self retain];
973 [loading_ addObject:[NSValue valueWithNonretainedObject:frame]];
974
975 if ([frame parentFrame] == nil) {
976 [webview_ resignFirstResponder];
977
978 reloading_ = false;
979
980 if (title_ != nil) {
981 [title_ release];
982 title_ = nil;
983 }
984
985 if (button_ != nil) {
986 [button_ release];
987 button_ = nil;
988 }
989
990 if (style_ != nil) {
991 [style_ release];
992 style_ = nil;
993 }
994
995 if (function_ != nil) {
996 [function_ release];
997 function_ = nil;
998 }
999
1000 if (finish_ != nil) {
1001 [finish_ release];
1002 finish_ = nil;
1003 }
1004
1005 if (closer_ != nil) {
1006 [closer_ release];
1007 closer_ = nil;
1008 }
1009
1010 if (special_ != nil) {
1011 [special_ release];
1012 special_ = nil;
1013 }
1014
1015 [book_ reloadTitleForPage:self];
1016
1017 [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
1018
1019 if ([scroller_ respondsToSelector:@selector(setZoomScale:duration:)])
1020 [scroller_ setZoomScale:1 duration:0];
1021 else if ([scroller_ respondsToSelector:@selector(_setZoomScale:duration:)])
1022 [scroller_ _setZoomScale:1 duration:0];
1023 /*else if ([scroller_ respondsToSelector:@selector(setZoomScale:animated:)])
1024 [scroller_ setZoomScale:1 animated:NO];*/
1025
1026 CGRect webrect = [scroller_ bounds];
1027 webrect.size.height = 0;
1028 [webview_ setFrame:webrect];
1029 }
1030
1031 [self reloadButtons];
1032 }
1033
1034 - (void) _finishLoading {
1035 size_t count([loading_ count]);
1036 if (count == 0)
1037 [self autorelease];
1038 if (reloading_ || count != 0)
1039 return;
1040 if (finish_ != nil)
1041 [self callFunction:finish_];
1042 [self reloadButtons];
1043 }
1044
1045 - (bool) isLoading {
1046 return [loading_ count] != 0;
1047 }
1048
1049 - (void) reloadButtons {
1050 if ([self isLoading])
1051 [indicator_ startAnimation];
1052 else
1053 [indicator_ stopAnimation];
1054 [super reloadButtons];
1055 }
1056
1057 - (BOOL) webView:(WebView *)sender shouldScrollToPoint:(struct CGPoint)point forFrame:(WebFrame *)frame {
1058 return [webview_ webView:sender shouldScrollToPoint:point forFrame:frame];
1059 }
1060
1061 - (void) webView:(WebView *)sender didReceiveViewportArguments:(id)arguments forFrame:(WebFrame *)frame {
1062 return [webview_ webView:sender didReceiveViewportArguments:arguments forFrame:frame];
1063 }
1064
1065 - (void) webView:(WebView *)sender needsScrollNotifications:(id)notifications forFrame:(WebFrame *)frame {
1066 return [webview_ webView:sender needsScrollNotifications:notifications forFrame:frame];
1067 }
1068
1069 - (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {
1070 [self _pushPage];
1071 return [webview_ webView:sender didCommitLoadForFrame:frame];
1072 }
1073
1074 - (void) webView:(WebView *)sender didReceiveDocTypeForFrame:(WebFrame *)frame {
1075 return [webview_ webView:sender didReceiveDocTypeForFrame:frame];
1076 }
1077
1078 - (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
1079 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
1080 [self _finishLoading];
1081
1082 if ([frame parentFrame] == nil) {
1083 if (DOMDocument *document = [frame DOMDocument])
1084 if (DOMNodeList<NSFastEnumeration> *bodies = [document getElementsByTagName:@"body"])
1085 for (DOMHTMLBodyElement *body in bodies) {
1086 DOMCSSStyleDeclaration *style([document getComputedStyle:body pseudoElement:nil]);
1087
1088 bool colored(false);
1089
1090 if (DOMCSSPrimitiveValue *color = static_cast<DOMCSSPrimitiveValue *>([style getPropertyCSSValue:@"background-color"])) {
1091 if ([color primitiveType] == DOM_CSS_RGBCOLOR) {
1092 DOMRGBColor *rgb([color getRGBColorValue]);
1093
1094 float red([[rgb red] getFloatValue:DOM_CSS_NUMBER]);
1095 float green([[rgb green] getFloatValue:DOM_CSS_NUMBER]);
1096 float blue([[rgb blue] getFloatValue:DOM_CSS_NUMBER]);
1097 float alpha([[rgb alpha] getFloatValue:DOM_CSS_NUMBER]);
1098
1099 UIColor *uic(nil);
1100
1101 if (red == 0xc7 && green == 0xce && blue == 0xd5)
1102 uic = [UIColor pinStripeColor];
1103 else if (alpha != 0)
1104 uic = [UIColor
1105 colorWithRed:(red / 255)
1106 green:(green / 255)
1107 blue:(blue / 255)
1108 alpha:alpha
1109 ];
1110
1111 if (uic != nil) {
1112 colored = true;
1113 [scroller_ setBackgroundColor:uic];
1114 }
1115 }
1116 }
1117
1118 if (!colored)
1119 [scroller_ setBackgroundColor:[UIColor pinStripeColor]];
1120 break;
1121 }
1122 }
1123
1124 return [webview_ webView:sender didFinishLoadForFrame:frame];
1125 }
1126
1127 - (void) _didFailWithError:(NSError *)error forFrame:(WebFrame *)frame {
1128 if ([frame parentFrame] == nil)
1129 [self autorelease];
1130
1131 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
1132 [self _finishLoading];
1133
1134 if (reloading_)
1135 return;
1136
1137 if ([frame parentFrame] == nil) {
1138 [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@",
1139 [[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"error" ofType:@"html"]] absoluteString],
1140 [[error localizedDescription] stringByAddingPercentEscapes]
1141 ]]];
1142
1143 error_ = true;
1144 }
1145 }
1146
1147 - (void) webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
1148 [self _didFailWithError:error forFrame:frame];
1149 }
1150
1151 - (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
1152 [self _didFailWithError:error forFrame:frame];
1153 }
1154
1155 - (void) webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary {
1156 #if LogBrowser || ForSaurik
1157 lprintf("Console:%s\n", [[dictionary description] UTF8String]);
1158 #endif
1159 }
1160
1161 /* XXX: fix this stupid include file
1162 - (void) webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)database {
1163 [origin setQuota:0x500000];
1164 }*/
1165
1166 - (void) _setTileDrawingEnabled:(BOOL)enabled {
1167 //[webview_ setTileDrawingEnabled:enabled];
1168 }
1169
1170 - (void) setViewportWidth:(float)width {
1171 width_ = width ? width != 0 : [[self class] defaultWidth];
1172 [webview_ setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
1173 }
1174
1175 - (void) willStartGesturesInView:(UIView *)view forEvent:(GSEventRef)event {
1176 [self _setTileDrawingEnabled:NO];
1177 }
1178
1179 - (void) didFinishGesturesInView:(UIView *)view forEvent:(GSEventRef)event {
1180 [self _setTileDrawingEnabled:YES];
1181 [webview_ redrawScaledDocument];
1182 }
1183
1184 - (void) scrollerWillStartDragging:(UIScroller *)scroller {
1185 [self _setTileDrawingEnabled:NO];
1186 }
1187
1188 - (void) scrollerDidEndDragging:(UIScroller *)scroller willSmoothScroll:(BOOL)smooth {
1189 [self _setTileDrawingEnabled:YES];
1190 }
1191
1192 - (void) scrollerDidEndDragging:(UIScroller *)scroller {
1193 [self _setTileDrawingEnabled:YES];
1194 }
1195
1196 - (id) initWithBook:(RVBook *)book forWidth:(float)width ofClass:(Class)_class {
1197 if ((self = [super initWithBook:book]) != nil) {
1198 class_ = _class;
1199 loading_ = [[NSMutableSet alloc] initWithCapacity:3];
1200 popup_ = false;
1201
1202 struct CGRect bounds = [self bounds];
1203
1204 scroller_ = [[UIScroller alloc] initWithFrame:bounds];
1205 [self addSubview:scroller_];
1206
1207 [scroller_ setFixedBackgroundPattern:YES];
1208 [scroller_ setBackgroundColor:[UIColor pinStripeColor]];
1209
1210 [scroller_ setScrollingEnabled:YES];
1211 [scroller_ setClipsSubviews:YES];
1212 [scroller_ setAllowsRubberBanding:YES];
1213
1214 [scroller_ setDelegate:self];
1215 [scroller_ setBounces:YES];
1216 [scroller_ setScrollHysteresis:8];
1217 [scroller_ setThumbDetectionEnabled:NO];
1218 [scroller_ setDirectionalScrolling:YES];
1219 [scroller_ setScrollDecelerationFactor:0.99]; /* 0.989324 */
1220 [scroller_ setEventMode:YES];
1221 [scroller_ setShowBackgroundShadow:NO]; /* YES */
1222 [scroller_ setAllowsRubberBanding:YES]; /* Vertical */
1223 [scroller_ setAdjustForContentSizeChange:YES]; /* NO */
1224
1225 CGRect webrect = [scroller_ bounds];
1226 webrect.size.height = 0;
1227
1228 WebView *webview;
1229
1230 WebThreadLock();
1231
1232 #if RecycleWebViews
1233 webview_ = [Documents_ lastObject];
1234 if (webview_ != nil) {
1235 webview_ = [webview_ retain];
1236 webview = [webview_ webView];
1237 [Documents_ removeLastObject];
1238 [webview_ setFrame:webrect];
1239 } else {
1240 #else
1241 if (true) {
1242 #endif
1243 webview_ = [[UIWebDocumentView alloc] initWithFrame:webrect];
1244 webview = [webview_ webView];
1245
1246 // XXX: this is terribly (too?) expensive
1247 //[webview_ setDrawsBackground:NO];
1248 [webview setPreferencesIdentifier:@"Cydia"];
1249
1250 [webview_ setTileSize:CGSizeMake(webrect.size.width, 500)];
1251
1252 if ([webview_ respondsToSelector:@selector(enableReachability)])
1253 [webview_ enableReachability];
1254
1255 [webview_ setAllowsMessaging:YES];
1256
1257 if ([webview_ respondsToSelector:@selector(useSelectionAssistantWithMode:)])
1258 [webview_ useSelectionAssistantWithMode:0];
1259
1260 [webview_ setTilingEnabled:YES];
1261 [webview_ setDrawsGrid:NO];
1262 [webview_ setLogsTilingChanges:NO];
1263 [webview_ setTileMinificationFilter:kCAFilterNearest];
1264
1265 if ([webview_ respondsToSelector:@selector(setDataDetectorTypes:)])
1266 /* XXX: abstractify */
1267 [webview_ setDataDetectorTypes:0x80000000];
1268 else
1269 [webview_ setDetectsPhoneNumbers:NO];
1270
1271 [webview_ setAutoresizes:YES];
1272
1273 [webview_ setMinimumScale:0.25f forDocumentTypes:0x10];
1274 [webview_ setMaximumScale:5.00f forDocumentTypes:0x10];
1275 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x10];
1276 //[webview_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
1277
1278 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x2];
1279
1280 [webview_ setMinimumScale:1.00f forDocumentTypes:0x8];
1281 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x8];
1282 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x8];
1283
1284 [webview_ _setDocumentType:0x4];
1285
1286 if ([webview_ respondsToSelector:@selector(UIWebDocumentView:)])
1287 [webview_ setZoomsFocusedFormControl:YES];
1288 [webview_ setContentsPosition:7];
1289 [webview_ setEnabledGestures:0xa];
1290 [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeIsZoomRubberBandEnabled];
1291 [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeUpdatesScroller];
1292
1293 [webview_ setSmoothsFonts:YES];
1294 [webview_ setAllowsImageSheet:YES];
1295 [webview _setUsesLoaderCache:YES];
1296
1297 [webview setGroupName:@"CydiaGroup"];
1298
1299 WebPreferences *preferences([webview preferences]);
1300
1301 if ([webview respondsToSelector:@selector(_setLayoutInterval:)])
1302 [webview _setLayoutInterval:0];
1303 else
1304 [preferences _setLayoutInterval:0];
1305 }
1306
1307 [self setViewportWidth:width];
1308
1309 [webview_ setDelegate:self];
1310 [webview_ setGestureDelegate:self];
1311 [webview_ setFormEditingDelegate:self];
1312 [webview_ setInteractionDelegate:self];
1313
1314 [scroller_ addSubview:webview_];
1315
1316 //NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
1317
1318 indirect_ = [[IndirectDelegate alloc] initWithDelegate:self];
1319
1320 [webview setFrameLoadDelegate:indirect_];
1321 [webview setPolicyDelegate:indirect_];
1322 [webview setResourceLoadDelegate:indirect_];
1323 [webview setUIDelegate:indirect_];
1324
1325 /* XXX: do not turn this on under penalty of extreme pain */
1326 [webview setScriptDebugDelegate:nil];
1327
1328 WebThreadUnlock();
1329
1330 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:UIProgressIndicatorStyleMediumWhite];
1331 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 12, indsize.width, indsize.height)];
1332 [indicator_ setStyle:UIProgressIndicatorStyleMediumWhite];
1333
1334 [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
1335 [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
1336
1337 /*UIWebView *test([[[UIWebView alloc] initWithFrame:[self bounds]] autorelease]);
1338 [test loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.saurik.com/"]]];
1339 [self addSubview:test];*/
1340 } return self;
1341 }
1342
1343 - (id) initWithBook:(RVBook *)book forWidth:(float)width {
1344 return [self initWithBook:book forWidth:width ofClass:[self class]];
1345 }
1346
1347 - (id) initWithBook:(RVBook *)book {
1348 return [self initWithBook:book forWidth:0];
1349 }
1350
1351 - (NSString *) stringByEvaluatingJavaScriptFromString:(NSString *)script {
1352 WebThreadLock();
1353 WebView *webview([webview_ webView]);
1354 NSString *string([webview stringByEvaluatingJavaScriptFromString:script]);
1355 WebThreadUnlock();
1356 return string;
1357 }
1358
1359 - (void) callFunction:(WebScriptObject *)function {
1360 WebThreadLock();
1361
1362 WebView *webview([webview_ webView]);
1363 WebFrame *frame([webview mainFrame]);
1364
1365 id _private(MSHookIvar<id>(webview, "_private"));
1366 WebCore::Page *page(_private == nil ? NULL : MSHookIvar<WebCore::Page *>(_private, "page"));
1367 WebCore::Settings *settings(page == NULL ? NULL : page->settings());
1368
1369 bool no;
1370 if (settings == NULL)
1371 no = 0;
1372 else {
1373 no = settings->JavaScriptCanOpenWindowsAutomatically();
1374 settings->setJavaScriptCanOpenWindowsAutomatically(true);
1375 }
1376
1377 if (UIWindow *window = [self window])
1378 if (UIResponder *responder = [window firstResponder])
1379 [responder resignFirstResponder];
1380
1381 JSObjectRef object([function JSObject]);
1382 JSGlobalContextRef context([frame globalContext]);
1383 JSObjectCallAsFunction(context, object, NULL, 0, NULL, NULL);
1384
1385 if (settings != NULL)
1386 settings->setJavaScriptCanOpenWindowsAutomatically(no);
1387
1388 WebThreadUnlock();
1389 }
1390
1391 - (void) didCloseBook:(RVBook *)book {
1392 if (closer_ != nil)
1393 [self callFunction:closer_];
1394 }
1395
1396 - (void) __rightButtonClicked {
1397 reloading_ = true;
1398 [self reloadURL];
1399 }
1400
1401 - (void) _rightButtonClicked {
1402 #if !AlwaysReload
1403 if (function_ != nil)
1404 [self callFunction:function_];
1405 else
1406 #endif
1407 [self __rightButtonClicked];
1408 }
1409
1410 - (id) _rightButtonTitle {
1411 return UCLocalize("RELOAD");
1412 }
1413
1414 - (id) rightButtonTitle {
1415 return [self isLoading] ? @"" : button_ != nil ? button_ : [self _rightButtonTitle];
1416 }
1417
1418 - (UINavigationButtonStyle) rightButtonStyle {
1419 if (style_ == nil) normal:
1420 return UINavigationButtonStyleNormal;
1421 else if ([style_ isEqualToString:@"Normal"])
1422 return UINavigationButtonStyleNormal;
1423 else if ([style_ isEqualToString:@"Back"])
1424 return UINavigationButtonStyleBack;
1425 else if ([style_ isEqualToString:@"Highlighted"])
1426 return UINavigationButtonStyleHighlighted;
1427 else if ([style_ isEqualToString:@"Destructive"])
1428 return UINavigationButtonStyleDestructive;
1429 else goto normal;
1430 }
1431
1432 - (NSString *) title {
1433 return title_ == nil ? UCLocalize("LOADING") : title_;
1434 }
1435
1436 - (NSString *) backButtonTitle {
1437 return UCLocalize("BROWSER");
1438 }
1439
1440 - (void) setPageActive:(BOOL)active {
1441 if (!active)
1442 [indicator_ removeFromSuperview];
1443 else
1444 [[book_ navigationBar] addSubview:indicator_];
1445 }
1446
1447 - (void) resetViewAnimated:(BOOL)animated {
1448 }
1449
1450 - (void) setPushed:(bool)pushed {
1451 pushed_ = pushed;
1452 }
1453
1454 + (float) defaultWidth {
1455 return 980;
1456 }
1457
1458 @end