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