You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2012/11/19 23:44:11 UTC

ios commit: Added CDVInAppBrowser implementation.

Updated Branches:
  refs/heads/master 7e6946daa -> 26a6535c7


Added CDVInAppBrowser implementation.


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/26a6535c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/26a6535c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/26a6535c

Branch: refs/heads/master
Commit: 26a6535c78d65f857749e463655617c971abf2ce
Parents: 7e6946d
Author: Shazron Abdullah <sh...@apache.org>
Authored: Mon Nov 19 14:43:10 2012 -0800
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Mon Nov 19 14:43:10 2012 -0800

----------------------------------------------------------------------
 CordovaLib/Classes/CDV.h                          |    2 +
 CordovaLib/Classes/CDVInAppBrowser.h              |   59 +++
 CordovaLib/Classes/CDVInAppBrowser.m              |  425 ++++++++++++++++
 CordovaLib/Classes/CDVScreenOrientationDelegate.h |   28 +
 CordovaLib/Classes/CDVViewController.h            |    3 +-
 CordovaLib/Classes/CDVViewController.m            |   66 ++--
 CordovaLib/CordovaLib.xcodeproj/project.pbxproj   |   40 +-
 7 files changed, 574 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDV.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDV.h b/CordovaLib/Classes/CDV.h
index fef0f8d..5367799 100644
--- a/CordovaLib/Classes/CDV.h
+++ b/CordovaLib/Classes/CDV.h
@@ -46,6 +46,8 @@
 #import "CDVSplashScreen.h"
 #import "CDVWhitelist.h"
 #import "CDVLocalStorage.h"
