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