aboutsummaryrefslogtreecommitdiffstats
path: root/iPhone/CordovaLib/Classes/CDVInAppBrowser.m
diff options
context:
space:
mode:
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVInAppBrowser.m')
-rwxr-xr-xiPhone/CordovaLib/Classes/CDVInAppBrowser.m162
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];
+ }
}
}
}