+#import "CDVInAppBrowser.h"
+#import "CDVScreenOrientationDelegate.h"
 
 #import "NSArray+Comparisons.h"
 #import "NSData+Base64.h"

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDVInAppBrowser.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInAppBrowser.h b/CordovaLib/Classes/CDVInAppBrowser.h
new file mode 100644
index 0000000..43ba26c
--- /dev/null
+++ b/CordovaLib/Classes/CDVInAppBrowser.h
@@ -0,0 +1,59 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVPlugin.h"
+#import "CDVInvokedUrlCommand.h"
+#import "CDVScreenOrientationDelegate.h"
+
+@class CDVInAppBrowserViewController;
+
+@interface CDVInAppBrowser : CDVPlugin {}
+
+@property (nonatomic, retain) CDVInAppBrowserViewController* inAppBrowserViewController;
+
+- (void)open:(CDVInvokedUrlCommand*)command;
+- (void)close:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVInAppBrowserViewController : UIViewController <UIWebViewDelegate>{}
+
+@property (nonatomic, strong) IBOutlet UIWebView* webView;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* closeButton;
+@property (nonatomic, strong) IBOutlet UILabel* addressLabel;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* backButton;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* forwardButton;
+@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinner;
+@property (nonatomic, strong) IBOutlet UIToolbar* toolbar;
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+
+- (void)close;
+- (void)navigateTo:(NSString*)url;
+- (void)showLocationBar:(BOOL)show;
+
+@end
+
+@interface CDVInAppBrowserOptions : NSObject {}
+
+@property (nonatomic, assign) BOOL location;
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDVInAppBrowser.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInAppBrowser.m b/CordovaLib/Classes/CDVInAppBrowser.m
new file mode 100644
index 0000000..2d87ea7
--- /dev/null
+++ b/CordovaLib/Classes/CDVInAppBrowser.m
@@ -0,0 +1,425 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVInAppBrowser.h"
+#import "CDVPluginResult.h"
+#import "CDVViewController.h"
+
+#define    kInAppBrowserTargetSelf @"_self"
+#define    kInAppBrowserTargetSystem @"_system"
+#define    kInAppBrowserTargetBlank @"_blank"
+
+#define    TOOLBAR_HEIGHT 44.0
+#define    LOCATIONBAR_HEIGHT 21.0
+#define    FOOTER_HEIGHT ((TOOLBAR_HEIGHT) + (LOCATIONBAR_HEIGHT))
+
+#pragma mark CDVInAppBrowser
+
+@implementation CDVInAppBrowser
+
+- (CDVInAppBrowser*)initWithWebView:(UIWebView*)theWebView
+{
+    self = [super initWithWebView:theWebView];
+    if (self != nil) {
+        // your initialization here
+    }
+
+    return self;
+}
+
+- (void)close:(CDVInvokedUrlCommand*)command
+{
+    if (self.inAppBrowserViewController != nil) {
+        [self.inAppBrowserViewController close];
+    }
+}
+
+- (void)open:(CDVInvokedUrlCommand*)command
+{
+    NSArray* arguments = command.arguments;
+    int argc = [arguments count];
+    CDVPluginResult* pluginResult;
+
+    if (argc > 0) {
+        NSString* url = [arguments objectAtIndex:0];
+        NSString* target = (argc > 1) ? [arguments objectAtIndex:1] : kInAppBrowserTargetSelf;
+        NSString* options = (argc > 2) ? [arguments objectAtIndex:2] : @"";
+
+        if ([target isEqualToString:kInAppBrowserTargetSelf]) {
+            [self openInCordovaWebView:url];
+        } else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
+            [self openInSystem:url];
+        } else { // _blank or anything else
+            [self openInInAppBrowser:url withOptions:options];
+        }
+
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    } else {
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"];
+    }
+
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (void)openInInAppBrowser:(NSString*)url withOptions:(NSString*)options
+{
+    if (self.inAppBrowserViewController == nil) {
+        self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] init];
+        if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) {
+            self.inAppBrowserViewController.orientationDelegate = (UIViewController <CDVScreenOrientationDelegate>*)self.viewController;
+        }
+    }
+
+    CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
+    [self.inAppBrowserViewController showLocationBar:browserOptions.location];
+
+    if (self.viewController.modalViewController != self.inAppBrowserViewController) {
+        [self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES];
+    }
+    [self.inAppBrowserViewController navigateTo:url];
+}
+
+- (void)openInCordovaWebView:(NSString*)url
+{
+    NSURL* urlObj = [NSURL URLWithString:url];
+    BOOL passesWhitelist = YES;
+
+    if ([self.viewController isKindOfClass:[CDVViewController class]]) {
+        CDVViewController* vc = (CDVViewController*)self.viewController;
+        if ([vc.whitelist schemeIsAllowed:[urlObj scheme]]) {
+            passesWhitelist = [vc.whitelist URLIsAllowed:urlObj];
+        }
+    } else { // something went wrong, we can't get the whitelist
+        passesWhitelist = NO;
+    }
+
+    if (passesWhitelist) {
+        NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
+        [self.webView loadRequest:request];
+    } else { // TODO: this assumes the InAppBrowser can be excepted from the white-list
+        [self openInInAppBrowser:url withOptions:@""];
+    }
+}
+
+- (void)openInSystem:(NSString*)url
+{
+    NSURL* urlObj = [NSURL URLWithString:url];
+
+    if ([[UIApplication sharedApplication] canOpenURL:urlObj]) {
+        [[UIApplication sharedApplication] openURL:urlObj];
+    } else { // handle any custom schemes to plugins
+        [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:urlObj]];
+    }
+}
+
+@end
+
+#pragma mark CDVInAppBrowserViewController
+
+@implementation CDVInAppBrowserViewController
+
+- (id)init
+{
+    self = [super init];
+    if (self != nil) {
+        // your initialization here
+        [self createViews];
+    }
+
+    return self;
+}
+
+- (void)createViews
+{
+    // We create the views in code for primarily for ease of upgrades and not requiring an external .xib to be included
+
+    CGRect webViewBounds = self.view.bounds;
+
+    webViewBounds.size.height -= FOOTER_HEIGHT;
+
+    if (!self.webView) {
+        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;
+    }
+
+    // TODO: create nav bar, location bar
+
+    self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
+    self.spinner.alpha = 1.000;
+    self.spinner.autoresizesSubviews = YES;
+    self.spinner.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
+    self.spinner.clearsContextBeforeDrawing = NO;
+    self.spinner.clipsToBounds = NO;
+    self.spinner.contentMode = UIViewContentModeScaleToFill;
+    self.spinner.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+    self.spinner.frame = CGRectMake(454.0, 231.0, 20.0, 20.0);
+    self.spinner.hidden = YES;
+    self.spinner.hidesWhenStopped = YES;
+    self.spinner.multipleTouchEnabled = NO;
+    self.spinner.opaque = NO;
+    self.spinner.userInteractionEnabled = NO;
+    [self.spinner stopAnimating];
+
+    self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
+    self.closeButton.enabled = YES;
+    self.closeButton.imageInsets = UIEdgeInsetsZero;
+    self.closeButton.style = UIBarButtonItemStylePlain;
+    self.closeButton.width = 32.000;
+
+    UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
+
+    UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
+    fixedSpaceButton.width = 20;
+
+    self.toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, (self.view.bounds.size.height - TOOLBAR_HEIGHT), self.view.bounds.size.width, TOOLBAR_HEIGHT)];
+    self.toolbar.alpha = 1.000;
+    self.toolbar.autoresizesSubviews = YES;
+    self.toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+    self.toolbar.barStyle = UIBarStyleBlackOpaque;
+    self.toolbar.clearsContextBeforeDrawing = NO;
+    self.toolbar.clipsToBounds = NO;
+    self.toolbar.contentMode = UIViewContentModeScaleToFill;
+    self.toolbar.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+    self.toolbar.hidden = NO;
+    self.toolbar.multipleTouchEnabled = NO;
+    self.toolbar.opaque = NO;
+    self.toolbar.userInteractionEnabled = YES;
+
+    self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, (self.view.bounds.size.height - FOOTER_HEIGHT), self.view.bounds.size.width, LOCATIONBAR_HEIGHT)];
+    self.addressLabel.adjustsFontSizeToFitWidth = NO;
+    self.addressLabel.alpha = 1.000;
+    self.addressLabel.autoresizesSubviews = YES;
+    self.addressLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
+    self.addressLabel.backgroundColor = [UIColor grayColor];
+    self.addressLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
+    self.addressLabel.clearsContextBeforeDrawing = YES;
+    self.addressLabel.clipsToBounds = YES;
+    self.addressLabel.contentMode = UIViewContentModeScaleToFill;
+    self.addressLabel.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+    self.addressLabel.enabled = YES;
+    self.addressLabel.hidden = NO;
+    self.addressLabel.lineBreakMode = UILineBreakModeTailTruncation;
+    self.addressLabel.minimumFontSize = 10.000;
+    self.addressLabel.multipleTouchEnabled = NO;
+    self.addressLabel.numberOfLines = 1;
+    self.addressLabel.opaque = NO;
+    self.addressLabel.shadowOffset = CGSizeMake(0.0, -1.0);
+    self.addressLabel.text = @"Loading...";
+    self.addressLabel.textAlignment = UITextAlignmentLeft;
+    self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000];
+    self.addressLabel.userInteractionEnabled = NO;
+
+    NSString* frontArrowString = @"►"; // create arrow from Unicode char
+    self.forwardButton = [[UIBarButtonItem alloc] initWithTitle:frontArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goForward:)];
+    self.forwardButton.enabled = YES;
+    self.forwardButton.imageInsets = UIEdgeInsetsZero;
+
+    NSString* backArrowString = @"◄"; // create arrow from Unicode char
+    self.backButton = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goBack:)];
+    self.backButton.enabled = YES;
+    self.backButton.imageInsets = UIEdgeInsetsZero;
+
+    [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]];
+
+    [self.view addSubview:self.toolbar];
+    [self.view addSubview:self.addressLabel];
+    [self.view addSubview:self.spinner];
+}
+
+- (void)showLocationBar:(BOOL)show
+{
+    CGRect addressLabelFrame = self.addressLabel.frame;
+    BOOL locationBarVisible = (addressLabelFrame.size.height > 0);
+
+    // prevent double show/hide
+    if (locationBarVisible == show) {
+        return;
+    }
+
+    if (show) {
+        CGRect webViewBounds = self.view.bounds;
+        webViewBounds.size.height -= FOOTER_HEIGHT;
+        self.webView.frame = webViewBounds;
+
+        CGRect addressLabelFrame = self.addressLabel.frame;
+        addressLabelFrame.size.height = LOCATIONBAR_HEIGHT;
+        self.addressLabel.frame = addressLabelFrame;
+    } else {
+        CGRect webViewBounds = self.view.bounds;
+        webViewBounds.size.height -= TOOLBAR_HEIGHT;
+        self.webView.frame = webViewBounds;
+
+        CGRect addressLabelFrame = self.addressLabel.frame;
+        addressLabelFrame.size.height = 0;
+        self.addressLabel.frame = addressLabelFrame;
+    }
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+}
+
+- (void)close
+{
+    if ([self respondsToSelector:@selector(presentingViewController)]) {
+        [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
+    } else {
+        [[self parentViewController] dismissModalViewControllerAnimated:YES];
+    }
+}
+
+- (void)navigateTo:(NSString*)url
+{
+    NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
+
+    [self.webView loadRequest:request];
+}
+
+- (void)goBack:(id)sender
+{
+    [self.webView goBack];
+}
+
+- (void)goForward:(id)sender
+{
+    [self.webView goForward];
+}
+
+#pragma mark UIWebViewDelegate
+
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+    // loading url, start spinner, update back/forward
+
+    self.addressLabel.text = @"Loading...";
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+
+    [self.spinner startAnimating];
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    // update url, stop spinner, update back/forward
+
+    self.addressLabel.text = theWebView.request.URL.absoluteString;
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+
+    [self.spinner stopAnimating];
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    // log fail message, stop spinner, update back/forward
+    NSLog(@"webView:didFailLoadWithError - %@", [error localizedDescription]);
+
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+    [self.spinner stopAnimating];
+
+    self.addressLabel.text = @"Load Error";
+}
+
+#pragma mark CDVScreenOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+        return [self.orientationDelegate shouldAutorotate];
+    }
+    return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+        return [self.orientationDelegate supportedInterfaceOrientations];
+    }
+
+    return 1 << UIInterfaceOrientationPortrait;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
+@end
+
+@implementation CDVInAppBrowserOptions
+
+- (id)init
+{
+    if (self = [super init]) {
+        // default values
+        self.location = YES;
+    }
+
+    return self;
+}
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
+{
+    CDVInAppBrowserOptions* obj = [[CDVInAppBrowserOptions alloc] init];
+
+    // NOTE: this parsing does not handle quotes within values
+    NSArray* pairs = [options componentsSeparatedByString:@","];
+
+    // parse keys and values, set the properties
+    for (NSString* pair in pairs) {
+        NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
+
+        if ([keyvalue count] == 2) {
+            NSString* key = [[keyvalue objectAtIndex:0] lowercaseString];
+            NSString* value = [keyvalue objectAtIndex:1];
+            BOOL valueBool = [[value lowercaseString] isEqualToString:@"yes"];
+
+            // set the property according to the key name
+            if ([obj respondsToSelector:NSSelectorFromString(key)]) {
+                [obj setValue:[NSNumber numberWithBool:valueBool] forKey:key];
+            }
+        }
+    }
+
+    return obj;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDVScreenOrientationDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVScreenOrientationDelegate.h b/CordovaLib/Classes/CDVScreenOrientationDelegate.h
new file mode 100644
index 0000000..7226205
--- /dev/null
+++ b/CordovaLib/Classes/CDVScreenOrientationDelegate.h
@@ -0,0 +1,28 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol CDVScreenOrientationDelegate <NSObject>
+
+- (NSUInteger)supportedInterfaceOrientations;
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
+- (BOOL)shouldAutorotate;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDVViewController.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.h b/CordovaLib/Classes/CDVViewController.h
index 0cf717f..16f6682 100644
--- a/CordovaLib/Classes/CDVViewController.h
+++ b/CordovaLib/Classes/CDVViewController.h
@@ -24,11 +24,12 @@
 #import "CDVInvokedUrlCommand.h"
 #import "CDVCommandDelegate.h"
 #import "CDVWhitelist.h"
+#import "CDVScreenOrientationDelegate.h"
 
 @class CDVCommandQueue;
 @class CDVCommandDelegateImpl;
 
-@interface CDVViewController : UIViewController <UIWebViewDelegate>{
+@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{
     @private
     CDVCommandDelegateImpl* _commandDelegate;
 }

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index f21b766..889bce3 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -522,30 +522,32 @@
      */
     else if ([url isFileURL]) {
         return YES;
-    } else if ([self.whitelist schemeIsAllowed:[url scheme]]) {
-        if ([self.whitelist URLIsAllowed:url] == YES) {
-            NSNumber* openAllInWhitelistSetting = [self.settings objectForKey:@"OpenAllWhitelistURLsInWebView"];
-            if ((nil != openAllInWhitelistSetting) && [openAllInWhitelistSetting boolValue]) {
-                NSLog(@"OpenAllWhitelistURLsInWebView set: opening in webview");
-                return YES;
-            }
-
-            // mainDocument will be nil for an iFrame
-            NSString* mainDocument = [theWebView.request.mainDocumentURL absoluteString];
-
-            // anchor target="_blank" - load in Mobile Safari
-            if ((navigationType == UIWebViewNavigationTypeOther) && (mainDocument != nil)) {
-                [[UIApplication sharedApplication] openURL:url];
-                return NO;
-            }
-            // other anchor target - load in Cordova webView
-            else {
-                return YES;
-            }
-        }
-
-        return NO;
     }
+    //    else if ([self.whitelist schemeIsAllowed:[url scheme]]) {
+    //        if ([self.whitelist URLIsAllowed:url] == YES) {
+    //            NSNumber* openAllInWhitelistSetting = [self.settings objectForKey:@"OpenAllWhitelistURLsInWebView"];
+    //            if ((nil != openAllInWhitelistSetting) && [openAllInWhitelistSetting boolValue]) {
+    //                NSLog(@"OpenAllWhitelistURLsInWebView set: opening in webview");
+    //                return YES;
+    //            }
+    //
+    //            // mainDocument will be nil for an iFrame
+    //            NSString* mainDocument = [theWebView.request.mainDocumentURL absoluteString];
+    //
+    //            // anchor target="_blank" - load in Mobile Safari
+    //            if ((navigationType == UIWebViewNavigationTypeOther) && (mainDocument != nil)) {
+    //                [[UIApplication sharedApplication] openURL:url];
+    //                return NO;
+    //            }
+    //            // other anchor target - load in Cordova webView
+    //            else {
+    //                return YES;
+    //            }
+    //        }
+    //
+    //        return NO;
+    //    }
+    //
 
     /*
      *    If we loaded the HTML from a string, we let the app handle it
@@ -577,16 +579,20 @@
     }
 
     /*
-     * We don't have a Cordova or web/local request, load it in the main Safari browser.
-     * pass this to the application to handle.  Could be a mailto:dude@duderanch.com or a tel:55555555 or sms:55555555 facetime:55555555
+     * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview.
      */
     else {
-        NSLog(@"AppDelegate::shouldStartLoadWithRequest: Received Unhandled URL %@", url);
+        // BOOL isIFrame = ([theWebView.request.mainDocumentURL absoluteString] == nil);
 
-        if ([[UIApplication sharedApplication] canOpenURL:url]) {
-            [[UIApplication sharedApplication] openURL:url];
-        } else { // handle any custom schemes to plugins
-            [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+        if ([self.whitelist schemeIsAllowed:[url scheme]] &&
+            [self.whitelist URLIsAllowed:url]) {
+            return YES;
+        } else {
+            if ([[UIApplication sharedApplication] canOpenURL:url]) {
+                [[UIApplication sharedApplication] openURL:url];
+            } else { // handle any custom schemes to plugins
+                [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+            }
         }
 
         return NO;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/26a6535c/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 1f7a618..e353c3d 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -22,6 +22,9 @@
 		30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */; };
+		3073E9E91656D37700957977 /* CDVInAppBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3073E9E71656D37700957977 /* CDVInAppBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3073E9EA1656D37700957977 /* CDVInAppBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3073E9E81656D37700957977 /* CDVInAppBrowser.m */; };
+		3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 307A8F9C1385A2EC00E43782 /* CDVConnection.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 307A8F9D1385A2EC00E43782 /* CDVConnection.m */; };
 		30A90B9114588697006178D3 /* JSONKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A90B8F14588697006178D3 /* JSONKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -69,15 +72,15 @@
 		8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD611090FBE7009987E8 /* CDVSound.m */; };
 		88BA573D109BB46F00FB5E78 /* CDVAccelerometer.h in Headers */ = {isa = PBXBuildFile; fileRef = 88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		88BA573E109BB46F00FB5E78 /* CDVAccelerometer.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */; };
-		9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */; };
+		9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */; };
 		C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef = C937A4541337599E002C4C79 /* CDVFileTransfer.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */ = {isa = PBXBuildFile; fileRef = C937A4551337599E002C4C79 /* CDVFileTransfer.m */; };
