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