X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/65fe894c774e2ed25ce990ac97ca3da3c7ebf0cc..7afcea1c7f36f0c4ee9c4d4b53618df39073d851:/UICaboodle/BrowserView.m diff --git a/UICaboodle/BrowserView.m b/UICaboodle/BrowserView.m index cb16bc85..0f95a049 100644 --- a/UICaboodle/BrowserView.m +++ b/UICaboodle/BrowserView.m @@ -1,5 +1,46 @@ #include +/* Indirect Delegate {{{ */ +@interface IndirectDelegate : NSProxy { + _transient volatile id delegate_; +} + +- (void) setDelegate:(id)delegate; +- (id) initWithDelegate:(id)delegate; +@end + +@implementation IndirectDelegate + +- (void) setDelegate:(id)delegate { + delegate_ = delegate; +} + +- (id) initWithDelegate:(id)delegate { + delegate_ = delegate; + return self; +} + +- (BOOL) respondsToSelector:(SEL)sel { + return delegate_ == nil ? FALSE : [delegate_ respondsToSelector:sel]; +} + +- (NSMethodSignature *) methodSignatureForSelector:(SEL)sel { + if (delegate_ != nil) + if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel]) + return sig; + // XXX: I fucking hate Apple so very very bad + return [NSMethodSignature signatureWithObjCTypes:"v@:"]; +} + +- (void) forwardInvocation:(NSInvocation *)inv { + SEL sel = [inv selector]; + if (delegate_ != nil && [delegate_ respondsToSelector:sel]) + [inv invokeWithTarget:delegate_]; +} + +@end +/* }}} */ + @interface WebView (Cydia) - (void) setScriptDebugDelegate:(id)delegate; - (void) _setFormDelegate:(id)delegate; @@ -8,13 +49,158 @@ - (void) _setLayoutInterval:(float)interval; @end +/* Web Scripting {{{ */ +@interface CydiaObject : NSObject { + id indirect_; +} + +- (id) initWithDelegate:(IndirectDelegate *)indirect; +@end + +@implementation CydiaObject + +- (void) dealloc { + [indirect_ release]; + [super dealloc]; +} + +- (id) initWithDelegate:(IndirectDelegate *)indirect { + if ((self = [super init]) != nil) { + indirect_ = [indirect retain]; + } return self; +} + ++ (NSString *) webScriptNameForSelector:(SEL)selector { + if (selector == @selector(close)) + return @"close"; + else if (selector == @selector(getPackageById:)) + return @"getPackageById"; + else if (selector == @selector(setAutoPopup:)) + return @"setAutoPopup"; + else if (selector == @selector(setButtonImage:withStyle:toFunction:)) + return @"setButtonImage"; + else if (selector == @selector(setButtonTitle:withStyle:toFunction:)) + return @"setButtonTitle"; + else if (selector == @selector(setPopupHook:)) + return @"setPopupHook"; + else if (selector == @selector(setViewportWidth:)) + return @"setViewportWidth"; + else if (selector == @selector(supports:)) + return @"supports"; + else if (selector == @selector(du:)) + return @"du"; + else if (selector == @selector(statfs:)) + return @"statfs"; + else + return nil; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return [self webScriptNameForSelector:selector] == nil; +} + +- (BOOL) supports:(NSString *)feature { + return [feature isEqualToString:@"window.open"]; +} + +- (Package *) getPackageById:(NSString *)id { + return [[Database sharedInstance] packageWithName:id]; +} + +- (NSArray *) statfs:(NSString *)path { + struct statfs stat; + + if (path == nil || statfs([path UTF8String], &stat) == -1) + return nil; + + return [NSArray arrayWithObjects: + [NSNumber numberWithUnsignedLong:stat.f_bsize], + [NSNumber numberWithUnsignedLong:stat.f_blocks], + [NSNumber numberWithUnsignedLong:stat.f_bfree], + nil]; +} + +- (NSNumber *) du:(NSString *)path { + NSNumber *value(nil); + + int fds[2]; + _assert(pipe(fds) != -1); + + pid_t pid(ExecFork()); + if (pid == 0) { + _assert(dup2(fds[1], 1) != -1); + _assert(close(fds[0]) != -1); + _assert(close(fds[1]) != -1); + execlp("du", "du", "-s", [path UTF8String], NULL); + exit(1); + _assert(false); + } + + _assert(close(fds[1]) != -1); + + if (FILE *du = fdopen(fds[0], "r")) { + char line[1024]; + while (fgets(line, sizeof(line), du) != NULL) { + size_t length(strlen(line)); + while (length != 0 && line[length - 1] == '\n') + line[--length] = '\0'; + if (char *tab = strchr(line, '\t')) { + *tab = '\0'; + value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)]; + } + } + + fclose(du); + } else _assert(close(fds[0])); + + int status; + wait: + if (waitpid(pid, &status, 0) == -1) + if (errno == EINTR) + goto wait; + else _assert(false); + + return value; +} + +- (void) close { + [indirect_ close]; +} + +- (void) setAutoPopup:(BOOL)popup { + [indirect_ setAutoPopup:popup]; +} + +- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { + [indirect_ setButtonImage:button withStyle:style toFunction:function]; +} + +- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { + [indirect_ setButtonTitle:button withStyle:style toFunction:function]; +} + +- (void) setPopupHook:(id)function { + [indirect_ setPopupHook:function]; +} + +- (void) setViewportWidth:(float)width { + [indirect_ setViewportWidth:width]; +} + +@end +/* }}} */ + @implementation BrowserView -#if ForSaurik +#if ShowInternals #include "Internals.h" #endif - (void) dealloc { +#if LogBrowser + NSLog(@"[BrowserView dealloc]"); +#endif + if (challenge_ != nil) [challenge_ release]; @@ -34,6 +220,8 @@ [webview_ setDelegate:nil]; [webview_ setGestureDelegate:nil]; + [webview_ setFormEditingDelegate:nil]; + [webview_ setInteractionDelegate:nil]; //NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; @@ -49,6 +237,8 @@ [indirect_ setDelegate:nil]; [indirect_ release]; + [cydia_ release]; + [scroller_ setDelegate:nil]; if (button_ != nil) @@ -57,6 +247,8 @@ [style_ release]; if (function_ != nil) [function_ release]; + if (closer_ != nil) + [closer_ release]; [scroller_ release]; [indicator_ release]; @@ -100,7 +292,6 @@ } - (void) reloadURL { - NSLog(@"rlu:%@", request_); if (request_ == nil) return; @@ -124,8 +315,48 @@ return [webview_ webView]; } +- (UIWebDocumentView *) documentView { + return webview_; +} + +- (void) _fixScroller { + CGRect bounds([webview_ documentBounds]); +#if LogBrowser + NSLog(@"_fs:(%f,%f+%f,%f)", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); +#endif + + float extra; + if (!editing_) + extra = 0; + else { + UIFormAssistant *assistant([UIFormAssistant sharedFormAssistant]); + CGRect peripheral([assistant peripheralFrame]); +#if LogBrowser + NSLog(@"per:%f", peripheral.size.height); +#endif + extra = peripheral.size.height; + } + + CGRect subrect([scroller_ frame]); + subrect.size.height -= extra; + [scroller_ setScrollerIndicatorSubrect:subrect]; + + NSSize visible(NSMakeSize(subrect.size.width, subrect.size.height)); + [webview_ setValue:[NSValue valueWithSize:visible] forGestureAttribute:UIGestureAttributeVisibleSize]; + + CGSize size(size_); + size.height += extra; + [scroller_ setContentSize:size]; + + [scroller_ releaseRubberBandIfNecessary]; +} + - (void) view:(UIView *)sender didSetFrame:(CGRect)frame { - [scroller_ setContentSize:frame.size]; + size_ = frame.size; +#if LogBrowser + NSLog(@"dsf:(%f,%f+%f,%f)", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); +#endif + [self _fixScroller]; } - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old { @@ -133,12 +364,32 @@ } - (void) pushPage:(RVPage *)page { - [self setBackButtonTitle:title_]; [page setDelegate:delegate_]; + [self setBackButtonTitle:title_]; [book_ pushPage:page]; } -- (BOOL) getSpecial:(NSURL *)url { +- (void) _pushPage { + if (pushed_) + return; + [self autorelease]; + pushed_ = true; + [book_ pushPage:self]; +} + +- (void) swapPage:(RVPage *)page { + [page setDelegate:delegate_]; + if (pushed_) + [book_ swapPage:page]; + else + [book_ pushPage:page]; +} + +- (BOOL) getSpecial:(NSURL *)url swap:(BOOL)swap { +#if LogBrowser + NSLog(@"getSpecial:%@", url); +#endif + NSString *href([url absoluteString]); NSString *scheme([[url scheme] lowercaseString]); @@ -154,11 +405,27 @@ return false; if (page != nil) - [self pushPage:page]; + if (swap) + [self swapPage:page]; + else + [self pushPage:page]; + return true; +} + +- (void) webViewShow:(WebView *)sender { + /* XXX: this is where I cry myself to sleep */ +} + +- (bool) _allowJavaScriptPanel { return true; } - (void) webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { + if (![self _allowJavaScriptPanel]) + return; + + [self retain]; + UIActionSheet *sheet = [[[UIActionSheet alloc] initWithTitle:nil buttons:[NSArray arrayWithObjects:@"OK", nil] @@ -172,11 +439,14 @@ } - (BOOL) webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { + if (![self _allowJavaScriptPanel]) + return NO; + UIActionSheet *sheet = [[[UIActionSheet alloc] initWithTitle:nil buttons:[NSArray arrayWithObjects:@"OK", @"Cancel", nil] defaultButtonIndex:0 - delegate:self + delegate:indirect_ context:@"confirm" ] autorelease]; @@ -194,69 +464,14 @@ return [confirm boolValue]; } -/* Web Scripting {{{ */ -+ (NSString *) webScriptNameForSelector:(SEL)selector { - if (selector == @selector(getPackageById:)) - return @"getPackageById"; - else if (selector == @selector(setButtonImage:withStyle:toFunction:)) - return @"setButtonImage"; - else if (selector == @selector(setButtonTitle:withStyle:toFunction:)) - return @"setButtonTitle"; - else if (selector == @selector(supports:)) - return @"supports"; - else if (selector == @selector(du:)) - return @"du"; - else if (selector == @selector(statfs:)) - return @"statfs"; - else - return nil; -} - -+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { - return [self webScriptNameForSelector:selector] == nil; -} - -- (BOOL) supports:(NSString *)feature { - return [feature isEqualToString:@"window.open"]; +- (void) setAutoPopup:(BOOL)popup { + popup_ = popup; } -- (Package *) getPackageById:(NSString *)id { - return [[Database sharedInstance] packageWithName:id]; -} - -- (NSArray *) statfs:(NSString *)path { - struct statfs stat; - - if (path == nil || statfs([path UTF8String], &stat) == -1) - return nil; - - return [NSArray arrayWithObjects: - [NSNumber numberWithUnsignedLong:stat.f_bsize], - [NSNumber numberWithUnsignedLong:stat.f_blocks], - [NSNumber numberWithUnsignedLong:stat.f_bfree], - nil]; -} - -- (NSNumber *) du:(NSString *)path { - NSNumber *value(nil); - - /* XXX: omfg this is stupid */ - if (FILE *du = popen([[@"du -s " stringByAppendingString:path] UTF8String], "r")) { - char line[1024]; - while (fgets(line, sizeof(line), du) != NULL) { - size_t length(strlen(line)); - while (length != 0 && line[length - 1] == '\n') - line[--length] = '\0'; - if (char *tab = strchr(line, '\t')) { - *tab = '\0'; - value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)]; - } - } - - pclose(du); - } - - return value; +- (void) setPopupHook:(id)function { + if (closer_ != nil) + [closer_ autorelease]; + closer_ = function == nil ? nil : [function retain]; } - (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { @@ -271,6 +486,8 @@ if (function_ != nil) [function_ autorelease]; function_ = function == nil ? nil : [function retain]; + + [self reloadButtons]; } - (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { @@ -285,11 +502,33 @@ if (function_ != nil) [function_ autorelease]; function_ = function == nil ? nil : [function retain]; + + [self reloadButtons]; +} + +- (void) webView:(WebView *)sender willBeginEditingFormElement:(id)element { + editing_ = true; +} + +- (void) webView:(WebView *)sender didBeginEditingFormElement:(id)element { + [self _fixScroller]; +} + +- (void) webViewDidEndEditingFormElements:(WebView *)sender { + editing_ = false; + [self _fixScroller]; +} + +- (void) webViewClose:(WebView *)sender { + [book_ close]; +} + +- (void) close { + [book_ close]; } -/* }}} */ - (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { - [window setValue:self forKey:@"cydia"]; + [window setValue:cydia_ forKey:@"cydia"]; } - (void) webView:(WebView *)sender unableToImplementPolicyWithError:(NSError *)error frame:(WebFrame *)frame { @@ -297,30 +536,56 @@ } - (void) webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)action request:(NSURLRequest *)request newFrameName:(NSString *)name decisionListener:(id)listener { +#if LogBrowser + NSLog(@"nwa:%@", name); +#endif + if (NSURL *url = [request URL]) { - if (name != nil && [name isEqualToString:@"_open"]) + if (name == nil) unknown: { + if (![self getSpecial:url swap:NO]) { + NSString *scheme([[url scheme] lowercaseString]); + if ([scheme isEqualToString:@"mailto"]) + [delegate_ openMailToURL:url]; + else goto use; + } + } else if ([name isEqualToString:@"_open"]) [delegate_ openURL:url]; + else if ([name isEqualToString:@"_popup"]) { + RVBook *book([[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]); + [book setHook:indirect_]; - NSLog(@"win:%@:%@", url, [action description]); - if (![self getSpecial:url]) { - NSString *scheme([[url scheme] lowercaseString]); - if ([scheme isEqualToString:@"mailto"]) - [delegate_ openMailToURL:url]; - else goto use; - } + RVPage *page([delegate_ pageForURL:url hasTag:NULL]); + if (page == nil) { + /* XXX: call createWebViewWithRequest instead? */ + + [self setBackButtonTitle:title_]; + + BrowserView *browser([[[BrowserView alloc] initWithBook:book] autorelease]); + [browser loadURL:url]; + page = browser; + } + + [book setDelegate:delegate_]; + [page setDelegate:delegate_]; + + [book setPage:page]; + [book_ pushBook:book]; + } else goto unknown; [listener ignore]; } else use: [listener use]; } -- (void) webView:(WebView *)webView decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { +- (void) webView:(WebView *)sender decidePolicyForMIMEType:(NSString *)type request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { if ([WebView canShowMIMEType:type]) [listener use]; else { // XXX: handle more mime types! [listener ignore]; - if (frame == [webView mainFrame]) + + WebView *webview([webview_ webView]); + if (frame == [webview mainFrame]) [UIApp openURL:[request URL]]; } } @@ -338,13 +603,19 @@ if (request_ != nil) [request_ autorelease]; request_ = [request retain]; +#if LogBrowser NSLog(@"dpn:%@", request_); +#endif } [listener use]; + + WebView *webview([webview_ webView]); + if (frame == [webview mainFrame]) + [self _pushPage]; return; } -#if ForSaurik +#if LogBrowser else NSLog(@"nav:%@:%@", url, [action description]); #endif @@ -361,7 +632,10 @@ int store(_not(int)); if (NSURL *itms = [url itmsURL:&store]) { +#if LogBrowser NSLog(@"itms#%@#%u#%@", url, store, itms); +#endif + if ( store == 1 && [capability containsObject:@"com.apple.MobileStore"] || store == 2 && [capability containsObject:@"com.apple.AppStore"] @@ -383,7 +657,7 @@ goto ignore; } - if ([self getSpecial:url]) + if ([self getSpecial:url swap:YES]) goto ignore; else if ([WebView _canHandleRequest:request]) goto use; @@ -397,19 +671,13 @@ //lprintf("Status:%s\n", [text UTF8String]); } -- (void) _pushPage { - if (pushed_) - return; - pushed_ = true; - [book_ pushPage:self]; -} - - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { NSString *context([sheet context]); - if ([context isEqualToString:@"alert"]) + if ([context isEqualToString:@"alert"]) { + [self autorelease]; [sheet dismiss]; - else if ([context isEqualToString:@"confirm"]) { + } else if ([context isEqualToString:@"confirm"]) { switch (button) { case 1: confirm_ = [NSNumber numberWithBool:YES]; @@ -507,33 +775,48 @@ } - (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source { - NSURL *url = [request URL]; - if ([self getSpecial:url]) - return nil; - [self _pushPage]; return [self _addHeadersToRequest:request]; } -- (WebView *) _createWebViewWithRequest:(NSURLRequest *)request pushed:(BOOL)pushed { - [self setBackButtonTitle:title_]; +- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features { +//- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request userGesture:(BOOL)gesture { +#if LogBrowser + NSLog(@"cwv:%@ (%@): %@", request, title_, features == nil ? @"{}" : [features description]); + //NSLog(@"cwv:%@ (%@): %@", request, title_, gesture ? @"Yes" : @"No"); +#endif - BrowserView *browser = [[[BrowserView alloc] initWithBook:book_] autorelease]; - [browser setDelegate:delegate_]; + NSNumber *value([features objectForKey:@"width"]); + float width(value == nil ? 0 : [value floatValue]); + + RVBook *book(!popup_ ? book_ : [[[RVPopUpBook alloc] initWithFrame:[delegate_ popUpBounds]] autorelease]); + + /* XXX: deal with cydia:// pages */ + BrowserView *browser([[[BrowserView alloc] initWithBook:book forWidth:width] autorelease]); + + if (features != nil && popup_) { + [book setDelegate:delegate_]; + [book setHook:indirect_]; + [browser setDelegate:delegate_]; - if (pushed) { [browser loadRequest:request]; - [book_ pushPage:browser]; + + [book setPage:browser]; + [book_ pushBook:book]; + } else if (request == nil) { + [self setBackButtonTitle:title_]; + [browser setDelegate:delegate_]; + [browser retain]; + } else { + [self pushPage:browser]; + [browser loadRequest:request]; } return [browser webView]; } - (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { - return [self _createWebViewWithRequest:request pushed:(request != nil)]; -} - -- (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features { - return [self _createWebViewWithRequest:request pushed:YES]; + return [self webView:sender createWebViewWithRequest:request windowFeatures:nil]; + //return [self webView:sender createWebViewWithRequest:request userGesture:YES]; } - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { @@ -548,6 +831,8 @@ if ([frame parentFrame] != nil) return; + [webview_ resignFirstResponder]; + reloading_ = false; loading_ = true; [self reloadButtons]; @@ -572,9 +857,15 @@ function_ = nil; } + if (closer_ != nil) { + [closer_ release]; + closer_ = nil; + } + [book_ reloadTitleForPage:self]; [scroller_ scrollPointVisibleAtTopLeft:CGPointZero]; + [scroller_ setZoomScale:1 duration:0]; CGRect webrect = [scroller_ bounds]; webrect.size.height = 0; @@ -588,12 +879,12 @@ } } -- (bool) _loading { +- (bool) isLoading { return loading_; } - (void) reloadButtons { - if ([self _loading]) + if ([self isLoading]) [indicator_ startAnimation]; else [indicator_ stopAnimation]; @@ -613,6 +904,7 @@ } - (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame { + [self _pushPage]; return [webview_ webView:sender didCommitLoadForFrame:frame]; } @@ -671,6 +963,8 @@ - (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { if ([frame parentFrame] != nil) return; + if (reloading_) + return; [self _finishLoading]; [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@", @@ -682,14 +976,20 @@ } - (void) webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary { -#if ForSaurik +#if LogBrowser || ForSaurik lprintf("Console:%s\n", [[dictionary description] UTF8String]); #endif } -- (id) initWithBook:(RVBook *)book { +- (void) setViewportWidth:(float)width { + width_ = width ? width != 0 : [[self class] defaultWidth]; + [webview_ setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; +} + +- (id) initWithBook:(RVBook *)book forWidth:(float)width { if ((self = [super initWithBook:book]) != nil) { loading_ = false; + popup_ = false; struct CGRect bounds = [self bounds]; @@ -742,12 +1042,13 @@ [webview_ setAutoresizes:YES]; [webview_ setMinimumScale:0.25f forDocumentTypes:0x10]; + [webview_ setMaximumScale:5.00f forDocumentTypes:0x10]; [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x10]; - [webview_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; + //[webview_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x2]; - [webview_ setMinimumScale:1.0f forDocumentTypes:0x8]; + [webview_ setMinimumScale:1.00f forDocumentTypes:0x8]; [webview_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x8]; [webview_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x8]; @@ -760,14 +1061,20 @@ [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeUpdatesScroller]; [webview_ setSmoothsFonts:YES]; - + [webview_ setAllowsImageSheet:YES]; [webview _setUsesLoaderCache:YES]; - [webview setGroupName:@"Cydia"]; + + [webview setGroupName:@"CydiaGroup"]; [webview _setLayoutInterval:0]; } + [self setViewportWidth:width]; + [webview_ setDelegate:self]; [webview_ setGestureDelegate:self]; + [webview_ setFormEditingDelegate:self]; + [webview_ setInteractionDelegate:self]; + [scroller_ addSubview:webview_]; //NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; @@ -780,9 +1087,24 @@ NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed] - ]; [webview setApplicationNameForUserAgent:application]; + ]; + + if (Product_ != nil) + application = [NSString stringWithFormat:@"%@ Version/%@", application, Product_]; + if (Build_ != nil) + application = [NSString stringWithFormat:@"%@ Mobile/%@", application, Build_]; + if (Safari_ != nil) + application = [NSString stringWithFormat:@"%@ Safari/%@", application, Safari_]; + + /* XXX: lookup application directory? */ + /*if (NSDictionary *safari = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) + if (NSString *version = [safari objectForKey:@"SafariProductVersion"]) + application = [NSString stringWithFormat:@"Version/%@ %@", version, application];*/ + + [webview setApplicationNameForUserAgent:application]; indirect_ = [[IndirectDelegate alloc] initWithDelegate:self]; + cydia_ = [[CydiaObject alloc] initWithDelegate:indirect_]; [webview setFrameLoadDelegate:self]; [webview setResourceLoadDelegate:indirect_]; @@ -795,46 +1117,62 @@ } return self; } +- (id) initWithBook:(RVBook *)book { + return [self initWithBook:book forWidth:0]; +} + - (void) didFinishGesturesInView:(UIView *)view forEvent:(id)event { [webview_ redrawScaledDocument]; } -- (void) _rightButtonClicked { - if (function_ == nil) { - reloading_ = true; - [self reloadURL]; - } else { - WebView *webview([webview_ webView]); - WebFrame *frame([webview mainFrame]); - - id _private(MSHookIvar(webview, "_private")); - WebCore::Page *page(_private == nil ? NULL : MSHookIvar(_private, "page")); - WebCore::Settings *settings(page == NULL ? NULL : page->settings()); - - bool no; - if (settings == NULL) - no = 0; - else { - no = settings->JavaScriptCanOpenWindowsAutomatically(); - settings->setJavaScriptCanOpenWindowsAutomatically(true); - } +- (void) callFunction:(WebScriptObject *)function { + WebView *webview([webview_ webView]); + WebFrame *frame([webview mainFrame]); - [delegate_ clearFirstResponder]; - JSObjectRef function([function_ JSObject]); - JSGlobalContextRef context([frame globalContext]); - JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL); + id _private(MSHookIvar(webview, "_private")); + WebCore::Page *page(_private == nil ? NULL : MSHookIvar(_private, "page")); + WebCore::Settings *settings(page == NULL ? NULL : page->settings()); - if (settings != NULL) - settings->setJavaScriptCanOpenWindowsAutomatically(no); + bool no; + if (settings == NULL) + no = 0; + else { + no = settings->JavaScriptCanOpenWindowsAutomatically(); + settings->setJavaScriptCanOpenWindowsAutomatically(true); } + + [delegate_ clearFirstResponder]; + JSObjectRef object([function JSObject]); + JSGlobalContextRef context([frame globalContext]); + JSObjectCallAsFunction(context, object, NULL, 0, NULL, NULL); + + if (settings != NULL) + settings->setJavaScriptCanOpenWindowsAutomatically(no); +} + +- (void) didCloseBook:(RVBook *)book { + if (closer_ != nil) + [self callFunction:closer_]; +} + +- (void) __rightButtonClicked { + reloading_ = true; + [self reloadURL]; +} + +- (void) _rightButtonClicked { + if (function_ == nil) + [self __rightButtonClicked]; + else + [self callFunction:function_]; } - (id) _rightButtonTitle { - return button_ != nil ? button_ : @"Reload"; + return @"Reload"; } - (id) rightButtonTitle { - return [self _loading] ? @"" : [self _rightButtonTitle]; + return [self isLoading] ? @"" : button_ != nil ? button_ : [self _rightButtonTitle]; } - (UINavigationButtonStyle) rightButtonStyle { @@ -873,4 +1211,8 @@ pushed_ = pushed; } ++ (float) defaultWidth { + return 980; +} + @end