-		EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */; };
+		EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */; };
-		EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; };
+		EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */; };
-		EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */ = {isa = PBXBuildFile; fileRef = EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */; };
+		EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */ = {isa = PBXBuildFile; fileRef = EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */ = {isa = PBXBuildFile; fileRef = EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */; };
 		EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */ = {isa = PBXBuildFile; fileRef = EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */ = {isa = PBXBuildFile; fileRef = EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */; };
@@ -100,6 +103,9 @@
 		30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailability.h; path = Classes/CDVAvailability.h; sourceTree = "<group>"; };
 		3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIDevice+Extensions.h"; path = "Classes/UIDevice+Extensions.h"; sourceTree = "<group>"; };
 		3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIDevice+Extensions.m"; path = "Classes/UIDevice+Extensions.m"; sourceTree = "<group>"; };
+		3073E9E71656D37700957977 /* CDVInAppBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVInAppBrowser.h; path = Classes/CDVInAppBrowser.h; sourceTree = "<group>"; };
+		3073E9E81656D37700957977 /* CDVInAppBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVInAppBrowser.m; path = Classes/CDVInAppBrowser.m; sourceTree = "<group>"; };
+		3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVScreenOrientationDelegate.h; path = Classes/CDVScreenOrientationDelegate.h; sourceTree = "<group>"; };
 		307A8F9C1385A2EC00E43782 /* CDVConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVConnection.h; path = Classes/CDVConnection.h; sourceTree = "<group>"; };
 		307A8F9D1385A2EC00E43782 /* CDVConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVConnection.m; path = Classes/CDVConnection.m; sourceTree = "<group>"; };
 		30A90B8F14588697006178D3 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
@@ -302,6 +308,9 @@
 				3E76876C156A90EE00EB6FA3 /* CDVLogger.h */,
 				9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */,
 				9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */,
+				3073E9E71656D37700957977 /* CDVInAppBrowser.h */,
+				3073E9E81656D37700957977 /* CDVInAppBrowser.m */,
+				3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */,
 			);
 			name = Commands;
 			sourceTree = "<group>";
