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