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