X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/b8b6c2b8747231c760ca05d34f4727e75db1dccc..ab2cfc1e0f4678f398698b0d9db90c69e1e71f3c:/UICaboodle/BrowserView.mm diff --git a/UICaboodle/BrowserView.mm b/UICaboodle/BrowserView.mm index 2abc02ec..43f2905a 100644 --- a/UICaboodle/BrowserView.mm +++ b/UICaboodle/BrowserView.mm @@ -27,6 +27,25 @@ extern NSString * const kCAFilterNearest; #include "substrate.h" #define ForSaurik 0 +#define DefaultTimeout_ 120.0 + +#define ShowInternals 0 +#define LogBrowser 0 +#define LogMessages 0 + +#define lprintf(args...) fprintf(stderr, args) + +// WebThreadLocked {{{ +struct WebThreadLocked { + _finline WebThreadLocked() { + WebThreadLock(); + } + + _finline ~WebThreadLocked() { + WebThreadUnlock(); + } +}; +// }}} template static inline void CYRelease(Type_ &value) { @@ -40,6 +59,7 @@ float CYScrollViewDecelerationRateNormal; @interface WebView (Apple) - (void) _setLayoutInterval:(float)interval; +- (void) _setAllowsMessaging:(BOOL)allows; @end @interface WebPreferences (Apple) @@ -85,18 +105,28 @@ float CYScrollViewDecelerationRateNormal; - (BOOL) respondsToSelector:(SEL)sel { if ([super respondsToSelector:sel]) return YES; + // XXX: WebThreadCreateNSInvocation returns nil - //fprintf(stderr, "[%s]R?%s\n", class_getName(self->isa), sel_getName(sel)); + +#if ShowInternals + fprintf(stderr, "[%s]R?%s\n", class_getName(self->isa), sel_getName(sel)); +#endif + return delegate_ == nil ? NO : [delegate_ respondsToSelector:sel]; } - (NSMethodSignature *) methodSignatureForSelector:(SEL)sel { if (NSMethodSignature *method = [super methodSignatureForSelector:sel]) return method; - //fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel)); + +#if ShowInternals + fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel)); +#endif + if (delegate_ != nil) if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel]) return sig; + // XXX: I fucking hate Apple so very very bad return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } @@ -197,6 +227,10 @@ enum CYWebPolicyDecision { @implementation CYWebView : UIWebView +#if ShowInternals +#include "UICaboodle/UCInternal.h" +#endif + - (id) initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame]) != nil) { } return self; @@ -220,6 +254,21 @@ enum CYWebPolicyDecision { return created; }*/ +// webView:addMessageToConsole: (X.Xx) {{{ +static void $UIWebViewWebViewDelegate$webView$addMessageToConsole$(UIWebViewWebViewDelegate *self, SEL sel, WebView *view, NSDictionary *message) { + UIWebView *uiWebView(MSHookIvar(self, "uiWebView")); + if ([uiWebView respondsToSelector:@selector(webView:addMessageToConsole:)]) + [uiWebView webView:view addMessageToConsole:message]; +} + +- (void) webView:(WebView *)view addMessageToConsole:(NSDictionary *)message { + id delegate([self delegate]); + if ([delegate respondsToSelector:@selector(webView:addMessageToConsole:)]) + [delegate webView:view addMessageToConsole:message]; + if ([UIWebView instancesRespondToSelector:@selector(webView:addMessageToConsole:)]) + [super webView:view addMessageToConsole:message]; +} +// }}} // webView:decidePolicyForNavigationAction:request:frame:decisionListener: (2.0+) {{{ - (void) webView:(WebView *)view decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { id delegate([self delegate]); @@ -392,6 +441,7 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se + (void) initialize { if (Class $UIWebViewWebViewDelegate = objc_getClass("UIWebViewWebViewDelegate")) { + class_addMethod($UIWebViewWebViewDelegate, @selector(webView:addMessageToConsole:), (IMP) &$UIWebViewWebViewDelegate$webView$addMessageToConsole$, "v16@0:4@8@12"); class_addMethod($UIWebViewWebViewDelegate, @selector(webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:), (IMP) &$UIWebViewWebViewDelegate$webView$decidePolicyForNewWindowAction$request$newFrameName$decisionListener$, "v28@0:4@8@12@16@20@24"); class_addMethod($UIWebViewWebViewDelegate, @selector(webView:didClearWindowObject:forFrame:), (IMP) &$UIWebViewWebViewDelegate$webView$didClearWindowObject$forFrame$, "v20@0:4@8@12@16"); class_addMethod($UIWebViewWebViewDelegate, @selector(webView:didReceiveTitle:forFrame:), (IMP) &$UIWebViewWebViewDelegate$webView$didReceiveTitle$forFrame$, "v20@0:4@8@12@16"); @@ -402,11 +452,6 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se @end -#define ShowInternals 0 -#define LogBrowser 0 - -#define lprintf(args...) fprintf(stderr, args) - @implementation BrowserController #if ShowInternals @@ -463,11 +508,21 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se [super dealloc]; } +- (void) setURL:(NSURL *)url { + _assert(request_ == nil); + + request_ = [[NSURLRequest + requestWithURL:url + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:DefaultTimeout_ + ] retain]; +} + - (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy { [self loadRequest:[NSURLRequest requestWithURL:url cachePolicy:policy - timeoutInterval:120.0 + timeoutInterval:DefaultTimeout_ ]]; } @@ -482,15 +537,20 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se error_ = false; - WebThreadLock(); + WebThreadLocked lock; [webview_ loadRequest:request]; - WebThreadUnlock(); } -- (void) reloadURL { +- (void) reloadURLWithCache:(BOOL)cache { if (request_ == nil) return; + NSMutableURLRequest *request([request_ mutableCopy]); + [request setCachePolicy:(cache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData)]; + + [request_ autorelease]; + request_ = [request retain]; + if ([request_ HTTPBody] == nil && [request_ HTTPBodyStream] == nil) [self loadRequest:request_]; else { @@ -499,7 +559,9 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se message:nil delegate:self cancelButtonTitle:UCLocalize("CANCEL") - otherButtonTitles:UCLocalize("SUBMIT"), nil + otherButtonTitles: + UCLocalize("SUBMIT"), + nil ] autorelease]; [alert setContext:@"submit"]; @@ -507,6 +569,15 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se } } +- (void) reloadURL { + [self reloadURLWithCache:YES]; +} + +- (void) reloadData { + [super reloadData]; + [self reloadURLWithCache:YES]; +} + - (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { if (custom_ != nil) [custom_ autorelease]; @@ -529,7 +600,7 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se else function_ = [function retain]; - [self applyRightButton]; + [self performSelectorOnMainThread:@selector(applyRightButton) withObject:nil waitUntilDone:NO]; } - (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { @@ -554,7 +625,7 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se else function_ = [function retain]; - [self applyRightButton]; + [self performSelectorOnMainThread:@selector(applyRightButton) withObject:nil waitUntilDone:NO]; } - (void) setPopupHook:(id)function { @@ -575,6 +646,14 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se [self _setViewportWidth]; } +- (void) _setViewportWidthOnMainThread:(NSNumber *)width { + [self setViewportWidth:[width floatValue]]; +} + +- (void) setViewportWidthOnMainThread:(float)width { + [self performSelectorOnMainThread:@selector(_setViewportWidthOnMainThread:) withObject:[NSNumber numberWithFloat:width] waitUntilDone:NO]; +} + - (void) webViewUpdateViewSettings:(UIWebView *)view { [self _setViewportWidth]; } @@ -605,6 +684,12 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se } // CYWebViewDelegate {{{ +- (void) webView:(WebView *)view addMessageToConsole:(NSDictionary *)message { +#if LogMessages + NSLog(@"addMessageToConsole:%@", message); +#endif +} + - (void) webView:(WebView *)view decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { #if LogBrowser NSLog(@"decidePolicyForNavigationAction:%@ request:%@ frame:%@", action, request, frame); @@ -638,7 +723,8 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se if ([scheme isEqualToString:@"mailto"]) [self _openMailToURL:url]; - CYViewController *page([delegate_ pageForURL:url]); + // XXX: filter to internal usage? + CYViewController *page([delegate_ pageForURL:url forExternal:NO]); if (page == nil) { BrowserController *browser([[[class_ alloc] init] autorelease]); @@ -838,9 +924,8 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se if (button == [alert cancelButtonIndex]) { } else if (button == [alert firstOtherButtonIndex]) { if (request_ != nil) { - WebThreadLock(); + WebThreadLocked lock; [webview_ loadRequest:request_]; - WebThreadUnlock(); } } @@ -969,6 +1054,13 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se [preferences setCacheModel:WebCacheModelDocumentBrowser]; [preferences setOfflineWebApplicationCacheEnabled:YES]; +#if LogMessages + if ([document respondsToSelector:@selector(setAllowsMessaging:)]) + [document setAllowsMessaging:YES]; + if ([webview respondsToSelector:@selector(_setAllowsMessaging:)]) + [webview _setAllowsMessaging:YES]; +#endif + if ([webview_ respondsToSelector:@selector(_scrollView)]) { scroller_ = [webview_ _scrollView]; @@ -1035,13 +1127,19 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se return [self initWithWidth:0]; } +- (id) initWithURL:(NSURL *)url { + if ((self = [self init]) != nil) { + [self setURL:url]; + } return self; +} + - (void) didDismissModalViewController { if (closer_ != nil) [self callFunction:closer_]; } - (void) callFunction:(WebScriptObject *)function { - WebThreadLock(); + WebThreadLocked lock; WebView *webview([[webview_ _documentView] webView]); WebFrame *frame([webview mainFrame]); @@ -1074,12 +1172,10 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se settings->setJavaScriptCanOpenWindowsAutomatically(no);*/ [preferences setJavaScriptCanOpenWindowsAutomatically:maybe]; - - WebThreadUnlock(); } - (void) reloadButtonClicked { - [self reloadURL]; + [self reloadURLWithCache:YES]; } - (void) _customButtonClicked { @@ -1099,4 +1195,47 @@ static void $UIWebViewWebViewDelegate$webViewClose$(UIWebViewWebViewDelegate *se return 980; } +- (void) dispatchEvent:(NSString *)event { + WebThreadLocked lock; + + NSString *script([NSString stringWithFormat:@ + "(function() {" + "var event = this.document.createEvent('Events');" + "event.initEvent('%@', false, false);" + "this.document.dispatchEvent(event);" + "})();" + , event]); + + NSMutableArray *frames([NSMutableArray arrayWithObjects: + [[[webview_ _documentView] webView] mainFrame] + , nil]); + + while (WebFrame *frame = [frames lastObject]) { + WebScriptObject *object([frame windowObject]); + [object evaluateWebScript:script]; + [frames removeLastObject]; + [frames addObjectsFromArray:[frame childFrames]]; + } +} + +- (void) viewWillAppear:(BOOL)animated { + [self dispatchEvent:@"CydiaViewWillAppear"]; + [super viewWillAppear:animated]; +} + +- (void) viewDidAppear:(BOOL)animated { + [self dispatchEvent:@"CydiaViewDidAppear"]; + [super viewDidAppear:animated]; +} + +- (void) viewWillDisappear:(BOOL)animated { + [self dispatchEvent:@"CydiaViewWillDisappear"]; + [super viewWillDisappear:animated]; +} + +- (void) viewDidDisappear:(BOOL)animated { + [self dispatchEvent:@"CydiaViewDidDisappear"]; + [super viewDidDisappear:animated]; +} + @end