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