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