@@ -391,6 +400,8 @@
 				EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
 				EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
 				9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */,
+				3073E9E91656D37700957977 /* CDVInAppBrowser.h in Headers */,
+				3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -483,6 +494,7 @@
 				EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
 				EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
 				9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */,
+				3073E9EA1656D37700957977 /* CDVInAppBrowser.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -493,9 +505,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				"ARCHS[sdk=iphoneos*]" = (
-					armv7,
-				);
+				"ARCHS[sdk=iphoneos*]" = armv7;
 				"ARCHS[sdk=iphoneos6.*]" = (
 					armv7,
 					armv7s,
@@ -513,7 +523,7 @@
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				INSTALL_PATH = /usr/local/lib;
-				IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+				IPHONEOS_DEPLOYMENT_TARGET = 5.0;
 				PRODUCT_NAME = Cordova;
 				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
 				SKIP_INSTALL = YES;
@@ -524,9 +534,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				"ARCHS[sdk=iphoneos*]" = (
-					armv7,
-				);
+				"ARCHS[sdk=iphoneos*]" = armv7;
 				"ARCHS[sdk=iphoneos6.*]" = (
 					armv7,
 					armv7s,
@@ -541,7 +549,7 @@
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				INSTALL_PATH = /usr/local/lib;
-				IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+				IPHONEOS_DEPLOYMENT_TARGET = 5.0;
 				PRODUCT_NAME = Cordova;
 				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
 				SKIP_INSTALL = YES;
@@ -551,9 +559,7 @@
 		1DEB922308733DC00010E9CD /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				"ARCHS[sdk=iphoneos*]" = (
-					armv7,
-				);
+				"ARCHS[sdk=iphoneos*]" = armv7;
 				"ARCHS[sdk=iphoneos6.*]" = (
 					armv7,
 					armv7s,
@@ -581,9 +587,7 @@
 		1DEB922408733DC00010E9CD /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				"ARCHS[sdk=iphoneos*]" = (
-					armv7,
-				);
+				"ARCHS[sdk=iphoneos*]" = armv7;
 				"ARCHS[sdk=iphoneos6.*]" = (
 					armv7,
 					armv7s,