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