]> git.saurik.com Git - cydia.git/blame - UICaboodle/BrowserView.mm
Major modifications to ready for stability.
[cydia.git] / UICaboodle / BrowserView.mm
CommitLineData
3cb572d2
JF
1#include <UICaboodle/BrowserView.h>
2#include <UICaboodle/UCLocalize.h>
61b13cae
JF
3
4#import <QuartzCore/CALayer.h>
5// XXX: fix the minimum requirement
6extern NSString * const kCAFilterNearest;
bde2d79b 7
9d7f5e2d 8#include <WebCore/WebCoreThread.h>
4825688a 9#include <WebKit/WebPreferences-WebPrivate.h>
9d7f5e2d 10
61b13cae
JF
11#include "substrate.h"
12
6981ccdf 13#define ForSaurik 0
017b2b71 14
5d8f1006
JF
15static CFArrayRef (*$GSSystemCopyCapability)(CFStringRef);
16static CFArrayRef (*$GSSystemGetCapability)(CFStringRef);
17
61b13cae
JF
18@interface NSString (UIKit)
19- (NSString *) stringByAddingPercentEscapes;
20@end
21
04700693 22/* Indirect Delegate {{{ */
9d7f5e2d 23@interface IndirectDelegate : NSObject {
04700693
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
9d7f5e2d
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
04700693 95- (BOOL) respondsToSelector:(SEL)sel {
9d7f5e2d
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];
04700693
JF
101}
102
103- (NSMethodSignature *) methodSignatureForSelector:(SEL)sel {
9d7f5e2d
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));
04700693
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
61b13cae 123@interface WebView (UICaboodle)
bde2d79b
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
61b13cae 131@implementation WebScriptObject (UICaboodle)
9d7f5e2d
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
4825688a 147#define ShowInternals 0
6981ccdf 148#define LogBrowser 0
4825688a
JF
149
150#define lprintf(args...) fprintf(stderr, args)
151
bde2d79b
JF
152@implementation BrowserView
153
5a5c1e4b 154#if ShowInternals
4825688a 155#include "UICaboodle/UCInternal.h"
bde2d79b
JF
156#endif
157
4825688a 158+ (void) _initialize {
4825688a
JF
159 [WebView enableWebThread];
160
161 WebPreferences *preferences([WebPreferences standardPreferences]);
162 [preferences setCacheModel:WebCacheModelDocumentBrowser];
163 [preferences setOfflineWebApplicationCacheEnabled:YES];
164
165 [WebPreferences _setInitialDefaultTextEncodingToSystemEncoding];
5d8f1006
JF
166
167 $GSSystemCopyCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemCopyCapability"));
168 $GSSystemGetCapability = reinterpret_cast<CFArrayRef (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemGetCapability"));
4825688a
JF
169}
170
bde2d79b 171- (void) dealloc {
1ce016d4 172#if LogBrowser
7b00c562
JF
173 NSLog(@"[BrowserView dealloc]");
174#endif
5a5c1e4b 175
bde2d79b
JF
176 if (challenge_ != nil)
177 [challenge_ release];
178
9d7f5e2d
JF
179 WebThreadLock();
180
bde2d79b
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
9d7f5e2d 188 /* XXX: these are set by UIWebDocumentView
4825688a 189 [webview setDownloadDelegate:nil];
bde2d79b
JF
190 [webview _setFormDelegate:nil];
191 [webview _setUIKitDelegate:nil];
9d7f5e2d
JF
192 [webview setEditingDelegate:nil];*/
193
194 /* XXX: no one sets this, ever
195 [webview setWebMailDelegate:nil];*/
bde2d79b
JF
196
197 [webview_ setDelegate:nil];
198 [webview_ setGestureDelegate:nil];
dcc55b8b
JF
199 [webview_ setFormEditingDelegate:nil];
200 [webview_ setInteractionDelegate:nil];
bde2d79b 201
9d7f5e2d
JF
202 [indirect_ setDelegate:nil];
203
bde2d79b
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
bde2d79b
JF
215 [indirect_ release];
216
9d7f5e2d
JF
217 WebThreadUnlock();
218
bde2d79b
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];
9d7f5e2d
JF
227 if (finish_ != nil)
228 [finish_ release];
1ce016d4
JF
229 if (closer_ != nil)
230 [closer_ release];
9d7f5e2d
JF
231 if (special_ != nil)
232 [special_ release];
bde2d79b
JF
233
234 [scroller_ release];
235 [indicator_ release];
236 if (confirm_ != nil)
237 [confirm_ release];
0fc560b6
JF
238 if (sensitive_ != nil)
239 [sensitive_ release];
bde2d79b
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
bde2d79b
JF
257- (void) loadRequest:(NSURLRequest *)request {
258 pushed_ = true;
f4772bd1 259 error_ = false;
9d7f5e2d
JF
260
261 WebThreadLock();
bde2d79b 262 [webview_ loadRequest:request];
9d7f5e2d 263 WebThreadUnlock();
bde2d79b
JF
264}
265
266- (void) reloadURL {
bde2d79b
JF
267 if (request_ == nil)
268 return;
269
270 if ([request_ HTTPBody] == nil && [request_ HTTPBodyStream] == nil)
f4772bd1 271 [self loadRequest:request_];
bde2d79b
JF
272 else {
273 UIActionSheet *sheet = [[[UIActionSheet alloc]
61b13cae
JF
274 initWithTitle:UCLocalize("RESUBMIT_FORM")
275 buttons:[NSArray arrayWithObjects:UCLocalize("CANCEL"), UCLocalize("SUBMIT"), nil]
bde2d79b
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
5a5c1e4b
JF
290- (UIWebDocumentView *) documentView {
291 return webview_;
292}
293
9d7f5e2d
JF
294/* XXX: WebThreadLock? */
295- (void) _fixScroller:(CGRect)bounds {
dcc55b8b
JF
296 float extra;
297 if (!editing_)
298 extra = 0;
299 else {
300 UIFormAssistant *assistant([UIFormAssistant sharedFormAssistant]);
301 CGRect peripheral([assistant peripheralFrame]);
1ce016d4 302#if LogBrowser
dcc55b8b 303 NSLog(@"per:%f", peripheral.size.height);
5889429e 304#endif
dcc55b8b
JF
305 extra = peripheral.size.height;
306 }
307
308 CGRect subrect([scroller_ frame]);
309 subrect.size.height -= extra;
310 [scroller_ setScrollerIndicatorSubrect:subrect];
311
5889429e
JF
312 NSSize visible(NSMakeSize(subrect.size.width, subrect.size.height));
313 [webview_ setValue:[NSValue valueWithSize:visible] forGestureAttribute:UIGestureAttributeVisibleSize];
314
dcc55b8b
JF
315 CGSize size(size_);
316 size.height += extra;
317 [scroller_ setContentSize:size];
5889429e
JF
318
319 [scroller_ releaseRubberBandIfNecessary];
dcc55b8b
JF
320}
321
9d7f5e2d
JF
322- (void) fixScroller {
323 CGRect bounds([webview_ documentBounds]);
e9fde613 324#if TrackResize
9d7f5e2d
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
bde2d79b 330- (void) view:(UIView *)sender didSetFrame:(CGRect)frame {
dcc55b8b 331 size_ = frame.size;
e9fde613 332#if TrackResize
5889429e
JF
333 NSLog(@"dsf:(%f,%f+%f,%f)", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
334#endif
9d7f5e2d 335 [self _fixScroller:frame];
bde2d79b
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 {
bde2d79b 343 [page setDelegate:delegate_];
2517c95f 344 [self setBackButtonTitle:title_];
5a5c1e4b 345 [book_ pushPage:page];
bde2d79b
JF
346}
347
a55054a2
JF
348- (void) _pushPage {
349 if (pushed_)
350 return;
9d7f5e2d 351 // WTR: [self autorelease];
a55054a2
JF
352 pushed_ = true;
353 [book_ pushPage:self];
354}
355
5889429e
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
b8de369a 364- (BOOL) getSpecial:(NSURL *)url swap:(BOOL)swap {
1ce016d4 365#if LogBrowser
a55054a2
JF
366 NSLog(@"getSpecial:%@", url);
367#endif
368
61b13cae 369 if (RVPage *page = [delegate_ pageForURL:url hasTag:NULL]) {
b8de369a
JF
370 if (swap)
371 [self swapPage:page];
372 else
373 [self pushPage:page];
61b13cae
JF
374
375 return true;
376 } else
377 return false;
bde2d79b
JF
378}
379
4825688a
JF
380- (void) formAssistant:(id)sender didBeginEditingFormNode:(id)node {
381}
382
383- (void) formAssistant:(id)sender didEndEditingFormNode:(id)node {
384 [self fixScroller];
385}
386
5a5c1e4b 387- (void) webViewShow:(WebView *)sender {
5b2d5cf3 388 /* XXX: this is where I cry myself to sleep */
5a5c1e4b
JF
389}
390
7b00c562
JF
391- (bool) _allowJavaScriptPanel {
392 return true;
393}
394
0fc560b6 395- (bool) allowSensitiveRequests {
61b13cae 396 return [self _allowJavaScriptPanel];
0fc560b6
JF
397}
398
399- (void) _promptForSensitive:(NSMutableArray *)array {
400 NSString *name([array objectAtIndex:0]);
401
402 UIActionSheet *sheet = [[[UIActionSheet alloc]
403 initWithTitle:nil
61b13cae 404 buttons:[NSArray arrayWithObjects:UCLocalize("YES"), UCLocalize("NO"), nil]
0fc560b6
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
bde2d79b 439- (void) webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
263b91b4 440 if (![self _allowJavaScriptPanel])
7b00c562 441 return;
b452841e 442 [self retain];
b456f1c9 443
bde2d79b
JF
444 UIActionSheet *sheet = [[[UIActionSheet alloc]
445 initWithTitle:nil
61b13cae 446 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil]
bde2d79b
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 {
7b00c562
JF
457 if (![self _allowJavaScriptPanel])
458 return NO;
b452841e 459 [self retain];
7b00c562 460
bde2d79b
JF
461 UIActionSheet *sheet = [[[UIActionSheet alloc]
462 initWithTitle:nil
61b13cae 463 buttons:[NSArray arrayWithObjects:UCLocalize("OK"), UCLocalize("CANCEL"), nil]
bde2d79b 464 defaultButtonIndex:0
b456f1c9 465 delegate:indirect_
bde2d79b
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;
b452841e
JF
480
481 [self autorelease];
bde2d79b
JF
482 return [confirm boolValue];
483}
484
7b00c562
JF
485- (void) setAutoPopup:(BOOL)popup {
486 popup_ = popup;
487}
488
9d7f5e2d
JF
489- (void) setSpecial:(id)function {
490 if (special_ != nil)
491 [special_ autorelease];
492 special_ = function == nil ? nil : [function retain];
1ce016d4
JF
493}
494
bde2d79b
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];
1ce016d4
JF
507
508 [self reloadButtons];
bde2d79b
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];
1ce016d4
JF
523
524 [self reloadButtons];
bde2d79b 525}
bde2d79b 526
9d7f5e2d
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
61b13cae 539- (void) _openMailToURL:(NSURL *)url {
61b13cae 540 [UIApp openURL:url];// asPanel:YES];
61b13cae
JF
541}
542
dcc55b8b
JF
543- (void) webView:(WebView *)sender willBeginEditingFormElement:(id)element {
544 editing_ = true;
545}
546
547- (void) webView:(WebView *)sender didBeginEditingFormElement:(id)element {
9d7f5e2d 548 [self fixScroller];
dcc55b8b
JF
549}
550
551- (void) webViewDidEndEditingFormElements:(WebView *)sender {
552 editing_ = false;
9d7f5e2d 553 [self fixScroller];
dcc55b8b
JF
554}
555
04700693
JF
556- (void) webViewClose:(WebView *)sender {
557 [book_ close];
558}
559
7afcea1c
JF
560- (void) close {
561 [book_ close];
562}
563
bde2d79b 564- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
bde2d79b
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 {
1ce016d4 572#if LogBrowser
5a5c1e4b 573 NSLog(@"nwa:%@", name);
7b00c562 574#endif
5a5c1e4b 575
bde2d79b 576 if (NSURL *url = [request URL]) {
04700693 577 if (name == nil) unknown: {
b8de369a 578 if (![self getSpecial:url swap:NO]) {
04700693
JF
579 NSString *scheme([[url scheme] lowercaseString]);
580 if ([scheme isEqualToString:@"mailto"])
61b13cae 581 [self _openMailToURL:url];
04700693
JF
582 else goto use;
583 }
584 } else if ([name isEqualToString:@"_open"])
bde2d79b 585 [delegate_ openURL:url];
04700693 586 else if ([name isEqualToString:@"_popup"]) {
3ac7a20a
JF
587 NSString *scheme([[url scheme] lowercaseString]);
588 if ([scheme isEqualToString:@"mailto"])
61b13cae 589 [self _openMailToURL:url];
3ac7a20a
JF
590 else {
591 RVBook *book([[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
592 [book setHook:indirect_];
04700693 593
3ac7a20a
JF
594 RVPage *page([delegate_ pageForURL:url hasTag:NULL]);
595 if (page == nil) {
596 /* XXX: call createWebViewWithRequest instead? */
5a5c1e4b 597
3ac7a20a 598 [self setBackButtonTitle:title_];
5a5c1e4b 599
85021801 600 BrowserView *browser([[[class_ alloc] initWithBook:book] autorelease]);
3ac7a20a
JF
601 [browser loadURL:url];
602 page = browser;
603 }
bde2d79b 604
3ac7a20a
JF
605 [book setDelegate:delegate_];
606 [page setDelegate:delegate_];
0a7e5478 607
3ac7a20a
JF
608 [book setPage:page];
609 [book_ pushBook:book];
610 }
04700693 611 } else goto unknown;
bde2d79b
JF
612
613 [listener ignore];
614 } else use:
615 [listener use];
616}
617
5889429e 618- (void) webView:(WebView *)sender decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
bde2d79b
JF
619 if ([WebView canShowMIMEType:type])
620 [listener use];
621 else {
622 // XXX: handle more mime types!
623 [listener ignore];
5889429e
JF
624
625 WebView *webview([webview_ webView]);
626 if (frame == [webview mainFrame])
bde2d79b
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]);
5d8f1006 638 NSString *host([url host]);
bde2d79b
JF
639
640 if (url == nil) use: {
f4772bd1 641 if (!error_ && [frame parentFrame] == nil) {
bde2d79b
JF
642 if (request_ != nil)
643 [request_ autorelease];
644 request_ = [request retain];
1ce016d4 645#if LogBrowser
bde2d79b 646 NSLog(@"dpn:%@", request_);
04700693 647#endif
bde2d79b
JF
648 }
649
650 [listener use];
5889429e
JF
651
652 WebView *webview([webview_ webView]);
653 if (frame == [webview mainFrame])
654 [self _pushPage];
bde2d79b
JF
655 return;
656 }
1ce016d4 657#if LogBrowser
bde2d79b
JF
658 else NSLog(@"nav:%@:%@", url, [action description]);
659#endif
660
9d7f5e2d
JF
661 const NSArray *capability;
662
5d8f1006
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);
bde2d79b 672
9d7f5e2d 673 if (capability != nil && (
5d8f1006
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
9d7f5e2d 677 )) {
5d8f1006 678 url = open;
bde2d79b
JF
679 open:
680 [UIApp openURL:url];
681 goto ignore;
682 }
683
684 int store(_not(int));
685 if (NSURL *itms = [url itmsURL:&store]) {
1ce016d4 686#if LogBrowser
bde2d79b 687 NSLog(@"itms#%@#%u#%@", url, store, itms);
7b00c562
JF
688#endif
689
9d7f5e2d 690 if (capability != nil && (
bde2d79b
JF
691 store == 1 && [capability containsObject:@"com.apple.MobileStore"] ||
692 store == 2 && [capability containsObject:@"com.apple.AppStore"]
9d7f5e2d 693 )) {
bde2d79b
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"]) {
61b13cae 707 [self _openMailToURL:url];
bde2d79b
JF
708 goto ignore;
709 }
710
b8de369a 711 if ([self getSpecial:url swap:YES])
bde2d79b
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
bde2d79b
JF
725- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
726 NSString *context([sheet context]);
727
b456f1c9
JF
728 if ([context isEqualToString:@"alert"]) {
729 [self autorelease];
bde2d79b 730 [sheet dismiss];
b456f1c9 731 } else if ([context isEqualToString:@"confirm"]) {
bde2d79b
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
0fc560b6
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
bde2d79b
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
6981ccdf 772 _nodefault
bde2d79b
JF
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:
9d7f5e2d
JF
785 if (request_ != nil) {
786 WebThreadLock();
bde2d79b 787 [webview_ loadRequest:request_];
9d7f5e2d
JF
788 WebThreadUnlock();
789 }
bde2d79b
JF
790 break;
791
6981ccdf 792 _nodefault
bde2d79b
JF
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
61b13cae 809 buttons:[NSArray arrayWithObjects:UCLocalize("LOGIN"), UCLocalize("CANCEL"), nil]
bde2d79b
JF
810 defaultButtonIndex:0
811 delegate:self
812 context:@"challenge"
813 ] autorelease];
814
815 [sheet setNumberOfRows:1];
816
61b13cae
JF
817 [sheet addTextFieldWithValue:@"" label:UCLocalize("USERNAME")];
818 [sheet addTextFieldWithValue:@"" label:UCLocalize("PASSWORD")];
bde2d79b
JF
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 {
61b13cae 842 return request;
bde2d79b
JF
843}
844
5a5c1e4b 845- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features {
7b00c562 846//- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request userGesture:(BOOL)gesture {
1ce016d4 847#if LogBrowser
7b00c562
JF
848 NSLog(@"cwv:%@ (%@): %@", request, title_, features == nil ? @"{}" : [features description]);
849 //NSLog(@"cwv:%@ (%@): %@", request, title_, gesture ? @"Yes" : @"No");
5a5c1e4b 850#endif
bde2d79b 851
7b00c562 852 NSNumber *value([features objectForKey:@"width"]);
5889429e 853 float width(value == nil ? 0 : [value floatValue]);
7b00c562
JF
854
855 RVBook *book(!popup_ ? book_ : [[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]);
856
857 /* XXX: deal with cydia:// pages */
85021801 858 BrowserView *browser([[[class_ alloc] initWithBook:book forWidth:width] autorelease]);
7b00c562 859
b456f1c9 860 if (features != nil && popup_) {
7b00c562 861 [book setDelegate:delegate_];
1ce016d4 862 [book setHook:indirect_];
7b00c562
JF
863 [browser setDelegate:delegate_];
864
865 [browser loadRequest:request];
a55054a2 866
7b00c562
JF
867 [book setPage:browser];
868 [book_ pushBook:book];
869 } else if (request == nil) {
a55054a2
JF
870 [self setBackButtonTitle:title_];
871 [browser setDelegate:delegate_];
872 [browser retain];
873 } else {
874 [self pushPage:browser];
875 [browser loadRequest:request];
876 }
877
bde2d79b
JF
878 return [browser webView];
879}
880
881- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
5a5c1e4b 882 return [self webView:sender createWebViewWithRequest:request windowFeatures:nil];
7b00c562 883 //return [self webView:sender createWebViewWithRequest:request userGesture:YES];
bde2d79b
JF
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 {
017b2b71
JF
895 /*if ([loading_ count] == 0)
896 [self retain];*/
b452841e 897 [loading_ addObject:[NSValue valueWithNonretainedObject:frame]];
bde2d79b 898
9d7f5e2d
JF
899 if ([frame parentFrame] == nil) {
900 [webview_ resignFirstResponder];
5889429e 901
9d7f5e2d 902 reloading_ = false;
bde2d79b 903
9d7f5e2d
JF
904 if (title_ != nil) {
905 [title_ release];
906 title_ = nil;
907 }
bde2d79b 908
9d7f5e2d
JF
909 if (button_ != nil) {
910 [button_ release];
911 button_ = nil;
912 }
bde2d79b 913
9d7f5e2d
JF
914 if (style_ != nil) {
915 [style_ release];
916 style_ = nil;
917 }
bde2d79b 918
9d7f5e2d
JF
919 if (function_ != nil) {
920 [function_ release];
921 function_ = nil;
922 }
bde2d79b 923
9d7f5e2d
JF
924 if (finish_ != nil) {
925 [finish_ release];
926 finish_ = nil;
927 }
1ce016d4 928
9d7f5e2d
JF
929 if (closer_ != nil) {
930 [closer_ release];
931 closer_ = nil;
932 }
933
934 if (special_ != nil) {
935 [special_ release];
936 special_ = nil;
937 }
bde2d79b 938
9d7f5e2d
JF
939 [book_ reloadTitleForPage:self];
940
941 [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
942
943 if ([scroller_ respondsToSelector:@selector(setZoomScale:duration:)])
944 [scroller_ setZoomScale:1 duration:0];
f4cd7e8b
JF
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];*/
bde2d79b 949
9d7f5e2d
JF
950 CGRect webrect = [scroller_ bounds];
951 webrect.size.height = 0;
952 [webview_ setFrame:webrect];
953 }
954
955 [self reloadButtons];
bde2d79b
JF
956}
957
958- (void) _finishLoading {
b452841e 959 size_t count([loading_ count]);
017b2b71
JF
960 /*if (count == 0)
961 [self autorelease];*/
b452841e 962 if (reloading_ || count != 0)
9d7f5e2d
JF
963 return;
964 if (finish_ != nil)
965 [self callFunction:finish_];
966 [self reloadButtons];
bde2d79b
JF
967}
968
1ce016d4 969- (bool) isLoading {
9d7f5e2d 970 return [loading_ count] != 0;
bde2d79b
JF
971}
972
973- (void) reloadButtons {
1ce016d4 974 if ([self isLoading])
bde2d79b
JF
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 {
10c3a9c1 994 [self _pushPage];
bde2d79b
JF
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 {
b452841e 1003 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
9d7f5e2d 1004 [self _finishLoading];
bde2d79b 1005
9d7f5e2d 1006 if ([frame parentFrame] == nil) {
bde2d79b
JF
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"])) {
f4772bd1
JF
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 }
bde2d79b
JF
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
9d7f5e2d 1051- (void) _didFailWithError:(NSError *)error forFrame:(WebFrame *)frame {
017b2b71
JF
1052 _trace();
1053 /*if ([frame parentFrame] == nil)
1054 [self autorelease];*/
9d7f5e2d 1055
b452841e 1056 [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]];
bde2d79b
JF
1057 [self _finishLoading];
1058
b452841e
JF
1059 if (reloading_)
1060 return;
1061
9d7f5e2d
JF
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}
f4772bd1 1071
9d7f5e2d
JF
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];
bde2d79b
JF
1078}
1079
1080- (void) webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary {
1ce016d4 1081#if LogBrowser || ForSaurik
bde2d79b
JF
1082 lprintf("Console:%s\n", [[dictionary description] UTF8String]);
1083#endif
1084}
1085
9d7f5e2d
JF
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
dcc55b8b 1095- (void) setViewportWidth:(float)width {
0a523b5a 1096 width_ = width != 0 ? width : [[self class] defaultWidth];
dcc55b8b
JF
1097 [webview_ setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
1098}
1099
9d7f5e2d
JF
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
85021801 1121- (id) initWithBook:(RVBook *)book forWidth:(float)width ofClass:(Class)_class {
bde2d79b 1122 if ((self = [super initWithBook:book]) != nil) {
85021801 1123 class_ = _class;
9d7f5e2d 1124 loading_ = [[NSMutableSet alloc] initWithCapacity:3];
7b00c562 1125 popup_ = false;
bde2d79b
JF
1126
1127 struct CGRect bounds = [self bounds];
1128
1129 scroller_ = [[UIScroller alloc] initWithFrame:bounds];
1130 [self addSubview:scroller_];
1131
bde2d79b
JF
1132 [scroller_ setFixedBackgroundPattern:YES];
1133 [scroller_ setBackgroundColor:[UIColor pinStripeColor]];
1134
1135 [scroller_ setScrollingEnabled:YES];
bde2d79b
JF
1136 [scroller_ setClipsSubviews:YES];
1137 [scroller_ setAllowsRubberBanding:YES];
9d7f5e2d 1138
bde2d79b 1139 [scroller_ setDelegate:self];
9d7f5e2d
JF
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 */
bde2d79b
JF
1149
1150 CGRect webrect = [scroller_ bounds];
1151 webrect.size.height = 0;
1152
1153 WebView *webview;
1154
9d7f5e2d
JF
1155 WebThreadLock();
1156
bde2d79b
JF
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
4825688a
JF
1177 if ([webview_ respondsToSelector:@selector(enableReachability)])
1178 [webview_ enableReachability];
1179
bde2d79b
JF
1180 [webview_ setAllowsMessaging:YES];
1181
4825688a
JF
1182 if ([webview_ respondsToSelector:@selector(useSelectionAssistantWithMode:)])
1183 [webview_ useSelectionAssistantWithMode:0];
1184
bde2d79b
JF
1185 [webview_ setTilingEnabled:YES];
1186 [webview_ setDrawsGrid:NO];
1187 [webview_ setLogsTilingChanges:NO];
1188 [webview_ setTileMinificationFilter:kCAFilterNearest];
4825688a 1189
9d7f5e2d
JF
1190 if ([webview_ respondsToSelector:@selector(setDataDetectorTypes:)])
1191 /* XXX: abstractify */
1192 [webview_ setDataDetectorTypes:0x80000000];
1193 else
1194 [webview_ setDetectsPhoneNumbers:NO];
4825688a 1195
bde2d79b
JF
1196 [webview_ setAutoresizes:YES];
1197
1198 [webview_ setMinimumScale:0.25f forDocumentTypes:0x10];
7b00c562 1199 [webview_ setMaximumScale:5.00f forDocumentTypes:0x10];
bde2d79b 1200 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x10];
7b00c562 1201 //[webview_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10];
bde2d79b
JF
1202
1203 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x2];
1204
7b00c562 1205 [webview_ setMinimumScale:1.00f forDocumentTypes:0x8];
bde2d79b
JF
1206 [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x8];
1207 [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x8];
1208
1209 [webview_ _setDocumentType:0x4];
1210
9d7f5e2d
JF
1211 if ([webview_ respondsToSelector:@selector(UIWebDocumentView:)])
1212 [webview_ setZoomsFocusedFormControl:YES];
bde2d79b
JF
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];
7b00c562 1219 [webview_ setAllowsImageSheet:YES];
bde2d79b 1220 [webview _setUsesLoaderCache:YES];
7b00c562
JF
1221
1222 [webview setGroupName:@"CydiaGroup"];
4825688a
JF
1223
1224 WebPreferences *preferences([webview preferences]);
1225
9d7f5e2d
JF
1226 if ([webview respondsToSelector:@selector(_setLayoutInterval:)])
1227 [webview _setLayoutInterval:0];
4825688a
JF
1228 else
1229 [preferences _setLayoutInterval:0];
bde2d79b
JF
1230 }
1231
dcc55b8b 1232 [self setViewportWidth:width];
7b00c562 1233
bde2d79b
JF
1234 [webview_ setDelegate:self];
1235 [webview_ setGestureDelegate:self];
dcc55b8b
JF
1236 [webview_ setFormEditingDelegate:self];
1237 [webview_ setInteractionDelegate:self];
1238
bde2d79b
JF
1239 [scroller_ addSubview:webview_];
1240
1241 //NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
1242
bde2d79b
JF
1243 indirect_ = [[IndirectDelegate alloc] initWithDelegate:self];
1244
9d7f5e2d 1245 [webview setFrameLoadDelegate:indirect_];
4825688a 1246 [webview setPolicyDelegate:indirect_];
bde2d79b 1247 [webview setResourceLoadDelegate:indirect_];
9d7f5e2d 1248 [webview setUIDelegate:indirect_];
4825688a
JF
1249
1250 /* XXX: do not turn this on under penalty of extreme pain */
1251 [webview setScriptDebugDelegate:nil];
9d7f5e2d
JF
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];
bde2d79b
JF
1258
1259 [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
1260 [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
9d7f5e2d
JF
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];*/
bde2d79b
JF
1265 } return self;
1266}
1267
85021801
JF
1268- (id) initWithBook:(RVBook *)book forWidth:(float)width {
1269 return [self initWithBook:book forWidth:width ofClass:[self class]];
1270}
1271
7b00c562 1272- (id) initWithBook:(RVBook *)book {
5889429e 1273 return [self initWithBook:book forWidth:0];
7b00c562
JF
1274}
1275
9d7f5e2d
JF
1276- (NSString *) stringByEvaluatingJavaScriptFromString:(NSString *)script {
1277 WebThreadLock();
1278 WebView *webview([webview_ webView]);
1279 NSString *string([webview stringByEvaluatingJavaScriptFromString:script]);
1280 WebThreadUnlock();
1281 return string;
bde2d79b
JF
1282}
1283
1ce016d4 1284- (void) callFunction:(WebScriptObject *)function {
9d7f5e2d
JF
1285 WebThreadLock();
1286
1ce016d4
JF
1287 WebView *webview([webview_ webView]);
1288 WebFrame *frame([webview mainFrame]);
bde2d79b 1289
1ce016d4
JF
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());
bde2d79b 1293
1ce016d4
JF
1294 bool no;
1295 if (settings == NULL)
1296 no = 0;
1297 else {
1298 no = settings->JavaScriptCanOpenWindowsAutomatically();
1299 settings->setJavaScriptCanOpenWindowsAutomatically(true);
bde2d79b 1300 }
1ce016d4 1301
61b13cae
JF
1302 if (UIWindow *window = [self window])
1303 if (UIResponder *responder = [window firstResponder])
1304 [responder resignFirstResponder];
1305
1ce016d4
JF
1306 JSObjectRef object([function JSObject]);
1307 JSGlobalContextRef context([frame globalContext]);
1308 JSObjectCallAsFunction(context, object, NULL, 0, NULL, NULL);
1309
1310 if (settings != NULL)
9d7f5e2d
JF
1311 settings->setJavaScriptCanOpenWindowsAutomatically(no);
1312
1313 WebThreadUnlock();
1ce016d4
JF
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 {
9d7f5e2d
JF
1327#if !AlwaysReload
1328 if (function_ != nil)
1ce016d4 1329 [self callFunction:function_];
9d7f5e2d
JF
1330 else
1331#endif
1332 [self __rightButtonClicked];
bde2d79b
JF
1333}
1334
1335- (id) _rightButtonTitle {
61b13cae 1336 return UCLocalize("RELOAD");
bde2d79b
JF
1337}
1338
1339- (id) rightButtonTitle {
1ce016d4 1340 return [self isLoading] ? @"" : button_ != nil ? button_ : [self _rightButtonTitle];
bde2d79b
JF
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 {
61b13cae 1358 return title_ == nil ? UCLocalize("LOADING") : title_;
bde2d79b
JF
1359}
1360
1361- (NSString *) backButtonTitle {
61b13cae 1362 return UCLocalize("BROWSER");
bde2d79b
JF
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
7b00c562
JF
1379+ (float) defaultWidth {
1380 return 980;
1381}
1382
bde2d79b 1383@end