]> git.saurik.com Git - cydia.git/blame - UICaboodle/BrowserView.mm
Checkpoint before UICaboodle reorganzation.
[cydia.git] / UICaboodle / BrowserView.mm
CommitLineData
275d8115
JF
1#include <UICaboodle/BrowserView.h>
2#include <UICaboodle/UCLocalize.h>
43f3d7f6
JF
3
4#import <QuartzCore/CALayer.h>
5// XXX: fix the minimum requirement
6extern NSString * const kCAFilterNearest;
22f8bed9 7
caa427d1 8#include <WebCore/WebCoreThread.h>
ea173384 9#include <WebKit/WebPreferences-WebPrivate.h>
caa427d1 10
43f3d7f6
JF
11#include "substrate.h"
12
bfc87a4d
JF
13#define ForSaurik 1
14
327624b6
JF
15static CFArrayRef (*$GSSystemCopyCapability)(CFStringRef);
16static CFArrayRef (*$GSSystemGetCapability)(CFStringRef);
17
43f3d7f6
JF
18@interface NSString (UIKit)
19- (NSString *) stringByAddingPercentEscapes;
20@end
21
aa5d0de7 22/* Indirect Delegate {{{ */
caa427d1 23@interface IndirectDelegate : NSObject {
aa5d0de7
JF
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
caa427d1
JF
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
aa5d0de7 95- (BOOL) respondsToSelector:(SEL)sel {
caa427d1
JF
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];
aa5d0de7
JF
101}
102
103- (NSMethodSignature *) methodSignatureForSelector:(SEL)sel {
caa427d1
JF
104 if (NSMethodSignature *method = [super methodSignatureForSelector:sel])
105 return method;
106 //fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel));
aa5d0de7
JF
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
43f3d7f6 123@interface WebView (UICaboodle)
22f8bed9
JF
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
43f3d7f6 131@implementation WebScriptObject (UICaboodle)
caa427d1
JF
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
ea173384 147#define ShowInternals 0
bfc87a4d 148#define LogBrowser 1
ea173384
JF
149
150#define lprintf(args...) fprintf(stderr, args)
151
22f8bed9
JF
152@implementation BrowserView
153
1b1b3f4a 154#if ShowInternals
ea173384 155#include "UICaboodle/UCInternal.h"
22f8bed9
JF
156#endif
157
ea173384 158+ (void) _initialize {
ea173384
JF
159 [WebView enableWebThread];
160
161 WebPreferences *preferences([WebPreferences standardPreferences]);
162 [preferences setCacheModel:WebCacheModelDocumentBrowser];
163 [preferences setOfflineWebApplicationCacheEnabled:YES];
164
165 [WebPreferences _setInitialDefaultTextEncodingToSystemEncoding];
327624b6
JF
166
167 $GSSystemCopyCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemCopyCapability"));
168 $GSSystemGetCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemGetCapability"));
ea173384
JF
169}
170
22f8bed9 171- (void) dealloc {
12b59862 172#if LogBrowser
3e9c9e85
JF
173 NSLog(@"[BrowserView dealloc]");
174#endif
1b1b3f4a 175
22f8bed9
JF
176 if (challenge_ != nil)
177 [challenge_ release];
178
caa427d1
JF
179 WebThreadLock();
180
22f8bed9
JF
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
caa427d1 188 /* XXX: these are set by UIWebDocumentView
ea173384 189 [webview setDownloadDelegate:nil];
22f8bed9
JF
190 [webview _setFormDelegate:nil];
191 [webview _setUIKitDelegate:nil];
caa427d1
JF
192 [webview setEditingDelegate:nil];*/
193
194 /* XXX: no one sets this, ever
195 [webview setWebMailDelegate:nil];*/
22f8bed9
JF
196
197 [webview_ setDelegate:nil];
198 [webview_ setGestureDelegate:nil];
eb35c522
JF
199 [webview_ setFormEditingDelegate:nil];
200 [webview_ setInteractionDelegate:nil];
22f8bed9 201
caa427d1
JF
202 [indirect_ setDelegate:nil];
203
22f8bed9
JF
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
22f8bed9
JF
215 [indirect_ release];
216
caa427d1
JF
217 WebThreadUnlock();
218
22f8bed9
JF
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];
caa427d1
JF
227 if (finish_ != nil)
228 [finish_ release];
12b59862
JF
229 if (closer_ != nil)
230 [closer_ release];
caa427d1
JF
231 if (special_ != nil)
232 [special_ release];
22f8bed9
JF
233
234 [scroller_ release];
235 [indicator_ release];
236 if (confirm_ != nil)
237 [confirm_ release];
0dceb29b
JF
238 if (sensitive_ != nil)
239 [sensitive_ release];
22f8bed9
JF
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
22f8bed9
JF
257- (void) loadRequest:(NSURLRequest *)request {
258 pushed_ = true;
fe468f45 259 error_ = false;
caa427d1
JF
260
261 WebThreadLock();
22f8bed9 262 [webview_ loadRequest:request];
caa427d1 263 WebThreadUnlock();
22f8bed9
JF
264}
265
266- (void) reloadURL {
22f8bed9
JF
267 if (request_ == nil)
268 return;
269
270 if ([request_ HTTPBody] == nil && [request_ HTTPBodyStream] == nil)
fe468f45 271 [self loadRequest:request_];
22f8bed9
JF
272 else {
273 UIActionSheet *sheet = [[[UIActionSheet alloc]
43f3d7f6
JF
274 initWithTitle:UCLocalize("RESUBMIT_FORM")
275 buttons:[NSArray arrayWithObjects:UCLocalize("CANCEL"), UCLocalize("SUBMIT"), nil]
22f8bed9
JF
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
1b1b3f4a
JF
290- (UIWebDocumentView *) documentView {
291 return webview_;
292}
293
caa427d1
JF
294/* XXX: WebThreadLock? */
295- (void) _fixScroller:(CGRect)bounds {
eb35c522
JF
296 float extra;
297 if (!editing_)
298 extra = 0;
299 else {
300 UIFormAssistant *assistant([UIFormAssistant sharedFormAssistant]);
301 CGRect peripheral([assistant peripheralFrame]);
12b59862 302#if LogBrowser
eb35c522 303 NSLog(@"per:%f", peripheral.size.height);
2f3ef0b1 304#endif
eb35c522
JF
305 extra = peripheral.size.height;
306 }
307
308 CGRect subrect([scroller_ frame]);
309 subrect.size.height -= extra;
310 [scroller_ setScrollerIndicatorSubrect:subrect];
311
2f3ef0b1
JF
312 NSSize visible(NSMakeSize(subrect.size.width, subrect.size.height));
313 [webview_ setValue:[NSValue valueWithSize:visible] forGestureAttribute:UIGestureAttributeVisibleSize];
314
eb35c522
JF
315 CGSize size(size_);
316 size.height += extra;
317 [scroller_ setContentSize:size];
2f3ef0b1
JF
318
319 [scroller_ releaseRubberBandIfNecessary];
eb35c522
JF
320}
321
caa427d1
JF
322- (void) fixScroller {
323 CGRect bounds([webview_ documentBounds]);
7adf7539 324#if TrackResize
caa427d1
JF
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
22f8bed9 330- (void) view:(UIView *)sender didSetFrame:(CGRect)frame {
eb35c522 331 size_ = frame.size;
7adf7539 332#if TrackResize
2f3ef0b1
JF
333 NSLog(@"dsf:(%f,%f+%f,%f)", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
334#endif
caa427d1 335 [self _fixScroller:frame];
22f8bed9
JF
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 {
22f8bed9 343 [page setDelegate:delegate_];
988f99ac 344 [self setBackButtonTitle:title_];
1b1b3f4a 345 [book_ pushPage:page];
22f8bed9
JF
346}
347
bf26e5f3
JF
348- (void) _pushPage {
349 if (pushed_)
350 return;
caa427d1 351 // WTR: [self autorelease];
bf26e5f3
JF
352 pushed_ = true;
353 [book_ pushPage:self];
354}
355
2f3ef0b1
JF
356- (void) swapPage:(RVPage *)page {
357 [page setDelegate:delegate_];
358 if (pushed_)
359 [book_ swapPage:page];
360 else
361 [book_ pushPage:page];
362}
363
e124f522 364- (BOOL) getSpecial:(NSURL *)url swap:(BOOL)swap {
12b59862 365#if LogBrowser
bf26e5f3
JF
366 NSLog(@"getSpecial:%@", url);
367#endif
368
43f3d7f6 369 if (RVPage *page = [delegate_ pageForURL:url hasTag:NULL]) {
e124f522
JF
370 if (swap)
371 [self swapPage:page];
372 else
373 [self pushPage:page];
43f3d7f6
JF
374
375 return true;
376 } else
377 return false;
22f8bed9
JF
378}
379
ea173384
JF
380- (void) formAssistant:(id)sender didBeginEditingFormNode:(id)node {
381}
382
383- (void) formAssistant:(id)sender didEndEditingFormNode:(id)node {
384 [self fixScroller];
385}
386
1b1b3f4a 387- (void) webViewShow:(WebView *)sender {
e8389e3e 388 /* XXX: this is where I cry myself to sleep */
1b1b3f4a
JF
389}
390
3e9c9e85
JF
391- (bool) _allowJavaScriptPanel {
392 return true;
393}
394
0dceb29b 395- (bool) allowSensitiveRequests {
43f3d7f6 396 return [self _allowJavaScriptPanel];
0dceb29b
JF
397}
398
399- (void) _promptForSensitive:(NSMutableArray *)array {
400 NSString *name([array objectAtIndex:0]);
401
402 UIActionSheet *sheet = [[[UIActionSheet alloc]
403 initWithTitle:nil
43f3d7f6 404 buttons:[NSArray arrayWithObjects:UCLocalize("YES"), UCLocalize("NO"), nil]
0dceb29b
JF
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
22f8bed9 439- (void) webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
8f8f02e9 440 if (![self _allowJavaScriptPanel])
3e9c9e85 441 return;
7592e053 442 [self retain];
bd0a4099 443
22f8bed9
JF
444 UIActionSheet *sheet = [[[UIActionSheet alloc]
445 initWithTitle:nil
43f3d7f6 446 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil]
22f8bed9
JF
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 {
3e9c9e85
JF
457 if (![self _allowJavaScriptPanel])
458 return NO;
7592e053 459 [self retain];
3e9c9e85 460
22f8bed9
JF
461 UIActionSheet *sheet = [[[UIActionSheet alloc]
462 initWithTitle:nil
43f3d7f6 463 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), UCLocalize("CANCEL"), nil]
22f8bed9 464 defaultButtonIndex:0
bd0a4099 465 delegate:indirect_
22f8bed9
JF
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;
7592e053
JF
480
481 [self autorelease];
22f8bed9
JF
482 return [confirm boolValue];
483}
484
3e9c9e85
JF
485- (void) setAutoPopup:(BOOL)popup {
486 popup_ = popup;
487}
488
caa427d1
JF
489- (void) setSpecial:(id)function {
490 if (special_ != nil)
491 [special_ autorelease];
492 special_ = function == nil ? nil : [function retain];
12b59862
JF
493}
494
22f8bed9
JF
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];
12b59862
JF
507
508 [self reloadButtons];
22f8bed9
JF
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];
12b59862
JF
523
524 [self reloadButtons];
22f8bed9 525}
22f8bed9 526
caa427d1
JF
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
43f3d7f6 539- (void) _openMailToURL:(NSURL *)url {
43f3d7f6 540 [UIApp openURL:url];// asPanel:YES];
43f3d7f6
JF
541}
542
eb35c522
JF
543- (void) webView:(WebView *)sender willBeginEditingFormElement:(id)element {
544 editing_ = true;
545}
546
547- (void) webView:(WebView *)sender didBeginEditingFormElement:(id)element {
caa427d1 548 [self fixScroller];
eb35c522
JF
549}
550
551- (void) webViewDidEndEditingFormElements:(WebView *)sender {
552 editing_ = false;
caa427d1 553 [self fixScroller];
eb35c522
JF
554}
555
aa5d0de7
JF
556- (void) webViewClose:(WebView *)sender {
557 [book_ close];
558}
559
e590d1ff
JF
560- (void) close {
561 [book_ close];
562}
563
22f8bed9 564- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
22f8bed9
JF
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 {
12b59862 572#if LogBrowser
1b1b3f4a 573 NSLog(@"nwa:%@", name);
3e9c9e85 574#endif
1b1b3f4a 575
22f8bed9 576 if (NSURL *url = [request URL]) {
aa5d0de7 577 if (name == nil) unknown: {
e124f522 578 if (![self getSpecial:url swap:NO]) {
aa5d0de7
JF
579 NSString *scheme([[url scheme] lowercaseString]);
580 if ([scheme isEqualToString:@"mailto"])
43f3d7f6 581 [self _openMailToURL:url];
aa5d0de7
JF
582 else goto use;
583 }
584 } else if ([name isEqualToString:@"_open"])
22f8bed9 585 [delegate_ openURL:url];
aa5d0de7 586 else if ([name isEqualToString:@"_popup"]) {
d8ac46da
JF
587 NSString *scheme([[url scheme] lowercaseString]);
588 if ([scheme isEqualToString:@"mailto"])
43f3d7f6 589 [self _openMailToURL:url];
d8ac46da
JF
590 else {
591 RVBook *book([[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
592 [book setHook:indirect_];
aa5d0de7 593
d8ac46da
JF
594 RVPage *page([delegate_ pageForURL:url hasTag:NULL]);
595 if (page == nil) {
596 /* XXX: call createWebViewWithRequest instead? */
1b1b3f4a 597
d8ac46da 598 [self setBackButtonTitle:title_];
1b1b3f4a 599
245cce8a 600 BrowserView *browser([[[class_ alloc] initWithBook:book] autorelease]);
d8ac46da
JF
601 [browser loadURL:url];
602 page = browser;
603 }
22f8bed9 604
d8ac46da
JF
605 [book setDelegate:delegate_];
606 [page setDelegate:delegate_];
00e2109e 607
d8ac46da
JF
608 [book setPage:page];
609 [book_ pushBook:book];
610 }
aa5d0de7 611 } else goto unknown;
22f8bed9
JF
612
613 [listener ignore];
614 } else use:
615 [listener use];
616}
617
2f3ef0b1 618- (void) webView:(WebView *)sender decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
22f8bed9
JF
619 if ([WebView canShowMIMEType:type])
620 [listener use];
621 else {
622 // XXX: handle more mime types!
623 [listener ignore];
2f3ef0b1
JF
624
625 WebView *webview([webview_ webView]);
626 if (frame == [webview mainFrame])
22f8bed9
JF
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]);
327624b6 638 NSString *host([url host]);
22f8bed9
JF
639
640 if (url == nil) use: {
fe468f45 641 if (!error_ && [frame parentFrame] == nil) {
22f8bed9
JF
642 if (request_ != nil)
643 [request_ autorelease];
644 request_ = [request retain];
12b59862 645#if LogBrowser
22f8bed9 646 NSLog(@"dpn:%@", request_);
aa5d0de7 647#endif
22f8bed9
JF
648 }
649
650 [listener use];
2f3ef0b1
JF
651
652 WebView *webview([webview_ webView]);
653 if (frame == [webview mainFrame])
654 [self _pushPage];
22f8bed9
JF
655 return;
656 }
12b59862 657#if LogBrowser
22f8bed9
JF
658 else NSLog(@"nav:%@:%@", url, [action description]);
659#endif
660
caa427d1
JF
661 const NSArray *capability;
662
327624b6
JF
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);
22f8bed9 672
caa427d1 673 if (capability != nil && (
327624b6
JF
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
caa427d1 677 )) {
327624b6 678 url = open;
22f8bed9
JF
679 open:
680 [UIApp openURL:url];
681 goto ignore;
682 }
683
684 int store(_not(int));
685 if (NSURL *itms = [url itmsURL:&store]) {
12b59862 686#if LogBrowser
22f8bed9 687 NSLog(@"itms#%@#%u#%@", url, store, itms);
3e9c9e85
JF
688#endif
689
caa427d1 690 if (capability != nil && (
22f8bed9
JF
691 store == 1 && [capability containsObject:@"com.apple.MobileStore"] ||
692 store == 2 && [capability containsObject:@"com.apple.AppStore"]
caa427d1 693 )) {
22f8bed9
JF
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"]) {
43f3d7f6 707 [self _openMailToURL:url];
22f8bed9
JF
708 goto ignore;
709 }
710
e124f522 711 if ([self getSpecial:url swap:YES])
22f8bed9
JF
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
22f8bed9
JF
725- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
726 NSString *context([sheet context]);
727
bd0a4099
JF
728 if ([context isEqualToString:@"alert"]) {
729 [self autorelease];
22f8bed9 730 [sheet dismiss];
bd0a4099 731 } else if ([context isEqualToString:@"confirm"]) {
22f8bed9
JF
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
0dceb29b
JF
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
22f8bed9
JF
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 default:
773 _assert(false);
774 }
775
776 [challenge_ release];
777 challenge_ = nil;
778
779 [sheet dismiss];
780 } else if ([context isEqualToString:@"submit"]) {
781 switch (button) {
782 case 1:
783 break;
784
785 case 2:
caa427d1
JF
786 if (request_ != nil) {
787 WebThreadLock();
22f8bed9 788 [webview_ loadRequest:request_];
caa427d1
JF
789 WebThreadUnlock();
790 }
22f8bed9
JF
791 break;
792
793 default:
794 _assert(false);
795 }
796
797 [sheet dismiss];
798 }
799}
800
801- (void) webView:(WebView *)sender resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)source {
802 challenge_ = [challenge retain];
803
804 NSURLProtectionSpace *space([challenge protectionSpace]);
805 NSString *realm([space realm]);
806 if (realm == nil)
807 realm = @"";
808
809 UIActionSheet *sheet = [[[UIActionSheet alloc]
810 initWithTitle:realm
43f3d7f6 811 buttons:[NSArray arrayWithObjects:UCLocalize("LOGIN"), UCLocalize("CANCEL"), nil]
22f8bed9
JF
812 defaultButtonIndex:0
813 delegate:self
814 context:@"challenge"
815 ] autorelease];
816
817 [sheet setNumberOfRows:1];
818
43f3d7f6
JF
819 [sheet addTextFieldWithValue:@"" label:UCLocalize("USERNAME")];
820 [sheet addTextFieldWithValue:@"" label:UCLocalize("PASSWORD")];
22f8bed9
JF
821
822 UITextField *username([sheet textFieldAtIndex:0]); {
823 UITextInputTraits *traits([username textInputTraits]);
824 [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
825 [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
826 [traits setKeyboardType:UIKeyboardTypeASCIICapable];
827 [traits setReturnKeyType:UIReturnKeyNext];
828 }
829
830 UITextField *password([sheet textFieldAtIndex:1]); {
831 UITextInputTraits *traits([password textInputTraits]);
832 [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
833 [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
834 [traits setKeyboardType:UIKeyboardTypeASCIICapable];
835 // XXX: UIReturnKeyDone
836 [traits setReturnKeyType:UIReturnKeyNext];
837 [traits setSecureTextEntry:YES];
838 }
839
840 [sheet popupAlertAnimated:YES];
841}
842
843- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
43f3d7f6 844 return request;
22f8bed9
JF
845}
846
1b1b3f4a 847- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features {
3e9c9e85 848//- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request userGesture:(BOOL)gesture {
12b59862 849#if LogBrowser
3e9c9e85
JF
850 NSLog(@"cwv:%@ (%@): %@", request, title_, features == nil ? @"{}" : [features description]);
851 //NSLog(@"cwv:%@ (%@): %@", request, title_, gesture ? @"Yes" : @"No");
1b1b3f4a 852#endif
22f8bed9 853
3e9c9e85 854 NSNumber *value([features objectForKey:@"width"]);
2f3ef0b1 855 float width(value == nil ? 0 : [value floatValue]);
3e9c9e85
JF
856
857 RVBook *book(!popup_ ? book_ : [[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
858
859 /* XXX: deal with cydia:// pages */
245cce8a 860 BrowserView *browser([[[class_ alloc] initWithBook:book forWidth:width] autorelease]);
3e9c9e85 861
bd0a4099 862 if (features != nil && popup_) {
3e9c9e85 863 [book setDelegate:delegate_];
12b59862 864 [book setHook:indirect_];
3e9c9e85
JF
865 [browser setDelegate:delegate_];
866
867 [browser loadRequest:request];
bf26e5f3 868
3e9c9e85
JF
869 [book setPage:browser];
870 [book_ pushBook:book];
871 } else if (request == nil) {
bf26e5f3
JF
872 [self setBackButtonTitle:title_];
873 [browser setDelegate:delegate_];
874 [browser retain];
875 } else {
876 [self pushPage:browser];
877 [browser loadRequest:request];
878 }
879
22f8bed9
JF
880 return [browser webView];
881}
882
883- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
1b1b3f4a 884 return [self webView:sender createWebViewWithRequest:request windowFeatures:nil];
3e9c9e85 885 //return [self webView:sender createWebViewWithRequest:request userGesture:YES];
22f8bed9
JF
886}
887
888- (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
889 if ([frame parentFrame] != nil)
890 return;
891
892 title_ = [title retain];
893 [book_ reloadTitleForPage:self];
894}
895
896- (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
bfc87a4d
JF
897 /*if ([loading_ count] == 0)
898 [self retain];*/
7592e053 899 [loading_ addObject:[NSValue valueWithNonretainedObject:frame]];
22f8bed9 900
caa427d1
JF
901 if ([frame parentFrame] == nil) {
902 [webview_ resignFirstResponder];
2f3ef0b1 903
caa427d1 904 reloading_ = false;
22f8bed9 905
caa427d1
JF
906 if (title_ != nil) {
907 [title_ release];
908 title_ = nil;
909 }
22f8bed9 910
caa427d1
JF
911 if (button_ != nil) {
912 [button_ release];
913 button_ = nil;
914 }
22f8bed9 915
caa427d1
JF
916 if (style_ != nil) {
917 [style_ release];
918 style_ = nil;
919 }
22f8bed9 920
caa427d1
JF
921 if (function_ != nil) {
922 [function_ release];
923 function_ = nil;
924 }
22f8bed9 925
caa427d1
JF
926 if (finish_ != nil) {
927 [finish_ release];
928 finish_ = nil;
929 }
12b59862 930
caa427d1
JF
931 if (closer_ != nil) {
932 [closer_ release];
933 closer_ = nil;
934 }
935
936 if (special_ != nil) {
937 [special_ release];
938 special_ = nil;
939 }
22f8bed9 940
caa427d1
JF
941 [book_ reloadTitleForPage:self];
942
943 [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
944
945 if ([scroller_ respondsToSelector:@selector(setZoomScale:duration:)])
946 [scroller_ setZoomScale:1 duration:0];
fa333ece
JF
947 else if ([scroller_ respondsToSelector:@selector(_setZoomScale:duration:)])
948 [scroller_ _setZoomScale:1 duration:0];
949 /*else if ([scroller_ respondsToSelector:@selector(setZoomScale:animated:)])
950 [scroller_ setZoomScale:1 animated:NO];*/
22f8bed9 951
caa427d1
JF
952 CGRect webrect = [scroller_ bounds];
953 webrect.size.height = 0;
954 [webview_ setFrame:webrect];
955 }
956
957 [self reloadButtons];
22f8bed9
JF
958}
959
960- (void) _finishLoading {
7592e053 961 size_t count([loading_ count]);
bfc87a4d
JF
962 /*if (count == 0)
963 [self autorelease];*/
7592e053 964 if (reloading_ || count != 0)
caa427d1
JF
965 return;
966 if (finish_ != nil)
967 [self callFunction:finish_];
968 [self reloadButtons];
22f8bed9
JF
969}
970
12b59862 971- (bool) isLoading {
caa427d1 972 return [loading_ count] != 0;
22f8bed9
JF
973}
974
975- (void) reloadButtons {
12b59862 976 if ([self isLoading])
22f8bed9
JF
977 [indicator_ startAnimation];
978 else
979 [indicator_ stopAnimation];
980 [super reloadButtons];
981}
982
983- (BOOL) webView:(WebView *)sender shouldScrollToPoint:(struct CGPoint)point forFrame:(WebFrame *)frame {
984 return [webview_ webView:sender shouldScrollToPoint:point forFrame:frame];
985}
986
987- (void) webView:(WebView *)sender didReceiveViewportArguments:(id)arguments forFrame:(WebFrame *)frame {
988 return [webview_ webView:sender didReceiveViewportArguments:arguments forFrame:frame];
989}
990
991- (void) webView:(WebView *)sender needsScrollNotifications:(id)notifications forFrame:(WebFrame *)frame {
992 return [webview_ webView:sender needsScrollNotifications:notifications forFrame:frame];
993}
994
995- (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {
4fbb376e 996 [self _pushPage];
22f8bed9
JF
997 return [webview_ webView:sender didCommitLoadForFrame:frame];
998}
999
1000- (void) webView:(WebView *)sender didReceiveDocTypeForFrame:(WebFrame *)frame {
1001 return [webview_ webView:sender didReceiveDocTypeForFrame:frame];
1002}
1003
1004- (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
7592e053 1005 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
caa427d1 1006 [self _finishLoading];
22f8bed9 1007
caa427d1 1008 if ([frame parentFrame] == nil) {
22f8bed9
JF
1009 if (DOMDocument *document = [frame DOMDocument])
1010 if (DOMNodeList<NSFastEnumeration> *bodies = [document getElementsByTagName:@"body"])
1011 for (DOMHTMLBodyElement *body in bodies) {
1012 DOMCSSStyleDeclaration *style([document getComputedStyle:body pseudoElement:nil]);
1013
1014 bool colored(false);
1015
1016 if (DOMCSSPrimitiveValue *color = static_cast<DOMCSSPrimitiveValue *>([style getPropertyCSSValue:@"background-color"])) {
fe468f45
JF
1017 if ([color primitiveType] == DOM_CSS_RGBCOLOR) {
1018 DOMRGBColor *rgb([color getRGBColorValue]);
1019
1020 float red([[rgb red] getFloatValue:DOM_CSS_NUMBER]);
1021 float green([[rgb green] getFloatValue:DOM_CSS_NUMBER]);
1022 float blue([[rgb blue] getFloatValue:DOM_CSS_NUMBER]);
1023 float alpha([[rgb alpha] getFloatValue:DOM_CSS_NUMBER]);
1024
1025 UIColor *uic(nil);
1026
1027 if (red == 0xc7 && green == 0xce && blue == 0xd5)
1028 uic = [UIColor pinStripeColor];
1029 else if (alpha != 0)
1030 uic = [UIColor
1031 colorWithRed:(red / 255)
1032 green:(green / 255)
1033 blue:(blue / 255)
1034 alpha:alpha
1035 ];
1036
1037 if (uic != nil) {
1038 colored = true;
1039 [scroller_ setBackgroundColor:uic];
1040 }
22f8bed9
JF
1041 }
1042 }
1043
1044 if (!colored)
1045 [scroller_ setBackgroundColor:[UIColor pinStripeColor]];
1046 break;
1047 }
1048 }
1049
1050 return [webview_ webView:sender didFinishLoadForFrame:frame];
1051}
1052
caa427d1 1053- (void) _didFailWithError:(NSError *)error forFrame:(WebFrame *)frame {
bfc87a4d
JF
1054 _trace();
1055 /*if ([frame parentFrame] == nil)
1056 [self autorelease];*/
caa427d1 1057
7592e053 1058 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
22f8bed9
JF
1059 [self _finishLoading];
1060
7592e053
JF
1061 if (reloading_)
1062 return;
1063
caa427d1
JF
1064 if ([frame parentFrame] == nil) {
1065 [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@",
1066 [[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"error" ofType:@"html"]] absoluteString],
1067 [[error localizedDescription] stringByAddingPercentEscapes]
1068 ]]];
1069
1070 error_ = true;
1071 }
1072}
fe468f45 1073
caa427d1
JF
1074- (void) webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
1075 [self _didFailWithError:error forFrame:frame];
1076}
1077
1078- (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
1079 [self _didFailWithError:error forFrame:frame];
22f8bed9
JF
1080}
1081
1082- (void) webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary {
12b59862 1083#if LogBrowser || ForSaurik
22f8bed9
JF
1084 lprintf("Console:%s\n", [[dictionary description] UTF8String]);
1085#endif
1086}
1087
caa427d1
JF
1088/* XXX: fix this stupid include file
1089- (void) webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)database {
1090 [origin setQuota:0x500000];
1091}*/
1092
1093- (void) _setTileDrawingEnabled:(BOOL)enabled {
1094 //[webview_ setTileDrawingEnabled:enabled];
1095}
1096
eb35c522 1097- (void) setViewportWidth:(float)width {
35bf217f 1098 width_ = width != 0 ? width : [[self class] defaultWidth];
eb35c522
JF
1099 [webview_ setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
1100}
1101
caa427d1
JF
1102- (void) willStartGesturesInView:(UIView *)view forEvent:(GSEventRef)event {
1103 [self _setTileDrawingEnabled:NO];
1104}
1105
1106- (void) didFinishGesturesInView:(UIView *)view forEvent:(GSEventRef)event {
1107 [self _setTileDrawingEnabled:YES];
1108 [webview_ redrawScaledDocument];
1109}
1110
1111- (void) scrollerWillStartDragging:(UIScroller *)scroller {
1112 [self _setTileDrawingEnabled:NO];
1113}
1114
1115- (void) scrollerDidEndDragging:(UIScroller *)scroller willSmoothScroll:(BOOL)smooth {
1116 [self _setTileDrawingEnabled:YES];
1117}
1118
1119- (void) scrollerDidEndDragging:(UIScroller *)scroller {
1120 [self _setTileDrawingEnabled:YES];
1121}
1122
245cce8a 1123- (id) initWithBook:(RVBook *)book forWidth:(float)width ofClass:(Class)_class {
22f8bed9 1124 if ((self = [super initWithBook:book]) != nil) {
245cce8a 1125 class_ = _class;
caa427d1 1126 loading_ = [[NSMutableSet alloc] initWithCapacity:3];
3e9c9e85 1127 popup_ = false;
22f8bed9
JF
1128
1129 struct CGRect bounds = [self bounds];
1130
1131 scroller_ = [[UIScroller alloc] initWithFrame:bounds];
1132 [self addSubview:scroller_];
1133
22f8bed9
JF
1134 [scroller_ setFixedBackgroundPattern:YES];
1135 [scroller_ setBackgroundColor:[UIColor pinStripeColor]];
1136
1137 [scroller_ setScrollingEnabled:YES];
22f8bed9
JF
1138 [scroller_ setClipsSubviews:YES];
1139 [scroller_ setAllowsRubberBanding:YES];
caa427d1 1140
22f8bed9 1141 [scroller_ setDelegate:self];
caa427d1
JF
1142 [scroller_ setBounces:YES];
1143 [scroller_ setScrollHysteresis:8];
1144 [scroller_ setThumbDetectionEnabled:NO];
1145 [scroller_ setDirectionalScrolling:YES];
1146 [scroller_ setScrollDecelerationFactor:0.99]; /* 0.989324 */
1147 [scroller_ setEventMode:YES];
1148 [scroller_ setShowBackgroundShadow:NO]; /* YES */
1149 [scroller_ setAllowsRubberBanding:YES]; /* Vertical */
1150 [scroller_ setAdjustForContentSizeChange:YES]; /* NO */
22f8bed9
JF
1151
1152 CGRect webrect = [scroller_ bounds];
1153 webrect.size.height = 0;
1154
1155 WebView *webview;
1156
caa427d1
JF
1157 WebThreadLock();
1158
22f8bed9
JF
1159#if RecycleWebViews
1160 webview_ = [Documents_ lastObject];
1161 if (webview_ != nil) {
1162 webview_ = [webview_ retain];
1163 webview = [webview_ webView];
1164 [Documents_ removeLastObject];
1165 [webview_ setFrame:webrect];
1166 } else {
1167#else
1168 if (true) {
1169#endif
1170 webview_ = [[UIWebDocumentView alloc] initWithFrame:webrect];
1171 webview = [webview_ webView];
1172
1173 // XXX: this is terribly (too?) expensive
1174 //[webview_ setDrawsBackground:NO];
1175 [webview setPreferencesIdentifier:@"Cydia"];
1176
1177 [webview_ setTileSize:CGSizeMake(webrect.size.width, 500)];
1178
ea173384
JF
1179 if ([webview_ respondsToSelector:@selector(enableReachability)])
1180 [webview_ enableReachability];
1181
22f8bed9
JF
1182 [webview_ setAllowsMessaging:YES];
1183
ea173384
JF
1184 if ([webview_ respondsToSelector:@selector(useSelectionAssistantWithMode:)])
1185 [webview_ useSelectionAssistantWithMode:0];
1186
22f8bed9
JF
1187 [webview_ setTilingEnabled:YES];
1188 [webview_ setDrawsGrid:NO];
1189 [webview_ setLogsTilingChanges:NO];
1190 [webview_ setTileMinificationFilter:kCAFilterNearest];
ea173384 1191
caa427d1
JF
1192 if ([webview_ respondsToSelector:@selector(setDataDetectorTypes:)])
1193 /* XXX: abstractify */
1194 [webview_ setDataDetectorTypes:0x80000000];
1195 else
1196 [webview_ setDetectsPhoneNumbers:NO];
ea173384 1197
22f8bed9
JF
1198 [webview_ setAutoresizes:YES];
1199
1200 [webview_ setMinimumScale:0.25f forDocumentTypes:0x10];
3e9c9e85 1201 [webview_ setMaximumScale:5.00f forDocumentTypes:0x10];
22f8bed9 1202 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x10];
3e9c9e85 1203 //[webview_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
22f8bed9
JF
1204
1205 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x2];
1206
3e9c9e85 1207 [webview_ setMinimumScale:1.00f forDocumentTypes:0x8];
22f8bed9
JF
1208 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x8];
1209 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x8];
1210
1211 [webview_ _setDocumentType:0x4];
1212
caa427d1
JF
1213 if ([webview_ respondsToSelector:@selector(UIWebDocumentView:)])
1214 [webview_ setZoomsFocusedFormControl:YES];
22f8bed9
JF
1215 [webview_ setContentsPosition:7];
1216 [webview_ setEnabledGestures:0xa];
1217 [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeIsZoomRubberBandEnabled];
1218 [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeUpdatesScroller];
1219
1220 [webview_ setSmoothsFonts:YES];
3e9c9e85 1221 [webview_ setAllowsImageSheet:YES];
22f8bed9 1222 [webview _setUsesLoaderCache:YES];
3e9c9e85
JF
1223
1224 [webview setGroupName:@"CydiaGroup"];
ea173384
JF
1225
1226 WebPreferences *preferences([webview preferences]);
1227
caa427d1
JF
1228 if ([webview respondsToSelector:@selector(_setLayoutInterval:)])
1229 [webview _setLayoutInterval:0];
ea173384
JF
1230 else
1231 [preferences _setLayoutInterval:0];
22f8bed9
JF
1232 }
1233
eb35c522 1234 [self setViewportWidth:width];
3e9c9e85 1235
22f8bed9
JF
1236 [webview_ setDelegate:self];
1237 [webview_ setGestureDelegate:self];
eb35c522
JF
1238 [webview_ setFormEditingDelegate:self];
1239 [webview_ setInteractionDelegate:self];
1240
22f8bed9
JF
1241 [scroller_ addSubview:webview_];
1242
1243 //NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
1244
22f8bed9
JF
1245 indirect_ = [[IndirectDelegate alloc] initWithDelegate:self];
1246
caa427d1 1247 [webview setFrameLoadDelegate:indirect_];
ea173384 1248 [webview setPolicyDelegate:indirect_];
22f8bed9 1249 [webview setResourceLoadDelegate:indirect_];
caa427d1 1250 [webview setUIDelegate:indirect_];
ea173384
JF
1251
1252 /* XXX: do not turn this on under penalty of extreme pain */
1253 [webview setScriptDebugDelegate:nil];
caa427d1
JF
1254
1255 WebThreadUnlock();
1256
1257 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:UIProgressIndicatorStyleMediumWhite];
1258 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 12, indsize.width, indsize.height)];
1259 [indicator_ setStyle:UIProgressIndicatorStyleMediumWhite];
22f8bed9
JF
1260
1261 [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
1262 [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
caa427d1
JF
1263
1264 /*UIWebView *test([[[UIWebView alloc] initWithFrame:[self bounds]] autorelease]);
1265 [test loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.saurik.com/"]]];
1266 [self addSubview:test];*/
22f8bed9
JF
1267 } return self;
1268}
1269
245cce8a
JF
1270- (id) initWithBook:(RVBook *)book forWidth:(float)width {
1271 return [self initWithBook:book forWidth:width ofClass:[self class]];
1272}
1273
3e9c9e85 1274- (id) initWithBook:(RVBook *)book {
2f3ef0b1 1275 return [self initWithBook:book forWidth:0];
3e9c9e85
JF
1276}
1277
caa427d1
JF
1278- (NSString *) stringByEvaluatingJavaScriptFromString:(NSString *)script {
1279 WebThreadLock();
1280 WebView *webview([webview_ webView]);
1281 NSString *string([webview stringByEvaluatingJavaScriptFromString:script]);
1282 WebThreadUnlock();
1283 return string;
22f8bed9
JF
1284}
1285
12b59862 1286- (void) callFunction:(WebScriptObject *)function {
caa427d1
JF
1287 WebThreadLock();
1288
12b59862
JF
1289 WebView *webview([webview_ webView]);
1290 WebFrame *frame([webview mainFrame]);
22f8bed9 1291
12b59862
JF
1292 id _private(MSHookIvar<id>(webview, "_private"));
1293 WebCore::Page *page(_private == nil ? NULL : MSHookIvar<WebCore::Page *>(_private, "page"));
1294 WebCore::Settings *settings(page == NULL ? NULL : page->settings());
22f8bed9 1295
12b59862
JF
1296 bool no;
1297 if (settings == NULL)
1298 no = 0;
1299 else {
1300 no = settings->JavaScriptCanOpenWindowsAutomatically();
1301 settings->setJavaScriptCanOpenWindowsAutomatically(true);
22f8bed9 1302 }
12b59862 1303
43f3d7f6
JF
1304 if (UIWindow *window = [self window])
1305 if (UIResponder *responder = [window firstResponder])
1306 [responder resignFirstResponder];
1307
12b59862
JF
1308 JSObjectRef object([function JSObject]);
1309 JSGlobalContextRef context([frame globalContext]);
1310 JSObjectCallAsFunction(context, object, NULL, 0, NULL, NULL);
1311
1312 if (settings != NULL)
caa427d1
JF
1313 settings->setJavaScriptCanOpenWindowsAutomatically(no);
1314
1315 WebThreadUnlock();
12b59862
JF
1316}
1317
1318- (void) didCloseBook:(RVBook *)book {
1319 if (closer_ != nil)
1320 [self callFunction:closer_];
1321}
1322
1323- (void) __rightButtonClicked {
1324 reloading_ = true;
1325 [self reloadURL];
1326}
1327
1328- (void) _rightButtonClicked {
caa427d1
JF
1329#if !AlwaysReload
1330 if (function_ != nil)
12b59862 1331 [self callFunction:function_];
caa427d1
JF
1332 else
1333#endif
1334 [self __rightButtonClicked];
22f8bed9
JF
1335}
1336
1337- (id) _rightButtonTitle {
43f3d7f6 1338 return UCLocalize("RELOAD");
22f8bed9
JF
1339}
1340
1341- (id) rightButtonTitle {
12b59862 1342 return [self isLoading] ? @"" : button_ != nil ? button_ : [self _rightButtonTitle];
22f8bed9
JF
1343}
1344
1345- (UINavigationButtonStyle) rightButtonStyle {
1346 if (style_ == nil) normal:
1347 return UINavigationButtonStyleNormal;
1348 else if ([style_ isEqualToString:@"Normal"])
1349 return UINavigationButtonStyleNormal;
1350 else if ([style_ isEqualToString:@"Back"])
1351 return UINavigationButtonStyleBack;
1352 else if ([style_ isEqualToString:@"Highlighted"])
1353 return UINavigationButtonStyleHighlighted;
1354 else if ([style_ isEqualToString:@"Destructive"])
1355 return UINavigationButtonStyleDestructive;
1356 else goto normal;
1357}
1358
1359- (NSString *) title {
43f3d7f6 1360 return title_ == nil ? UCLocalize("LOADING") : title_;
22f8bed9
JF
1361}
1362
1363- (NSString *) backButtonTitle {
43f3d7f6 1364 return UCLocalize("BROWSER");
22f8bed9
JF
1365}
1366
1367- (void) setPageActive:(BOOL)active {
1368 if (!active)
1369 [indicator_ removeFromSuperview];
1370 else
1371 [[book_ navigationBar] addSubview:indicator_];
1372}
1373
1374- (void) resetViewAnimated:(BOOL)animated {
1375}
1376
1377- (void) setPushed:(bool)pushed {
1378 pushed_ = pushed;
1379}
1380
3e9c9e85
JF
1381+ (float) defaultWidth {
1382 return 980;
1383}
1384
22f8bed9 1385@end