diff options
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVInAppBrowser.m')
-rwxr-xr-x | iPhone/CordovaLib/Classes/CDVInAppBrowser.m | 162 |
1 files changed, 114 insertions, 48 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVInAppBrowser.m b/iPhone/CordovaLib/Classes/CDVInAppBrowser.m index 22fd1fc..14671a5 100755 --- a/iPhone/CordovaLib/Classes/CDVInAppBrowser.m +++ b/iPhone/CordovaLib/Classes/CDVInAppBrowser.m @@ -19,7 +19,7 @@ #import "CDVInAppBrowser.h" #import "CDVPluginResult.h" -#import "CDVViewController.h" +#import "CDVUserAgentUtil.h" #define kInAppBrowserTargetSelf @"_self" #define kInAppBrowserTargetSystem @"_system" @@ -91,8 +91,8 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options { if (self.inAppBrowserViewController == nil) { - NSString* originalUA = [CDVViewController originalUserAgent]; - self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] initWithUserAgent:originalUA]; + NSString* originalUA = [CDVUserAgentUtil originalUserAgent]; + self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] initWithUserAgent:originalUA prevUserAgent:[self.commandDelegate userAgent]]; self.inAppBrowserViewController.navigationDelegate = self; if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) { @@ -103,6 +103,37 @@ CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options]; [self.inAppBrowserViewController showLocationBar:browserOptions.location]; + // Set Presentation Style + UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default + if (browserOptions.presentationstyle != nil) { + if ([browserOptions.presentationstyle isEqualToString:@"pagesheet"]) { + presentationStyle = UIModalPresentationPageSheet; + } else if ([browserOptions.presentationstyle isEqualToString:@"formsheet"]) { + presentationStyle = UIModalPresentationFormSheet; + } + } + self.inAppBrowserViewController.modalPresentationStyle = presentationStyle; + + // Set Transition Style + UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default + if (browserOptions.transitionstyle != nil) { + if ([browserOptions.transitionstyle isEqualToString:@"fliphorizontal"]) { + transitionStyle = UIModalTransitionStyleFlipHorizontal; + } else if ([browserOptions.transitionstyle isEqualToString:@"crossdissolve"]) { + transitionStyle = UIModalTransitionStyleCrossDissolve; + } + } + self.inAppBrowserViewController.modalTransitionStyle = transitionStyle; + + // UIWebView options + self.inAppBrowserViewController.webView.scalesPageToFit = browserOptions.enableviewportscale; + self.inAppBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction; + self.inAppBrowserViewController.webView.allowsInlineMediaPlayback = browserOptions.allowinlinemediaplayback; + if (IsAtLeastiOSVersion(@"6.0")) { + self.inAppBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction; + self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering; + } + if (self.viewController.modalViewController != self.inAppBrowserViewController) { [self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES]; } @@ -111,18 +142,7 @@ - (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options { - BOOL passesWhitelist = YES; - - if ([self.viewController isKindOfClass:[CDVViewController class]]) { - CDVViewController* vc = (CDVViewController*)self.viewController; - if ([vc.whitelist schemeIsAllowed:[url scheme]]) { - passesWhitelist = [vc.whitelist URLIsAllowed:url]; - } - } else { // something went wrong, we can't get the whitelist - passesWhitelist = NO; - } - - if (passesWhitelist) { + if ([self.commandDelegate URLIsWhitelisted:url]) { NSURLRequest* request = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:request]; } else { // this assumes the InAppBrowser can be excepted from the white-list @@ -172,6 +192,9 @@ [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; } + // Don't recycle the ViewController since it may be consuming a lot of memory. + // Also - this is required for the PDF/User-Agent bug work-around. + self.inAppBrowserViewController = nil; } @end @@ -180,11 +203,12 @@ @implementation CDVInAppBrowserViewController -- (id)initWithUserAgent:(NSString*)userAgent +- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent { self = [super init]; if (self != nil) { - self.userAgent = userAgent; + _userAgent = userAgent; + _prevUserAgent = prevUserAgent; [self createViews]; } @@ -199,31 +223,23 @@ webViewBounds.size.height -= FOOTER_HEIGHT; - if (!self.webView) { - // setting the UserAgent must occur before the UIWebView is instantiated. - // This is read per instantiation, so it does not affect the main Cordova UIWebView - NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:self.userAgent, @"UserAgent", nil]; - [[NSUserDefaults standardUserDefaults] registerDefaults:dict]; - - self.webView = [[UIWebView alloc] initWithFrame:webViewBounds]; - self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); - - [self.view addSubview:self.webView]; - [self.view sendSubviewToBack:self.webView]; - - self.webView.delegate = self; - self.webView.scalesPageToFit = TRUE; - self.webView.backgroundColor = [UIColor whiteColor]; - - self.webView.clearsContextBeforeDrawing = YES; - self.webView.clipsToBounds = YES; - self.webView.contentMode = UIViewContentModeScaleToFill; - self.webView.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); - self.webView.multipleTouchEnabled = YES; - self.webView.opaque = YES; - self.webView.scalesPageToFit = NO; - self.webView.userInteractionEnabled = YES; - } + self.webView = [[UIWebView alloc] initWithFrame:webViewBounds]; + self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + + [self.view addSubview:self.webView]; + [self.view sendSubviewToBack:self.webView]; + + self.webView.delegate = self; + self.webView.backgroundColor = [UIColor whiteColor]; + + self.webView.clearsContextBeforeDrawing = YES; + self.webView.clipsToBounds = YES; + self.webView.contentMode = UIViewContentModeScaleToFill; + self.webView.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}"); + self.webView.multipleTouchEnabled = YES; + self.webView.opaque = YES; + self.webView.scalesPageToFit = NO; + self.webView.userInteractionEnabled = YES; self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; self.spinner.alpha = 1.000; @@ -346,11 +362,14 @@ - (void)viewDidUnload { [self.webView loadHTMLString:nil baseURL:nil]; + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; [super viewDidUnload]; } - (void)close { + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; + if ([self respondsToSelector:@selector(presentingViewController)]) { [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil]; } else { @@ -366,7 +385,17 @@ { NSURLRequest* request = [NSURLRequest requestWithURL:url]; - [self.webView loadRequest:request]; + _requestedURL = url; + + if (_userAgentLockToken != 0) { + [self.webView loadRequest:request]; + } else { + [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) { + _userAgentLockToken = lockToken; + [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken]; + [self.webView loadRequest:request]; + }]; + } } - (void)goBack:(id)sender @@ -392,7 +421,11 @@ [self.spinner startAnimating]; if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserLoadStart:)]) { - [self.navigationDelegate browserLoadStart:theWebView.request.URL]; + NSURL* url = theWebView.request.URL; + if (url == nil) { + url = _requestedURL; + } + [self.navigationDelegate browserLoadStart:url]; } } @@ -406,8 +439,25 @@ [self.spinner stopAnimating]; + // Work around a bug where the first time a PDF is opened, all UIWebViews + // reload their User-Agent from NSUserDefaults. + // This work-around makes the following assumptions: + // 1. The app has only a single Cordova Webview. If not, then the app should + // take it upon themselves to load a PDF in the background as a part of + // their start-up flow. + // 2. That the PDF does not require any additional network requests. We change + // the user-agent here back to that of the CDVViewController, so requests + // from it must pass through its white-list. This *does* break PDFs that + // contain links to other remote PDF/websites. + // More info at https://issues.apache.org/jira/browse/CB-2225 + BOOL isPDF = [@"true" isEqualToString:[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]]; + if (isPDF) { + [CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken]; + } + if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserLoadStop:)]) { - [self.navigationDelegate browserLoadStop:theWebView.request.URL]; + NSURL* url = theWebView.request.URL; + [self.navigationDelegate browserLoadStop:url]; } } @@ -460,6 +510,12 @@ if (self = [super init]) { // default values self.location = YES; + + self.enableviewportscale = NO; + self.mediaplaybackrequiresuseraction = NO; + self.allowinlinemediaplayback = NO; + self.keyboarddisplayrequiresuseraction = YES; + self.suppressesincrementalrendering = NO; } return self; @@ -478,12 +534,22 @@ if ([keyvalue count] == 2) { NSString* key = [[keyvalue objectAtIndex:0] lowercaseString]; - NSString* value = [keyvalue objectAtIndex:1]; - BOOL valueBool = [[value lowercaseString] isEqualToString:@"yes"]; + NSString* value = [[keyvalue objectAtIndex:1] lowercaseString]; + + BOOL isBoolean = [value isEqualToString:@"yes"] || [value isEqualToString:@"no"]; + NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init]; + [numberFormatter setAllowsFloats:YES]; + BOOL isNumber = [numberFormatter numberFromString:value] != nil; // set the property according to the key name if ([obj respondsToSelector:NSSelectorFromString(key)]) { - [obj setValue:[NSNumber numberWithBool:valueBool] forKey:key]; + if (isNumber) { + [obj setValue:[numberFormatter numberFromString:value] forKey:key]; + } else if (isBoolean) { + [obj setValue:[NSNumber numberWithBool:[value isEqualToString:@"yes"]] forKey:key]; + } else { + [obj setValue:value forKey:key]; + } } } } |