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