]> git.saurik.com Git - cydia.git/blame_incremental - UICaboodle/BrowserView.mm
Major modifications to ready for stability.
[cydia.git] / UICaboodle / BrowserView.mm
... / ...
CommitLineData
1#include <UICaboodle/BrowserView.h>
2#include <UICaboodle/UCLocalize.h>
3
4#import <QuartzCore/CALayer.h>
5// XXX: fix the minimum requirement
6extern 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
15static CFArrayRef (*$GSSystemCopyCapability)(CFStringRef);
16static 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