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