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 2014/11/06 11:07:07 UTC

[1/2] Separate the WebViews into plugins, prep for plugin breakout (plus style mixups)

Repository: cordova-ios
Updated Branches:
  refs/heads/wkwebview 5bb424575 -> ce6604dbf


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewEngineProtocol.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewEngineProtocol.h b/CordovaLib/Classes/CDVWebViewEngineProtocol.h
new file mode 100644
index 0000000..0c15c63
--- /dev/null
+++ b/CordovaLib/Classes/CDVWebViewEngineProtocol.h
@@ -0,0 +1,41 @@
+/*
+ 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>
+#import <UIKit/UIKit.h>
+
+#define kCDVWebViewEngineScriptMessageHandlers @"kCDVWebViewEngineScriptMessageHandlers"
+#define kCDVWebViewEngineUIWebViewDelegate @"kCDVWebViewEngineUIWebViewDelegate"
+#define kCDVWebViewEngineWKNavigationDelegate @"kCDVWebViewEngineWKNavigationDelegate"
+#define kCDVWebViewEngineWKUIDelegate @"kCDVWebViewEngineWKUIDelegate"
+#define kCDVWebViewEngineWebViewPreferences @"kCDVWebViewEngineWebViewPreferences"
+
+@protocol CDVWebViewEngineProtocol
+
+@property (nonatomic, strong, readonly) UIView* engineWebView;
+
+- (void)loadRequest:(NSURLRequest*)request;
+- (void)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL;
+- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
+- (void)loadFileURL:(NSURL*)URL allowingReadAccessToURL:(NSURL*)readAccessURL;
+
+- (instancetype)initWithFrame:(CGRect)frame;
+- (void)updateWithInfo:(NSDictionary*)info;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewPreferences.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewPreferences.h b/CordovaLib/Classes/CDVWebViewPreferences.h
deleted file mode 100644
index a57748e..0000000
--- a/CordovaLib/Classes/CDVWebViewPreferences.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- 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>
-#import <UIKit/UIKit.h>
-
-@interface CDVWebViewPreferences : NSObject
-
-@property (nonatomic, strong) NSDictionary* settings;
-
-- (instancetype)initWithWebView:(UIView*)webView settings:(NSDictionary*)settings;
-- (instancetype)initWithSettings:(NSDictionary*)settings;
-
-- (void)update;
-
-- (id)settingForKey:(NSString*)key;
-- (BOOL)boolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue;
-- (CGFloat)floatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewPreferences.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewPreferences.m b/CordovaLib/Classes/CDVWebViewPreferences.m
deleted file mode 100644
index 4ca67cd..0000000
--- a/CordovaLib/Classes/CDVWebViewPreferences.m
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- 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 "CDVWebViewPreferences.h"
-#import "CDVWKWebViewPreferences.h"
-#import "CDVUIWebViewPreferences.h"
-#import "CDVAvailability.h"
-#import <objc/message.h>
-#import <WebKit/WebKit.h>
-
-@implementation CDVWebViewPreferences
-
-- (instancetype)initWithWebView:(UIView*)webView settings:(NSDictionary*)settings
-{
-    self = [super init];
-    if (self) {
-        if ([webView isKindOfClass:[WKWebView class]]) {
-            return [[CDVWKWebViewPreferences alloc] initWithWebView:(WKWebView*)webView settings:settings];
-        } else if ([webView isKindOfClass:[UIWebView class]]) {
-            return [[CDVUIWebViewPreferences alloc] initWithWebView:(UIWebView*)webView settings:settings];
-        } else {
-            return nil;
-        }
-    }
-
-    return self;
-}
-
-- (instancetype)initWithSettings:(NSDictionary*)settings
-{
-    self = [super init];
-    if (self) {
-        self.settings = settings;
-    }
-
-    return self;
-}
-
-- (void)update
-{
-    [NSException raise:@"Invoked abstract method" format:@"Invoked abstract method"];
-}
-
-- (id)settingForKey:(NSString*)key
-{
-    return [self.settings objectForKey:[key lowercaseString]];
-}
-
-- (BOOL)boolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue
-{
-    BOOL value = defaultValue;
-    id prefObj = [self settingForKey:key];
-
-    if (prefObj != nil) {
-        value = [(NSNumber*)prefObj boolValue];
-    }
-
-    return value;
-}
-
-- (CGFloat)floatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue
-{
-    CGFloat value = defaultValue;
-    id prefObj = [self settingForKey:key];
-
-    if (prefObj != nil) {
-        value = [prefObj floatValue];
-    }
-
-    return value;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewProxy.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewProxy.h b/CordovaLib/Classes/CDVWebViewProxy.h
deleted file mode 100644
index 32b9839..0000000
--- a/CordovaLib/Classes/CDVWebViewProxy.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- 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>
-#import <UIKit/UIKit.h>
-
-#ifdef __IPHONE_8_0
-    #pragma message("For iOS 8 - Please add WebKit.framework into your 'Link Binary with Libraries' Build Phase Project Setting. This will be baked in once Xcode 6 is required.")
-#endif /* ifdef __IPHONE_8_0 */
-
-@interface CDVWebViewProxy : NSObject {
-    @private
-    __weak UIView* _webView;
-}
-
-- (instancetype)initWithWebView:(UIView*)webView;
-
-- (void)loadRequest:(NSURLRequest*)request;
-- (void)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL;
-- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
-- (void)loadFileURL:(NSURL*)URL allowingReadAccessToURL:(NSURL*)readAccessURL;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewProxy.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewProxy.m b/CordovaLib/Classes/CDVWebViewProxy.m
deleted file mode 100644
index 03b8049..0000000
--- a/CordovaLib/Classes/CDVWebViewProxy.m
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- 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 <objc/message.h>
-#import <WebKit/WebKit.h>
-#import "CDVWebViewProxy.h"
-
-@interface UIWebView (Extensions)
-
-- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
-
-@end
-
-@implementation UIWebView (Extensions)
-
-- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler
-{
-    NSString* ret = [self stringByEvaluatingJavaScriptFromString:javaScriptString];
-
-    completionHandler(ret, nil);
-}
-
-@end
-
-// see forwardingTargetForSelector: selector comment for the reason for this pragma
-#pragma clang diagnostic ignored "-Wincomplete-implementation"
-
-@implementation CDVWebViewProxy
-
-- (instancetype)initWithWebView:(UIView*)webView
-{
-    self = [super init];
-    if (self) {
-        if (!([webView isKindOfClass:[WKWebView class]] || [webView isKindOfClass:[UIWebView class]])) {
-            return nil;
-        }
-        _webView = webView;
-    }
-
-    return self;
-}
-
-// We implement this here because certain versions of iOS 8 do not implement this
-// in WKWebView, so we need to test for this during runtime.
-// It is speculated that this selector will be available in iOS 8.2 for WKWebView
-- (void)loadFileURL:(NSURL*)url allowingReadAccessToURL:(NSURL*)readAccessURL
-{
-    SEL wk_sel = @selector(loadFileURL:allowingReadAccessToURL:);
-    __weak CDVWebViewProxy* weakSelf = self;
-
-    // UIKit operations have to be on the main thread. This method does not need to be synchronous
-    dispatch_async(dispatch_get_main_queue(), ^{
-            if ([_webView respondsToSelector:wk_sel] && [[url scheme] isEqualToString:@"file"]) {
-                ((id (*)(id, SEL, id, id))objc_msgSend)(_webView, wk_sel, url, readAccessURL);
-            } else {
-                [weakSelf loadRequest:[NSURLRequest requestWithURL:url]];
-            }
-        });
-}
-
-// This forwards the methods that are in the header that are not implemented here.
-// Both WKWebView and UIWebView implement the below:
-//     loadHTMLString:baseURL:
-//     loadRequest:
-//     evaluateJavaScript:completionHandler: (UIWebView implements in Category above)
-- (id)forwardingTargetForSelector:(SEL)aSelector
-{
-    return _webView;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewUIDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewUIDelegate.h b/CordovaLib/Classes/CDVWebViewUIDelegate.h
deleted file mode 100644
index 9ff2ac1..0000000
--- a/CordovaLib/Classes/CDVWebViewUIDelegate.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- 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>
-
-#ifdef __IPHONE_8_0
-    #import <WebKit/WebKit.h>
-#endif
-
-@interface CDVWebViewUIDelegate : NSObject
-#ifdef __IPHONE_8_0
-                                      <WKUIDelegate>
-#endif
-
-@property (nonatomic, copy) NSString* title;
-
-- (instancetype)initWithTitle:(NSString*)title;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewUIDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewUIDelegate.m b/CordovaLib/Classes/CDVWebViewUIDelegate.m
deleted file mode 100644
index 6f98327..0000000
--- a/CordovaLib/Classes/CDVWebViewUIDelegate.m
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- 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.
- */
-
-#ifdef __IPHONE_8_0
-
-#import "CDVWebViewUIDelegate.h"
-
-    @implementation CDVWebViewUIDelegate
-
-    - (instancetype)initWithTitle:(NSString*)title
-    {
-        self = [super init];
-        if (self) {
-            self.title = title;
-        }
-
-        return self;
-    }
-
-    - (void)     webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message
-        initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)())completionHandler
-    {
-        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
-                                                                       message:message
-                                                                preferredStyle:UIAlertControllerStyleAlert];
-
-        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
-                                                     style:UIAlertActionStyleDefault
-                                                   handler:^(UIAlertAction* action)
-            {
-                completionHandler();
-                [alert dismissViewControllerAnimated:YES completion:nil];
-            }];
-
-        [alert addAction:ok];
-
-        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
-
-        [rootController presentViewController:alert animated:YES completion:nil];
-    }
-
-    - (void)     webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message
-        initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler
-    {
-        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
-                                                                       message:message
-                                                                preferredStyle:UIAlertControllerStyleAlert];
-
-        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
-                                                     style:UIAlertActionStyleDefault
-                                                   handler:^(UIAlertAction* action)
-            {
-                completionHandler(YES);
-                [alert dismissViewControllerAnimated:YES completion:nil];
-            }];
-
-        [alert addAction:ok];
-
-        UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
-                                                         style:UIAlertActionStyleDefault
-                                                       handler:^(UIAlertAction* action)
-            {
-                completionHandler(NO);
-                [alert dismissViewControllerAnimated:YES completion:nil];
-            }];
-        [alert addAction:cancel];
-
-        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
-
-        [rootController presentViewController:alert animated:YES completion:nil];
-    }
-
-    - (void)      webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
-              defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame
-        completionHandler:(void (^)(NSString* result))completionHandler
-    {
-        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
-                                                                       message:prompt
-                                                                preferredStyle:UIAlertControllerStyleAlert];
-
-        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
-                                                     style:UIAlertActionStyleDefault
-                                                   handler:^(UIAlertAction* action)
-            {
-                completionHandler(((UITextField*)alert.textFields[0]).text);
-                [alert dismissViewControllerAnimated:YES completion:nil];
-            }];
-
-        [alert addAction:ok];
-
-        UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
-                                                         style:UIAlertActionStyleDefault
-                                                       handler:^(UIAlertAction* action)
-            {
-                completionHandler(nil);
-                [alert dismissViewControllerAnimated:YES completion:nil];
-            }];
-        [alert addAction:cancel];
-
-        [alert addTextFieldWithConfigurationHandler:^(UITextField* textField) {
-            textField.text = defaultText;
-        }];
-
-        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
-
-        [rootController presentViewController:alert animated:YES completion:nil];
-    }
-
-    @end
-#endif /* ifdef __IPHONE_8_0 */

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/NSDictionary+CordovaPreferences.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/NSDictionary+CordovaPreferences.h b/CordovaLib/Classes/NSDictionary+CordovaPreferences.h
new file mode 100644
index 0000000..9be2be2
--- /dev/null
+++ b/CordovaLib/Classes/NSDictionary+CordovaPreferences.h
@@ -0,0 +1,35 @@
+/*
+ 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>
+#import <UIKit/UIKit.h>
+
+@interface NSDictionary (CordovaPreferences)
+
+- (id)cordovaSettingForKey:(NSString*)key;
+- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue;
+- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue;
+
+@end
+
+@interface NSMutableDictionary (CordovaPreferences)
+
+- (void)setCordovaSetting:(id)value forKey:(NSString*)key;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/NSDictionary+CordovaPreferences.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/NSDictionary+CordovaPreferences.m b/CordovaLib/Classes/NSDictionary+CordovaPreferences.m
new file mode 100644
index 0000000..dcac40f
--- /dev/null
+++ b/CordovaLib/Classes/NSDictionary+CordovaPreferences.m
@@ -0,0 +1,63 @@
+/*
+ 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 "NSDictionary+CordovaPreferences.h"
+#import <Foundation/Foundation.h>
+
+@implementation NSDictionary (CordovaPreferences)
+
+- (id)cordovaSettingForKey:(NSString*)key
+{
+    return [self objectForKey:[key lowercaseString]];
+}
+
+- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue
+{
+    BOOL value = defaultValue;
+    id prefObj = [self cordovaSettingForKey:key];
+
+    if (prefObj != nil) {
+        value = [(NSNumber*)prefObj boolValue];
+    }
+
+    return value;
+}
+
+- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue
+{
+    CGFloat value = defaultValue;
+    id prefObj = [self cordovaSettingForKey:key];
+
+    if (prefObj != nil) {
+        value = [prefObj floatValue];
+    }
+
+    return value;
+}
+
+@end
+
+@implementation NSMutableDictionary (CordovaPreferences)
+
+- (void)setCordovaSetting:(id)value forKey:(NSString*)key
+{
+    [self setObject:value forKey:[key lowercaseString]];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 9ce87d3..678fbae 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -12,22 +12,23 @@
 		1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F92F49F1314023E0046367C /* CDVPluginResult.m */; };
 		301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 301F2F2914F3C9CA003FE9FC /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 302965BB13A94E9D007046C5 /* CDVDebug.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		302D72FC19554BFC0028C99F /* CDVWebViewProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D72FA19554BFC0028C99F /* CDVWebViewProxy.m */; };
 		3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
-		303820731955603600C91592 /* CDVWebViewProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 302D72F919554BFC0028C99F /* CDVWebViewProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		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 */; };
 		3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3083EB941A0AF1E100548672 /* CDVWKWebViewEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3083EB921A0AF1E100548672 /* CDVWKWebViewEngine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3083EB951A0AF1E100548672 /* CDVWKWebViewEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3083EB931A0AF1E100548672 /* CDVWKWebViewEngine.m */; };
+		3083EB981A0AF23A00548672 /* CDVUIWebViewEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 3083EB961A0AF23A00548672 /* CDVUIWebViewEngine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3083EB991A0AF23A00548672 /* CDVUIWebViewEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3083EB971A0AF23A00548672 /* CDVUIWebViewEngine.m */; };
+		30B7A65C1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B7A65A1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30B7A65D1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B7A65B1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.m */; };
 		30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */; };
 		30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C684921407044A004C1A8E /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C684931407044A004C1A8E /* CDVURLProtocol.m */; };
-		30CD6C631A07681E00522A22 /* CDVUIWebViewPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 30CD6C611A07681E00522A22 /* CDVUIWebViewPreferences.h */; };
-		30CD6C641A07681E00522A22 /* CDVUIWebViewPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CD6C621A07681E00522A22 /* CDVUIWebViewPreferences.m */; };
-		30CD6C681A0769F900522A22 /* CDVWKWebViewPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CD6C661A0769F900522A22 /* CDVWKWebViewPreferences.m */; };
-		30CD6C691A0769F900522A22 /* CDVWKWebViewPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 30CD6C671A0769F900522A22 /* CDVWKWebViewPreferences.h */; };
+		30D552E11A0AB1F5002007BB /* CDVWebViewEngineProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 30D552E01A0AB1F5002007BB /* CDVWebViewEngineProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E33AF013A7E24B00594D64 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E33AF113A7E24B00594D64 /* CDVPlugin.m */; };
 		30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -38,10 +39,8 @@
 		7E14B5A81705050A0032169E /* CDVTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E14B5A61705050A0032169E /* CDVTimer.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		7E14B5A91705050A0032169E /* CDVTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E14B5A71705050A0032169E /* CDVTimer.m */; };
 		7E22B88519E4C0210026F95E /* CDVAvailabilityDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		7E785B9A196F508900ABBDC8 /* CDVWebViewUIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		7E785B9B196F508900ABBDC8 /* CDVWebViewUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */; };
-		7EE9ECF819525D24004CA6B9 /* CDVWebViewPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		7EE9ECF919525D24004CA6B9 /* CDVWebViewPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */; };
+		7E785B9A196F508900ABBDC8 /* CDVWKWebViewUIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E785B98196F508900ABBDC8 /* CDVWKWebViewUIDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7E785B9B196F508900ABBDC8 /* CDVWKWebViewUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E785B99196F508900ABBDC8 /* CDVWKWebViewUIDelegate.m */; };
 		8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* CDVViewController.m */; };
 		8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -58,8 +57,8 @@
 		EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = EB96673A16A8970900D86CDF /* CDVUserAgentUtil.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 */; };
-		EBFF4DBC16D3FE2E008F452B /* CDVWebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */; };
-		EBFF4DBD16D3FE2E008F452B /* CDVWebViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EBFF4DBC16D3FE2E008F452B /* CDVUIWebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EBFF4DBA16D3FE2E008F452B /* CDVUIWebViewDelegate.m */; };
+		EBFF4DBD16D3FE2E008F452B /* CDVUIWebViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = EBFF4DBB16D3FE2E008F452B /* CDVUIWebViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F858FBC6166009A8007DA594 /* CDVConfigParser.h in Headers */ = {isa = PBXBuildFile; fileRef = F858FBC4166009A8007DA594 /* CDVConfigParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */ = {isa = PBXBuildFile; fileRef = F858FBC5166009A8007DA594 /* CDVConfigParser.m */; };
 /* End PBXBuildFile section */
@@ -70,8 +69,6 @@
 		1F92F49F1314023E0046367C /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPluginResult.m; path = Classes/CDVPluginResult.m; sourceTree = "<group>"; };
 		301F2F2914F3C9CA003FE9FC /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDV.h; path = Classes/CDV.h; sourceTree = "<group>"; };
 		302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree = "<group>"; };
-		302D72F919554BFC0028C99F /* CDVWebViewProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewProxy.h; path = Classes/CDVWebViewProxy.h; sourceTree = "<group>"; };
-		302D72FA19554BFC0028C99F /* CDVWebViewProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewProxy.m; path = Classes/CDVWebViewProxy.m; sourceTree = "<group>"; };
 		30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
 		3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h; sourceTree = "<group>"; };
 		3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m; sourceTree = "<group>"; };
@@ -79,14 +76,17 @@
 		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>"; };
 		3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVScreenOrientationDelegate.h; path = Classes/CDVScreenOrientationDelegate.h; sourceTree = "<group>"; };
+		3083EB921A0AF1E100548672 /* CDVWKWebViewEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWKWebViewEngine.h; path = Classes/CDVWKWebViewEngine.h; sourceTree = "<group>"; };
+		3083EB931A0AF1E100548672 /* CDVWKWebViewEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWKWebViewEngine.m; path = Classes/CDVWKWebViewEngine.m; sourceTree = "<group>"; };
+		3083EB961A0AF23A00548672 /* CDVUIWebViewEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVUIWebViewEngine.h; path = Classes/CDVUIWebViewEngine.h; sourceTree = "<group>"; };
+		3083EB971A0AF23A00548672 /* CDVUIWebViewEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUIWebViewEngine.m; path = Classes/CDVUIWebViewEngine.m; sourceTree = "<group>"; };
+		30B7A65A1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+CordovaPreferences.h"; path = "Classes/NSDictionary+CordovaPreferences.h"; sourceTree = "<group>"; };
+		30B7A65B1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+CordovaPreferences.m"; path = "Classes/NSDictionary+CordovaPreferences.m"; sourceTree = "<group>"; };
 		30C6847E1406CB38004C1A8E /* CDVWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWhitelist.h; path = Classes/CDVWhitelist.h; sourceTree = "<group>"; };
 		30C6847F1406CB38004C1A8E /* CDVWhitelist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWhitelist.m; path = Classes/CDVWhitelist.m; sourceTree = "<group>"; };
 		30C684921407044A004C1A8E /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVURLProtocol.h; path = Classes/CDVURLProtocol.h; sourceTree = "<group>"; };
 		30C684931407044A004C1A8E /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVURLProtocol.m; path = Classes/CDVURLProtocol.m; sourceTree = "<group>"; };
-		30CD6C611A07681E00522A22 /* CDVUIWebViewPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVUIWebViewPreferences.h; path = Classes/CDVUIWebViewPreferences.h; sourceTree = "<group>"; };
-		30CD6C621A07681E00522A22 /* CDVUIWebViewPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUIWebViewPreferences.m; path = Classes/CDVUIWebViewPreferences.m; sourceTree = "<group>"; };
-		30CD6C661A0769F900522A22 /* CDVWKWebViewPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWKWebViewPreferences.m; path = Classes/CDVWKWebViewPreferences.m; sourceTree = "<group>"; };
-		30CD6C671A0769F900522A22 /* CDVWKWebViewPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWKWebViewPreferences.h; path = Classes/CDVWKWebViewPreferences.h; sourceTree = "<group>"; };
+		30D552E01A0AB1F5002007BB /* CDVWebViewEngineProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewEngineProtocol.h; path = Classes/CDVWebViewEngineProtocol.h; sourceTree = "<group>"; };
 		30E33AF013A7E24B00594D64 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPlugin.h; path = Classes/CDVPlugin.h; sourceTree = "<group>"; };
 		30E33AF113A7E24B00594D64 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPlugin.m; path = Classes/CDVPlugin.m; sourceTree = "<group>"; };
 		30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+QueueAdditions.h"; path = "Classes/NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
@@ -109,10 +109,8 @@
 		7E14B5A61705050A0032169E /* CDVTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVTimer.h; path = Classes/CDVTimer.h; sourceTree = "<group>"; };
 		7E14B5A71705050A0032169E /* CDVTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVTimer.m; path = Classes/CDVTimer.m; sourceTree = "<group>"; };
 		7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailabilityDeprecated.h; path = Classes/CDVAvailabilityDeprecated.h; sourceTree = "<group>"; };
-		7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewUIDelegate.h; path = Classes/CDVWebViewUIDelegate.h; sourceTree = "<group>"; };
-		7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewUIDelegate.m; path = Classes/CDVWebViewUIDelegate.m; sourceTree = "<group>"; };
-		7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewPreferences.h; path = Classes/CDVWebViewPreferences.h; sourceTree = "<group>"; };
-		7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewPreferences.m; path = Classes/CDVWebViewPreferences.m; sourceTree = "<group>"; };
+		7E785B98196F508900ABBDC8 /* CDVWKWebViewUIDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWKWebViewUIDelegate.h; path = Classes/CDVWKWebViewUIDelegate.h; sourceTree = "<group>"; };
+		7E785B99196F508900ABBDC8 /* CDVWKWebViewUIDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWKWebViewUIDelegate.m; path = Classes/CDVWKWebViewUIDelegate.m; sourceTree = "<group>"; };
 		8220B5C316D5427E00EC3921 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
 		8852C43614B65FD800F0E735 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVViewController.h; path = Classes/CDVViewController.h; sourceTree = "<group>"; };
 		8852C43714B65FD800F0E735 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVViewController.m; path = Classes/CDVViewController.m; sourceTree = "<group>"; };
@@ -131,8 +129,8 @@
 		EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUserAgentUtil.m; path = Classes/CDVUserAgentUtil.m; sourceTree = "<group>"; };
 		EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+Comparisons.h"; path = "Classes/NSArray+Comparisons.h"; sourceTree = "<group>"; };
 		EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Comparisons.m"; path = "Classes/NSArray+Comparisons.m"; sourceTree = "<group>"; };
-		EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewDelegate.m; path = Classes/CDVWebViewDelegate.m; sourceTree = "<group>"; };
-		EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewDelegate.h; path = Classes/CDVWebViewDelegate.h; sourceTree = "<group>"; };
+		EBFF4DBA16D3FE2E008F452B /* CDVUIWebViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUIWebViewDelegate.m; path = Classes/CDVUIWebViewDelegate.m; sourceTree = "<group>"; };
+		EBFF4DBB16D3FE2E008F452B /* CDVUIWebViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVUIWebViewDelegate.h; path = Classes/CDVUIWebViewDelegate.h; sourceTree = "<group>"; };
 		F858FBC4166009A8007DA594 /* CDVConfigParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVConfigParser.h; path = Classes/CDVConfigParser.h; sourceTree = "<group>"; };
 		F858FBC5166009A8007DA594 /* CDVConfigParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVConfigParser.m; path = Classes/CDVConfigParser.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -190,32 +188,39 @@
 		3054098714B77FF3009841CA /* Cleaver */ = {
 			isa = PBXGroup;
 			children = (
-				30CD6C651A0768DA00522A22 /* Preferences */,
+				30D552DF1A0AB176002007BB /* WKWebView */,
+				30CD6C651A0768DA00522A22 /* UIWebView */,
+				30D552E01A0AB1F5002007BB /* CDVWebViewEngineProtocol.h */,
 				F858FBC4166009A8007DA594 /* CDVConfigParser.h */,
 				F858FBC5166009A8007DA594 /* CDVConfigParser.m */,
 				8852C43614B65FD800F0E735 /* CDVViewController.h */,
 				8852C43714B65FD800F0E735 /* CDVViewController.m */,
 				EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */,
 				EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */,
-				302D72F919554BFC0028C99F /* CDVWebViewProxy.h */,
-				302D72FA19554BFC0028C99F /* CDVWebViewProxy.m */,
-				7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */,
-				7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */,
 			);
 			name = Cleaver;
 			sourceTree = "<group>";
 		};
-		30CD6C651A0768DA00522A22 /* Preferences */ = {
+		30CD6C651A0768DA00522A22 /* UIWebView */ = {
 			isa = PBXGroup;
 			children = (
-				30CD6C671A0769F900522A22 /* CDVWKWebViewPreferences.h */,
-				30CD6C661A0769F900522A22 /* CDVWKWebViewPreferences.m */,
-				30CD6C611A07681E00522A22 /* CDVUIWebViewPreferences.h */,
-				30CD6C621A07681E00522A22 /* CDVUIWebViewPreferences.m */,
-				7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */,
-				7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */,
+				EBFF4DBA16D3FE2E008F452B /* CDVUIWebViewDelegate.m */,
+				EBFF4DBB16D3FE2E008F452B /* CDVUIWebViewDelegate.h */,
+				3083EB961A0AF23A00548672 /* CDVUIWebViewEngine.h */,
+				3083EB971A0AF23A00548672 /* CDVUIWebViewEngine.m */,
 			);
-			name = Preferences;
+			name = UIWebView;
+			sourceTree = "<group>";
+		};
+		30D552DF1A0AB176002007BB /* WKWebView */ = {
+			isa = PBXGroup;
+			children = (
+				7E785B98196F508900ABBDC8 /* CDVWKWebViewUIDelegate.h */,
+				7E785B99196F508900ABBDC8 /* CDVWKWebViewUIDelegate.m */,
+				3083EB921A0AF1E100548672 /* CDVWKWebViewEngine.h */,
+				3083EB931A0AF1E100548672 /* CDVWKWebViewEngine.m */,
+			);
+			name = WKWebView;
 			sourceTree = "<group>";
 		};
 		32C88DFF0371C24200C91783 /* Other Sources */ = {
@@ -230,8 +235,6 @@
 			isa = PBXGroup;
 			children = (
 				7E22B88419E4C0210026F95E /* CDVAvailabilityDeprecated.h */,
-				EBFF4DBA16D3FE2E008F452B /* CDVWebViewDelegate.m */,
-				EBFF4DBB16D3FE2E008F452B /* CDVWebViewDelegate.h */,
 				301F2F2914F3C9CA003FE9FC /* CDV.h */,
 				3034979A1513D56A0090E688 /* CDVLocalStorage.h */,
 				3034979B1513D56A0090E688 /* CDVLocalStorage.m */,
@@ -275,6 +278,8 @@
 				8887FD511090FBE7009987E8 /* NSData+Base64.m */,
 				7E14B5A61705050A0032169E /* CDVTimer.h */,
 				7E14B5A71705050A0032169E /* CDVTimer.m */,
+				30B7A65A1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.h */,
+				30B7A65B1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.m */,
 			);
 			name = Util;
 			sourceTree = "<group>";
@@ -312,21 +317,21 @@
 				7E22B88519E4C0210026F95E /* CDVAvailabilityDeprecated.h in Headers */,
 				3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
 				3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */,
-				30CD6C691A0769F900522A22 /* CDVWKWebViewPreferences.h in Headers */,
 				EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */,
-				30CD6C631A07681E00522A22 /* CDVUIWebViewPreferences.h in Headers */,
 				EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
 				EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
 				1B701028177A61CF00AE11F4 /* CDVShared.h in Headers */,
 				3073E9ED1656D51200957977 /* CDVScreenOrientationDelegate.h in Headers */,
 				F858FBC6166009A8007DA594 /* CDVConfigParser.h in Headers */,
 				30F3930B169F839700B22307 /* CDVJSON.h in Headers */,
-				EBFF4DBD16D3FE2E008F452B /* CDVWebViewDelegate.h in Headers */,
-				7EE9ECF819525D24004CA6B9 /* CDVWebViewPreferences.h in Headers */,
+				EBFF4DBD16D3FE2E008F452B /* CDVUIWebViewDelegate.h in Headers */,
+				30B7A65C1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.h in Headers */,
+				3083EB981A0AF23A00548672 /* CDVUIWebViewEngine.h in Headers */,
+				30D552E11A0AB1F5002007BB /* CDVWebViewEngineProtocol.h in Headers */,
+				3083EB941A0AF1E100548672 /* CDVWKWebViewEngine.h in Headers */,
 				EB96673B16A8970A00D86CDF /* CDVUserAgentUtil.h in Headers */,
 				7E14B5A81705050A0032169E /* CDVTimer.h in Headers */,
-				7E785B9A196F508900ABBDC8 /* CDVWebViewUIDelegate.h in Headers */,
-				303820731955603600C91592 /* CDVWebViewProxy.h in Headers */,
+				7E785B9A196F508900ABBDC8 /* CDVWKWebViewUIDelegate.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -387,8 +392,9 @@
 				8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */,
 				8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */,
 				8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
+				3083EB951A0AF1E100548672 /* CDVWKWebViewEngine.m in Sources */,
 				1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */,
-				7EE9ECF919525D24004CA6B9 /* CDVWebViewPreferences.m in Sources */,
+				30B7A65D1A0B73AF0010C630 /* NSDictionary+CordovaPreferences.m in Sources */,
 				30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */,
 				30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */,
 				30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */,
@@ -398,16 +404,14 @@
 				3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */,
 				EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */,
 				EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
-				30CD6C681A0769F900522A22 /* CDVWKWebViewPreferences.m in Sources */,
 				EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
-				30CD6C641A07681E00522A22 /* CDVUIWebViewPreferences.m in Sources */,
 				F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */,
 				30F3930C169F839700B22307 /* CDVJSON.m in Sources */,
-				7E785B9B196F508900ABBDC8 /* CDVWebViewUIDelegate.m in Sources */,
+				7E785B9B196F508900ABBDC8 /* CDVWKWebViewUIDelegate.m in Sources */,
+				3083EB991A0AF23A00548672 /* CDVUIWebViewEngine.m in Sources */,
 				EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */,
-				EBFF4DBC16D3FE2E008F452B /* CDVWebViewDelegate.m in Sources */,
+				EBFF4DBC16D3FE2E008F452B /* CDVUIWebViewDelegate.m in Sources */,
 				7E14B5A91705050A0032169E /* CDVTimer.m in Sources */,
-				302D72FC19554BFC0028C99F /* CDVWebViewProxy.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/bin/templates/project/__PROJECT_NAME__/config.xml
----------------------------------------------------------------------
diff --git a/bin/templates/project/__PROJECT_NAME__/config.xml b/bin/templates/project/__PROJECT_NAME__/config.xml
index da6c067..c6830d9 100644
--- a/bin/templates/project/__PROJECT_NAME__/config.xml
+++ b/bin/templates/project/__PROJECT_NAME__/config.xml
@@ -36,7 +36,7 @@
     <content src="index.html" />
 
     <!-- Preferences for iOS -->
-    <preference name="UseWKWebView" value="false" />
+    <preference name="CordovaWebViewEngine" value="CDVUIWebViewEngine" />
     <preference name="AllowInlineMediaPlayback" value="false" />
     <preference name="BackupWebStorage" value="cloud" />
     <preference name="DisallowOverscroll" value="false" />


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[2/2] ios commit: Separate the WebViews into plugins, prep for plugin breakout (plus style mixups)

Posted by sh...@apache.org.
Separate the WebViews into plugins, prep for plugin breakout (plus style mixups)


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

Branch: refs/heads/wkwebview
Commit: ce6604dbf1f2e0ecc5f80a94da9da88eac287561
Parents: 5bb4245
Author: Shazron Abdullah <sh...@apache.org>
Authored: Thu Nov 6 02:07:05 2014 -0800
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Thu Nov 6 02:07:05 2014 -0800

----------------------------------------------------------------------
 CordovaLib/Classes/CDV.h                        |  32 +-
 CordovaLib/Classes/CDVCommandDelegateImpl.m     |   2 +-
 CordovaLib/Classes/CDVCommandQueue.m            |   4 +-
 CordovaLib/Classes/CDVPlugin.m                  |   2 +-
 CordovaLib/Classes/CDVUIWebViewDelegate.h       |  42 ++
 CordovaLib/Classes/CDVUIWebViewDelegate.m       | 417 +++++++++++++++++++
 CordovaLib/Classes/CDVUIWebViewEngine.h         |  26 ++
 CordovaLib/Classes/CDVUIWebViewEngine.m         | 164 ++++++++
 CordovaLib/Classes/CDVUIWebViewPreferences.h    |  29 --
 CordovaLib/Classes/CDVUIWebViewPreferences.m    | 103 -----
 CordovaLib/Classes/CDVViewController.h          |   7 +-
 CordovaLib/Classes/CDVViewController.m          | 114 ++---
 CordovaLib/Classes/CDVWKWebViewEngine.h         |  28 ++
 CordovaLib/Classes/CDVWKWebViewEngine.m         | 139 +++++++
 CordovaLib/Classes/CDVWKWebViewPreferences.h    |  29 --
 CordovaLib/Classes/CDVWKWebViewPreferences.m    |  48 ---
 CordovaLib/Classes/CDVWKWebViewUIDelegate.h     |  29 ++
 CordovaLib/Classes/CDVWKWebViewUIDelegate.m     | 126 ++++++
 CordovaLib/Classes/CDVWebViewDelegate.h         |  42 --
 CordovaLib/Classes/CDVWebViewDelegate.m         | 417 -------------------
 CordovaLib/Classes/CDVWebViewEngineProtocol.h   |  41 ++
 CordovaLib/Classes/CDVWebViewPreferences.h      |  36 --
 CordovaLib/Classes/CDVWebViewPreferences.m      |  88 ----
 CordovaLib/Classes/CDVWebViewProxy.h            |  39 --
 CordovaLib/Classes/CDVWebViewProxy.m            |  87 ----
 CordovaLib/Classes/CDVWebViewUIDelegate.h       |  35 --
 CordovaLib/Classes/CDVWebViewUIDelegate.m       | 126 ------
 .../Classes/NSDictionary+CordovaPreferences.h   |  35 ++
 .../Classes/NSDictionary+CordovaPreferences.m   |  63 +++
 CordovaLib/CordovaLib.xcodeproj/project.pbxproj | 106 ++---
 .../project/__PROJECT_NAME__/config.xml         |   2 +-
 31 files changed, 1234 insertions(+), 1224 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDV.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDV.h b/CordovaLib/Classes/CDV.h
index 771bdc5..2d14fc3 100644
--- a/CordovaLib/Classes/CDV.h
+++ b/CordovaLib/Classes/CDV.h
@@ -18,26 +18,32 @@
  */
 
 #import "CDVAvailability.h"
-
-#import "CDVPlugin.h"
-#import "CDVViewController.h"
+#import "CDVAvailabilityDeprecated.h"
 #import "CDVCommandDelegate.h"
-#import "CDVURLProtocol.h"
-#import "CDVInvokedUrlCommand.h"
-
+#import "CDVCommandDelegateImpl.h"
+#import "CDVCommandQueue.h"
+#import "CDVConfigParser.h"
 #import "CDVDebug.h"
-#import "CDVPluginResult.h"
-#import "CDVWhitelist.h"
+#import "CDVInvokedUrlCommand.h"
+#import "CDVJSON.h"
 #import "CDVLocalStorage.h"
+#import "CDVPlugin.h"
+#import "CDVPluginResult.h"
 #import "CDVScreenOrientationDelegate.h"
+#import "CDVShared.h"
 #import "CDVTimer.h"
-#import "CDVWebViewPreferences.h"
-#import "CDVWebViewProxy.h"
-
+#import "CDVUIWebViewDelegate.h"
+#import "CDVUIWebViewEngine.h"
+#import "CDVURLProtocol.h"
+#import "CDVUserAgentUtil.h"
+#import "CDVViewController.h"
+#import "CDVWKWebViewEngine.h"
+#import "CDVWKWebViewUIDelegate.h"
+#import "CDVWebViewEngineProtocol.h"
+#import "CDVWhitelist.h"
 #import "NSArray+Comparisons.h"
 #import "NSData+Base64.h"
+#import "NSDictionary+CordovaPreferences.h"
 #import "NSDictionary+Extensions.h"
 #import "NSMutableArray+QueueAdditions.h"
 #import "UIDevice+Extensions.h"
-
-#import "CDVJSON.h"

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVCommandDelegateImpl.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVCommandDelegateImpl.m b/CordovaLib/Classes/CDVCommandDelegateImpl.m
index 9a5f2aa..7f4254a 100644
--- a/CordovaLib/Classes/CDVCommandDelegateImpl.m
+++ b/CordovaLib/Classes/CDVCommandDelegateImpl.m
@@ -71,7 +71,7 @@
 - (void)evalJsHelper2:(NSString*)js
 {
     CDV_EXEC_LOG(@"Exec: evalling: %@", [js substringToIndex:MIN([js length], 160)]);
-    [_viewController.webViewProxy evaluateJavaScript:js completionHandler:^(id obj, NSError* error) {
+    [_viewController.webViewEngine evaluateJavaScript:js completionHandler:^(id obj, NSError* error) {
         // TODO: obj can be something other than string
         if ([obj isKindOfClass:[NSString class]]) {
             NSString* commandsJSON = (NSString*)obj;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVCommandQueue.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVCommandQueue.m b/CordovaLib/Classes/CDVCommandQueue.m
index 21a6489..efaf640 100644
--- a/CordovaLib/Classes/CDVCommandQueue.m
+++ b/CordovaLib/Classes/CDVCommandQueue.m
@@ -112,8 +112,8 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame.
     __weak CDVCommandQueue* weakSelf = self;
     NSString* js = @"cordova.require('cordova/exec').nativeFetchMessages()";
 
-    [_viewController.webViewProxy evaluateJavaScript:js
-                                   completionHandler:^(id obj, NSError* error) {
+    [_viewController.webViewEngine evaluateJavaScript:js
+                                    completionHandler:^(id obj, NSError* error) {
         if ((error == nil) && [obj isKindOfClass:[NSString class]]) {
             NSString* queuedCommandsJSON = (NSString*)obj;
             CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0);

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVPlugin.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPlugin.m b/CordovaLib/Classes/CDVPlugin.m
index bae6926..ac1ac4d 100644
--- a/CordovaLib/Classes/CDVPlugin.m
+++ b/CordovaLib/Classes/CDVPlugin.m
@@ -132,7 +132,7 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError";
 - (NSString*)writeJavascript:(NSString*)javascript
 {
     // TODO: although deprecated, should have some solution here instead of removing it
-    [((CDVViewController*)self.viewController).webViewProxy evaluateJavaScript : javascript completionHandler : nil]; // bad cast, but ok for now
+    [((CDVViewController*)self.viewController).webViewEngine evaluateJavaScript : javascript completionHandler : nil]; // bad cast, but ok for now
     return @"";
 }
 

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewDelegate.h b/CordovaLib/Classes/CDVUIWebViewDelegate.h
new file mode 100644
index 0000000..05979ed
--- /dev/null
+++ b/CordovaLib/Classes/CDVUIWebViewDelegate.h
@@ -0,0 +1,42 @@
+/*
+ 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 <UIKit/UIKit.h>
+#import "CDVAvailability.h"
+
+/**
+ * Distinguishes top-level navigations from sub-frame navigations.
+ * shouldStartLoadWithRequest is called for every request, but didStartLoad
+ * and didFinishLoad is called only for top-level navigations.
+ * Relevant bug: CB-2389
+ */
+@interface CDVUIWebViewDelegate : NSObject <UIWebViewDelegate>{
+    __weak NSObject <UIWebViewDelegate>* _delegate;
+    NSInteger _loadCount;
+    NSInteger _state;
+    NSInteger _curLoadToken;
+    NSInteger _loadStartPollCount;
+}
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
+- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest CDV_DEPRECATED(3.5, "Use request:isEqualToRequestAfterStrippingFragments: instead.");
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewDelegate.m b/CordovaLib/Classes/CDVUIWebViewDelegate.m
new file mode 100644
index 0000000..230a7fa
--- /dev/null
+++ b/CordovaLib/Classes/CDVUIWebViewDelegate.m
@@ -0,0 +1,417 @@
+/*
+ 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.
+ */
+
+//
+// Testing shows:
+//
+// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
+// When loading a page with a redirect:
+// 1. shouldStartLoading (requestURL is target page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is redirect target)
+// 4. didFinishLoad (request.URL is redirect target)
+//
+// Note the lack of a second didStartLoading **
+//
+// When loading a page with iframes:
+// 1. shouldStartLoading (requestURL is main page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is one of the iframes)
+// 4. didStartLoading
+// 5. didFinishLoad
+// 6. didFinishLoad
+//
+// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
+//
+// Loading a page by calling window.history.go(-1):
+// 1. didStartLoading
+// 2. didFinishLoad
+//
+// Note the lack of a shouldStartLoading call **
+// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
+//
+// Loading a page by calling location.reload()
+// 1. shouldStartLoading
+// 2. didStartLoading
+// 3. didFinishLoad
+//
+// Loading a page with an iframe that fails to load:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 4. didStart
+// 5. didFailWithError
+// 6. didFinish
+//
+// Loading a page with an iframe that fails to load due to an invalid URL:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 5. didFailWithError
+// 6. didFinish
+//
+// This case breaks our logic since there is a missing didStart. To prevent this,
+// we check URLs in shouldStart and return NO if they are invalid.
+//
+// Loading a page with an invalid URL
+// 1. shouldStart (main page)
+// 2. didFailWithError
+//
+// TODO: Record order when page is re-navigated before the first navigation finishes.
+//
+
+#import "CDVUIWebViewDelegate.h"
+#import "CDVAvailability.h"
+
+// #define VerboseLog NSLog
+#define VerboseLog(...) do {} while (0)
+
+typedef enum {
+    STATE_IDLE = 0,
+    STATE_WAITING_FOR_LOAD_START = 1,
+    STATE_WAITING_FOR_LOAD_FINISH = 2,
+    STATE_IOS5_POLLING_FOR_LOAD_START = 3,
+    STATE_IOS5_POLLING_FOR_LOAD_FINISH = 4,
+    STATE_CANCELLED = 5
+} State;
+
+static NSString *stripFragment(NSString* url)
+{
+    NSRange r = [url rangeOfString:@"#"];
+
+    if (r.location == NSNotFound) {
+        return url;
+    }
+    return [url substringToIndex:r.location];
+}
+
+@implementation CDVUIWebViewDelegate
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
+{
+    self = [super init];
+    if (self != nil) {
+        _delegate = delegate;
+        _loadCount = -1;
+        _state = STATE_IDLE;
+    }
+    return self;
+}
+
+- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest
+{
+    return [self request:newRequest isEqualToRequestAfterStrippingFragments:originalRequest];
+}
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
+{
+    if (originalRequest.URL && newRequest.URL) {
+        NSString* originalRequestUrl = [originalRequest.URL absoluteString];
+        NSString* newRequestUrl = [newRequest.URL absoluteString];
+
+        NSString* baseOriginalRequestUrl = stripFragment(originalRequestUrl);
+        NSString* baseNewRequestUrl = stripFragment(newRequestUrl);
+        return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl];
+    }
+
+    return NO;
+}
+
+- (BOOL)isPageLoaded:(UIWebView*)webView
+{
+    NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
+
+    return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+}
+
+- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
+{
+    NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
+
+    return [[NSString stringWithFormat:@"%ld", (long)_curLoadToken] isEqualToString:loadToken];
+}
+
+- (void)setLoadToken:(UIWebView*)webView
+{
+    _curLoadToken += 1;
+    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%ld", (long)_curLoadToken]];
+}
+
+- (NSString*)evalForCurrentURL:(UIWebView*)webView
+{
+    return [webView stringByEvaluatingJavaScriptFromString:@"location.href"];
+}
+
+- (void)pollForPageLoadStart:(UIWebView*)webView
+{
+    if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
+        return;
+    }
+    if (![self isJsLoadTokenSet:webView]) {
+        VerboseLog(@"Polled for page load start. result = YES!");
+        _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
+        [self setLoadToken:webView];
+        if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+            [_delegate webViewDidStartLoad:webView];
+        }
+        [self pollForPageLoadFinish:webView];
+    } else {
+        VerboseLog(@"Polled for page load start. result = NO");
+        // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
+        ++_loadStartPollCount;
+        if (_loadStartPollCount < (1000 * .05)) {
+            [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
+        }
+    }
+}
+
+- (void)pollForPageLoadFinish:(UIWebView*)webView
+{
+    if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
+        return;
+    }
+    if ([self isPageLoaded:webView]) {
+        VerboseLog(@"Polled for page load finish. result = YES!");
+        _state = STATE_IDLE;
+        if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+            [_delegate webViewDidFinishLoad:webView];
+        }
+    } else {
+        VerboseLog(@"Polled for page load finish. result = NO");
+        [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
+    }
+}
+
+- (BOOL)shouldLoadRequest:(NSURLRequest*)request
+{
+    NSString* scheme = [[request URL] scheme];
+
+    if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
+        return YES;
+    }
+
+    return [NSURLConnection canHandleRequest:request];
+}
+
+- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    BOOL shouldLoad = YES;
+
+    if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
+        shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
+    }
+
+    VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
+
+    if (shouldLoad) {
+        // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
+        // mainDocumentURL != URL even though it's a top-level navigation.
+        BOOL isDevToolsRefresh = (request == webView.request);
+        BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
+        if (isTopLevelNavigation) {
+            // Ignore hash changes that don't navigate to a different page.
+            // webView.request does actually update when history.replaceState() gets called.
+            if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
+                NSString* prevURL = [self evalForCurrentURL:webView];
+                if ([prevURL isEqualToString:[request.URL absoluteString]]) {
+                    VerboseLog(@"Page reload detected.");
+                } else {
+                    VerboseLog(@"Detected hash change shouldLoad");
+                    return shouldLoad;
+                }
+            }
+
+            switch (_state) {
+                case STATE_WAITING_FOR_LOAD_FINISH:
+                    // Redirect case.
+                    // We expect loadCount == 1.
+                    if (_loadCount != 1) {
+                        NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
+                    }
+                    break;
+
+                case STATE_IDLE:
+                case STATE_IOS5_POLLING_FOR_LOAD_START:
+                case STATE_CANCELLED:
+                    // Page navigation start.
+                    _loadCount = 0;
+                    _state = STATE_WAITING_FOR_LOAD_START;
+                    break;
+
+                default:
+                    {
+                        _loadCount = 0;
+                        _state = STATE_WAITING_FOR_LOAD_START;
+                        NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
+                        NSLog(@"%@", description);
+                        if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
+                            NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
+                            NSError* error = [[NSError alloc] initWithDomain:@"CDVUIWebViewDelegate" code:1 userInfo:errorDictionary];
+                            [_delegate webView:webView didFailLoadWithError:error];
+                        }
+                    }
+            }
+        } else {
+            // Deny invalid URLs so that we don't get the case where we go straight from
+            // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
+            shouldLoad = shouldLoad && [self shouldLoadRequest:request];
+        }
+        VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
+    }
+    return shouldLoad;
+}
+
+- (void)webViewDidStartLoad:(UIWebView*)webView
+{
+    VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+    switch (_state) {
+        case STATE_IDLE:
+            if (IsAtLeastiOSVersion(@"6.0")) {
+                break;
+            }
+            // If history.go(-1) is used pre-iOS6, the shouldStartLoadWithRequest function is not called.
+            // Without shouldLoad, we can't distinguish an iframe from a top-level navigation.
+            // We could try to distinguish using [UIWebView canGoForward], but that's too much complexity,
+            // and would work only on the first time it was used.
+
+            // Our work-around is to set a JS variable and poll until it disappears (from a navigation).
+            _state = STATE_IOS5_POLLING_FOR_LOAD_START;
+            _loadStartPollCount = 0;
+            [self setLoadToken:webView];
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_CANCELLED:
+            fireCallback = YES;
+            _state = STATE_WAITING_FOR_LOAD_FINISH;
+            _loadCount += 1;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            if (_loadCount != 0) {
+                NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%ld", (long)_loadCount);
+            }
+            fireCallback = YES;
+            _state = STATE_WAITING_FOR_LOAD_FINISH;
+            _loadCount = 1;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            _loadCount += 1;
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+
+        default:
+            NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%ld loadCount=%ld", (long)_state, (long)_loadCount);
+    }
+    VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+        [_delegate webViewDidStartLoad:webView];
+    }
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)webView
+{
+    VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+    switch (_state) {
+        case STATE_IDLE:
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            if (_loadCount == 1) {
+                fireCallback = YES;
+                _state = STATE_IDLE;
+            }
+            _loadCount -= 1;
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+    }
+    VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+        [_delegate webViewDidFinishLoad:webView];
+    }
+}
+
+- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
+{
+    VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+
+    switch (_state) {
+        case STATE_IDLE:
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            if ([error code] == NSURLErrorCancelled) {
+                _state = STATE_CANCELLED;
+            } else {
+                _state = STATE_IDLE;
+            }
+            fireCallback = YES;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            if ([error code] != NSURLErrorCancelled) {
+                if (_loadCount == 1) {
+                    _state = STATE_IDLE;
+                    fireCallback = YES;
+                }
+                _loadCount = -1;
+            } else {
+                fireCallback = YES;
+                _state = STATE_CANCELLED;
+                _loadCount -= 1;
+            }
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+    }
+    VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
+        [_delegate webView:webView didFailLoadWithError:error];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewEngine.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewEngine.h b/CordovaLib/Classes/CDVUIWebViewEngine.h
new file mode 100644
index 0000000..ea1d8f5
--- /dev/null
+++ b/CordovaLib/Classes/CDVUIWebViewEngine.h
@@ -0,0 +1,26 @@
+/*
+ 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>
+#import "CDVWebViewEngineProtocol.h"
+#import "CDVPlugin.h"
+
+@interface CDVUIWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol>
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewEngine.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewEngine.m b/CordovaLib/Classes/CDVUIWebViewEngine.m
new file mode 100644
index 0000000..e81778f
--- /dev/null
+++ b/CordovaLib/Classes/CDVUIWebViewEngine.m
@@ -0,0 +1,164 @@
+/*
+ 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 "CDVUIWebViewEngine.h"
+#import "CDVUIWebViewDelegate.h"
+#import "NSDictionary+CordovaPreferences.h"
+
+#import <objc/message.h>
+
+@interface CDVUIWebViewEngine ()
+
+@property (nonatomic, strong, readwrite) UIView* engineWebView;
+
+@end
+
+// see forwardingTargetForSelector: selector comment for the reason for this pragma
+#pragma clang diagnostic ignored "-Wprotocol"
+
+@implementation CDVUIWebViewEngine
+
+@synthesize engineWebView = _engineWebView;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super init];
+    if (self) {
+        self.engineWebView = [[UIWebView alloc] initWithFrame:frame];
+        NSLog(@"Using UIWebView");
+    }
+
+    return self;
+}
+
+- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler
+{
+    NSString* ret = [(UIWebView*)_engineWebView stringByEvaluatingJavaScriptFromString : javaScriptString];
+
+    if (completionHandler) {
+        completionHandler(ret, nil);
+    }
+}
+
+- (void)loadFileURL:(NSURL*)url allowingReadAccessToURL:(NSURL*)readAccessURL
+{
+    __weak CDVUIWebViewEngine* weakSelf = self;
+
+    // UIKit operations have to be on the main thread. This method does not need to be synchronous
+    dispatch_async(dispatch_get_main_queue(), ^{
+            [weakSelf loadRequest:[NSURLRequest requestWithURL:url]];
+        });
+}
+
+- (void)updateSettings:(NSDictionary*)settings
+{
+    UIWebView* uiWebView = (UIWebView*)_engineWebView;
+
+    uiWebView.scalesPageToFit = [settings cordovaBoolSettingForKey:@"EnableViewportScale" defaultValue:NO];
+    uiWebView.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
+    uiWebView.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
+    uiWebView.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
+    uiWebView.keyboardDisplayRequiresUserAction = [settings cordovaBoolSettingForKey:@"KeyboardDisplayRequiresUserAction" defaultValue:YES];
+    uiWebView.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
+    uiWebView.gapBetweenPages = [settings cordovaFloatSettingForKey:@"GapBetweenPages" defaultValue:0.0];
+    uiWebView.pageLength = [settings cordovaFloatSettingForKey:@"PageLength" defaultValue:0.0];
+
+    id prefObj = nil;
+
+    // By default, DisallowOverscroll is false (thus bounce is allowed)
+    BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);
+
+    // prevent webView from bouncing
+    if (!bounceAllowed) {
+        if ([self.webView respondsToSelector:@selector(scrollView)]) {
+            ((UIScrollView*)[uiWebView scrollView]).bounces = NO;
+        } else {
+            for (id subview in self.webView.subviews) {
+                if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+                    ((UIScrollView*)subview).bounces = NO;
+                }
+            }
+        }
+    }
+
+    NSString* decelerationSetting = [settings cordovaSettingForKey:@"UIWebViewDecelerationSpeed"];
+    if (![@"fast" isEqualToString : decelerationSetting]) {
+        [uiWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
+    }
+
+    NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage
+    prefObj = [settings cordovaSettingForKey:@"PaginationBreakingMode"];
+    if (prefObj != nil) {
+        NSArray* validValues = @[@"page", @"column"];
+        NSString* prefValue = [validValues objectAtIndex:0];
+
+        if ([prefObj isKindOfClass:[NSString class]]) {
+            prefValue = prefObj;
+        }
+
+        paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]];
+        if (paginationBreakingMode == NSNotFound) {
+            paginationBreakingMode = 0;
+        }
+    }
+    uiWebView.paginationBreakingMode = paginationBreakingMode;
+
+    NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated
+    prefObj = [settings cordovaSettingForKey:@"PaginationMode"];
+    if (prefObj != nil) {
+        NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"];
+        NSString* prefValue = [validValues objectAtIndex:0];
+
+        if ([prefObj isKindOfClass:[NSString class]]) {
+            prefValue = prefObj;
+        }
+
+        paginationMode = [validValues indexOfObject:[prefValue lowercaseString]];
+        if (paginationMode == NSNotFound) {
+            paginationMode = 0;
+        }
+    }
+    uiWebView.paginationMode = paginationMode;
+}
+
+- (void)updateWithInfo:(NSDictionary*)info
+{
+    id <UIWebViewDelegate> uiWebViewDelegate = [info objectForKey:kCDVWebViewEngineUIWebViewDelegate];
+    NSDictionary* settings = [info objectForKey:kCDVWebViewEngineWebViewPreferences];
+
+    if (uiWebViewDelegate &&
+        [uiWebViewDelegate conformsToProtocol:@protocol(UIWebViewDelegate)]) {
+        ((UIWebView*)_engineWebView).delegate = uiWebViewDelegate;
+    }
+
+    if (settings && [settings isKindOfClass:[NSDictionary class]]) {
+        [self updateSettings:settings];
+    }
+}
+
+// This forwards the methods that are in the header that are not implemented here.
+// Both WKWebView and UIWebView implement the below:
+//     loadHTMLString:baseURL:
+//     loadRequest:
+- (id)forwardingTargetForSelector:(SEL)aSelector
+{
+    return _engineWebView;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewPreferences.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewPreferences.h b/CordovaLib/Classes/CDVUIWebViewPreferences.h
deleted file mode 100644
index dd5caf9..0000000
--- a/CordovaLib/Classes/CDVUIWebViewPreferences.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- 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 "CDVWebViewPreferences.h"
-#import <UIKit/UIKit.h>
-
-@interface CDVUIWebViewPreferences : CDVWebViewPreferences
-
-@property (nonatomic, weak) UIWebView* webView;
-
-- (instancetype)initWithWebView:(UIWebView*)webView settings:(NSDictionary*)settings;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVUIWebViewPreferences.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVUIWebViewPreferences.m b/CordovaLib/Classes/CDVUIWebViewPreferences.m
deleted file mode 100644
index 5eae9b1..0000000
--- a/CordovaLib/Classes/CDVUIWebViewPreferences.m
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- 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 "CDVUIWebViewPreferences.h"
-
-@implementation CDVUIWebViewPreferences
-
-- (instancetype)initWithWebView:(UIWebView*)webView settings:(NSDictionary*)settings
-{
-    self = [super initWithSettings:settings];
-    if (self) {
-        self.webView = webView;
-    }
-
-    return self;
-}
-
-- (void)update
-{
-    self.webView.scalesPageToFit = [self boolSettingForKey:@"EnableViewportScale" defaultValue:NO];
-    self.webView.allowsInlineMediaPlayback = [self boolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
-    self.webView.mediaPlaybackRequiresUserAction = [self boolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
-    self.webView.mediaPlaybackAllowsAirPlay = [self boolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
-    self.webView.keyboardDisplayRequiresUserAction = [self boolSettingForKey:@"KeyboardDisplayRequiresUserAction" defaultValue:YES];
-    self.webView.suppressesIncrementalRendering = [self boolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
-    self.webView.gapBetweenPages = [self floatSettingForKey:@"GapBetweenPages" defaultValue:0.0];
-    self.webView.pageLength = [self floatSettingForKey:@"PageLength" defaultValue:0.0];
-
-    id prefObj = nil;
-
-    // By default, DisallowOverscroll is false (thus bounce is allowed)
-    BOOL bounceAllowed = !([self boolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);
-
-    // prevent webView from bouncing
-    if (!bounceAllowed) {
-        if ([self.webView respondsToSelector:@selector(scrollView)]) {
-            ((UIScrollView*)[self.webView scrollView]).bounces = NO;
-        } else {
-            for (id subview in self.webView.subviews) {
-                if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
-                    ((UIScrollView*)subview).bounces = NO;
-                }
-            }
-        }
-    }
-
-    NSString* decelerationSetting = [self settingForKey:@"UIWebViewDecelerationSpeed"];
-    if (![@"fast" isEqualToString : decelerationSetting]) {
-        [self.webView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
-    }
-
-    NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage
-    prefObj = [self settingForKey:@"PaginationBreakingMode"];
-    if (prefObj != nil) {
-        NSArray* validValues = @[@"page", @"column"];
-        NSString* prefValue = [validValues objectAtIndex:0];
-
-        if ([prefObj isKindOfClass:[NSString class]]) {
-            prefValue = prefObj;
-        }
-
-        paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]];
-        if (paginationBreakingMode == NSNotFound) {
-            paginationBreakingMode = 0;
-        }
-    }
-    self.webView.paginationBreakingMode = paginationBreakingMode;
-
-    NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated
-    prefObj = [self settingForKey:@"PaginationMode"];
-    if (prefObj != nil) {
-        NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"];
-        NSString* prefValue = [validValues objectAtIndex:0];
-
-        if ([prefObj isKindOfClass:[NSString class]]) {
-            prefValue = prefObj;
-        }
-
-        paginationMode = [validValues indexOfObject:[prefValue lowercaseString]];
-        if (paginationMode == NSNotFound) {
-            paginationMode = 0;
-        }
-    }
-    self.webView.paginationMode = paginationMode;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVViewController.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.h b/CordovaLib/Classes/CDVViewController.h
index e5acc20..453ce30 100644
--- a/CordovaLib/Classes/CDVViewController.h
+++ b/CordovaLib/Classes/CDVViewController.h
@@ -26,7 +26,8 @@
 #import "CDVWhitelist.h"
 #import "CDVScreenOrientationDelegate.h"
 #import "CDVPlugin.h"
-#import "CDVWebViewProxy.h"
+#import "CDVWebViewEngineProtocol.h"
+
 #ifdef __IPHONE_8_0
     #import <WebKit/WebKit.h>
 #else
@@ -38,7 +39,7 @@
 
 @interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate, WKScriptMessageHandler>{
     @protected
-    CDVWebViewProxy* _webViewProxy;
+    id <CDVWebViewEngineProtocol> _webViewEngine;
     @protected
     id <CDVCommandDelegate> _commandDelegate;
     @protected
@@ -58,7 +59,7 @@
 @property (nonatomic, readwrite, copy) NSString* wwwFolderName;
 @property (nonatomic, readwrite, copy) NSString* startPage;
 @property (nonatomic, readonly, strong) CDVCommandQueue* commandQueue;
-@property (nonatomic, readonly, strong) CDVWebViewProxy* webViewProxy;
+@property (nonatomic, readonly, strong) id <CDVWebViewEngineProtocol> webViewEngine;
 @property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate;
 
 /**

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index be31591..10c68ec 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -17,21 +17,20 @@
  under the License.
  */
 
-#import <objc/message.h>
 #import "CDV.h"
 #import "CDVCommandDelegateImpl.h"
 #import "CDVConfigParser.h"
 #import "CDVUserAgentUtil.h"
-#import "CDVWebViewDelegate.h"
-#import "CDVWebViewUIDelegate.h"
+#import "CDVUIWebViewDelegate.h"
+#import "NSDictionary+CordovaPreferences.h"
+
+#import <objc/message.h>
 #import <AVFoundation/AVFoundation.h>
 
 #define degreesToRadian(x) (M_PI * (x) / 180.0)
 
 @interface CDVViewController () {
     NSInteger _userAgentLockToken;
-    CDVWebViewDelegate* _webViewDelegate;
-    CDVWebViewUIDelegate* _webViewUIDelegate;
 }
 
 @property (nonatomic, readwrite, strong) NSXMLParser* configParser;
@@ -42,6 +41,7 @@
 @property (nonatomic, readwrite, strong) NSDictionary* pluginsMap;
 @property (nonatomic, readwrite, strong) NSArray* supportedOrientations;
 @property (nonatomic, readwrite, assign) BOOL loadFromString;
+@property (nonatomic, readwrite, strong) id <CDVWebViewEngineProtocol> webViewEngine;
 
 @property (readwrite, assign) BOOL initialized;
 
@@ -57,7 +57,7 @@
 @synthesize wwwFolderName, startPage, initialized, openURL, baseUserAgent;
 @synthesize commandDelegate = _commandDelegate;
 @synthesize commandQueue = _commandQueue;
-@synthesize webViewProxy = _webViewProxy;
+@synthesize webViewEngine = _webViewEngine;
 
 - (void)__init
 {
@@ -177,13 +177,13 @@
 
     NSURL* url = [NSURL fileURLWithPath:path];
 
-    configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
-    if (configParser == nil) {
+    self.configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
+    if (self.configParser == nil) {
         NSLog(@"Failed to initialize XML parser.");
         return;
     }
-    [configParser setDelegate:((id < NSXMLParserDelegate >)delegate)];
-    [configParser parse];
+    [self.configParser setDelegate:((id < NSXMLParserDelegate >)delegate)];
+    [self.configParser parse];
 
     // Get the plugin dictionary, whitelist and settings from the delegate.
     self.pluginsMap = delegate.pluginsDict;
@@ -237,7 +237,7 @@
 {
     NSURL* errorURL = nil;
 
-    id setting = [self settingForKey:@"ErrorUrl"];
+    id setting = [self.settings cordovaSettingForKey:@"ErrorUrl"];
 
     if (setting) {
         NSString* errorUrlString = (NSString*)setting;
@@ -264,11 +264,11 @@
 
     NSString* backupWebStorageType = @"cloud"; // default value
 
-    id backupWebStorage = [self settingForKey:@"BackupWebStorage"];
+    id backupWebStorage = [self.settings cordovaSettingForKey:@"BackupWebStorage"];
     if ([backupWebStorage isKindOfClass:[NSString class]]) {
         backupWebStorageType = backupWebStorage;
     }
-    [self setSetting:backupWebStorageType forKey:@"BackupWebStorage"];
+    [self.settings setCordovaSetting:backupWebStorageType forKey:@"BackupWebStorage"];
 
     if (IsAtLeastiOSVersion(@"5.1")) {
         [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType];
@@ -280,12 +280,6 @@
         [self createGapView];
     }
 
-    // Configure WebView
-    _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
-    if ([webView respondsToSelector:@selector(setDelegate:)]) {
-        [webView setValue:_webViewDelegate forKey:@"delegate"];
-    }
-
     // register this viewcontroller with the NSURLProtocol, only after the User-Agent is set
     [CDVURLProtocol registerViewController:self];
 
@@ -299,8 +293,9 @@
         [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage class])];
     }
 
-    CDVWebViewPreferences* prefs = [[CDVWebViewPreferences alloc] initWithWebView:webView settings:self.settings];
-    [prefs update];
+    // TODO:
+    //    CDVWebViewPreferences* prefs = [[CDVWebViewPreferences alloc] initWithWebView:webView settings:self.settings];
+    //    [prefs update];
 
     if ([self.startupPluginNames count] > 0) {
         [CDVTimer start:@"TotalPluginStartup"];
@@ -322,7 +317,7 @@
         [CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken];
         if (appURL) {
             NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
-            [_webViewProxy loadRequest:appReq];
+            [self.webViewEngine loadRequest:appReq];
         } else {
             NSString* loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", self.wwwFolderName, self.startPage];
             NSLog(@"%@", loadErr);
@@ -331,25 +326,15 @@
             if (errorUrl) {
                 errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [loadErr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl];
                 NSLog(@"%@", [errorUrl absoluteString]);
-                [_webViewProxy loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+                [self.webViewEngine loadRequest:[NSURLRequest requestWithURL:errorUrl]];
             } else {
                 NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr];
-                [_webViewProxy loadHTMLString:html baseURL:nil];
+                [self.webViewEngine loadHTMLString:html baseURL:nil];
             }
         }
     }];
 }
 
-- (id)settingForKey:(NSString*)key
-{
-    return [[self settings] objectForKey:[key lowercaseString]];
-}
-
-- (void)setSetting:(id)setting forKey:(NSString*)key
-{
-    [[self settings] setObject:setting forKey:[key lowercaseString]];
-}
-
 - (NSArray*)parseInterfaceOrientations:(NSArray*)orientations
 {
     NSMutableArray* result = [[NSMutableArray alloc] init];
@@ -407,7 +392,7 @@
         , (long)[self mapIosOrientationToJsOrientation:interfaceOrientation]];
     __weak CDVViewController* weakSelf = self;
 
-    [_webViewProxy evaluateJavaScript:jsCall completionHandler:^(NSString* obj, NSError* error) {
+    [_webViewEngine evaluateJavaScript:jsCall completionHandler:^(NSString* obj, NSError* error) {
         if ([obj length] > 0) {
             completionHandler([obj boolValue]);
         } else {
@@ -449,37 +434,28 @@
 
 - (UIView*)newCordovaViewWithFrame:(CGRect)bounds
 {
-    UIView* cordovaView = nil;
-    BOOL useWKWebView = NO;  // default value
+    NSString* defaultWebViewEngineClass = @"CDVUIWebViewEngine";
+    NSString* webViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaWebViewEngine"];
 
-    if ([self settingForKey:@"UseWKWebView"]) {
-        useWKWebView = [(NSNumber*)[self settingForKey:@"UseWKWebView"] boolValue];
+    if (!webViewEngineClass) {
+        webViewEngineClass = defaultWebViewEngineClass;
     }
 
-    if (NSClassFromString(@"WKWebView") && useWKWebView) {
-#ifdef __IPHONE_8_0
-            WKUserContentController* userContentController = [[WKUserContentController alloc] init];
-
-            // scriptMessageHandler is the object that conforms to the WKScriptMessageHandler protocol
-            // see https://developer.apple.com/library/prerelease/ios/documentation/WebKit/Reference/WKScriptMessageHandler_Ref/index.html#//apple_ref/swift/intf/WKScriptMessageHandler
-            if ([self conformsToProtocol:@protocol(WKScriptMessageHandler)]) {
-                [userContentController addScriptMessageHandler:self name:@"cordova"];
-            }
-
-            WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
-            configuration.userContentController = userContentController;
-
-            cordovaView = [[WKWebView alloc] initWithFrame:bounds configuration:configuration];
-            NSLog(@"Using a WKWebView");
-            _webViewUIDelegate = [[CDVWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
-            ((WKWebView*)cordovaView).UIDelegate = _webViewUIDelegate;
-#endif
+    // Find webViewEngine
+    if (NSClassFromString(webViewEngineClass)) {
+        self.webViewEngine = [[NSClassFromString(webViewEngineClass) alloc] initWithFrame:bounds];
     } else {
-        cordovaView = [[UIWebView alloc] initWithFrame:bounds];
-        NSLog(@"Using a UIWebView");
+        self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds];
     }
 
-    return cordovaView;
+    NSMutableDictionary* info = [NSMutableDictionary dictionaryWithCapacity:1];
+    [info setValue:@{@"cordova" : self} forKey:kCDVWebViewEngineScriptMessageHandlers];
+    [info setValue:self forKey:kCDVWebViewEngineUIWebViewDelegate];
+    [info setValue:self.settings forKey:kCDVWebViewEngineWebViewPreferences];
+
+    [self.webViewEngine updateWithInfo:info];
+
+    return self.webViewEngine.engineWebView;
 }
 
 - (NSString*)userAgent
@@ -504,9 +480,8 @@
     webViewBounds.origin = self.view.bounds.origin;
 
     self.webView = [self newCordovaViewWithFrame:webViewBounds];
-    self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
-    _webViewProxy = [[CDVWebViewProxy alloc] initWithWebView:self.webView];
 
+    self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
     [self.view addSubview:self.webView];
     [self.view sendSubviewToBack:self.webView];
 }
@@ -541,9 +516,6 @@
     // Release any retained subviews of the main view.
     // e.g. self.myOutlet = nil;
 
-    if ([webView respondsToSelector:@selector(setDelegate:)]) {
-        [webView setValue:nil forKey:@"delegate"];
-    }
     self.webView = nil;
     [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
 
@@ -900,8 +872,8 @@
 
     dispatch_block_t handleOpenUrl = ^(void) {
         NSString* jsString = [NSString stringWithFormat:@"if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}", url];
-        [_webViewProxy evaluateJavaScript:jsString
-                        completionHandler:^(id object, NSError* error) {
+        [_webViewEngine evaluateJavaScript:jsString
+                         completionHandler:^(id object, NSError* error) {
             if (error == nil) {
                 weakSelf.openURL = nil;
             }
@@ -911,8 +883,8 @@
     if (!pageLoaded) {
         // query the webview for readystate
         NSString* jsString = @"document.readystate";
-        [_webViewProxy evaluateJavaScript:jsString
-                        completionHandler:^(id object, NSError* error) {
+        [_webViewEngine evaluateJavaScript:jsString
+                         completionHandler:^(id object, NSError* error) {
             if ((error == nil) && [object isKindOfClass:[NSString class]]) {
                 NSString* readyState = (NSString*)object;
                 BOOL ready = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
@@ -967,10 +939,6 @@
     [CDVURLProtocol unregisterViewController:self];
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 
-    if ([webView respondsToSelector:@selector(setDelegate:)]) {
-        [webView setValue:nil forKey:@"delegate"];
-    }
-
     self.webView = nil;
     [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
     [_commandQueue dispose];

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewEngine.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewEngine.h b/CordovaLib/Classes/CDVWKWebViewEngine.h
new file mode 100644
index 0000000..fde1d11
--- /dev/null
+++ b/CordovaLib/Classes/CDVWKWebViewEngine.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>
+#import "CDVWebViewEngineProtocol.h"
+#import "CDVPlugin.h"
+
+@interface CDVWKWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol>
+
+@property (nonatomic, strong, readonly) id <WKUIDelegate> uiDelegate;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewEngine.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewEngine.m b/CordovaLib/Classes/CDVWKWebViewEngine.m
new file mode 100644
index 0000000..4907572
--- /dev/null
+++ b/CordovaLib/Classes/CDVWKWebViewEngine.m
@@ -0,0 +1,139 @@
+/*
+ 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 "CDVWKWebViewEngine.h"
+#import "CDVWKWebViewUIDelegate.h"
+#import "NSDictionary+CordovaPreferences.h"
+
+#import <objc/message.h>
+#import <WebKit/WebKit.h>
+
+@interface CDVWKWebViewEngine ()
+
+@property (nonatomic, strong, readwrite) UIView* engineWebView;
+@property (nonatomic, strong, readwrite) id <WKUIDelegate> uiDelegate;
+
+@end
+
+// see forwardingTargetForSelector: selector comment for the reason for this pragma
+#pragma clang diagnostic ignored "-Wprotocol"
+
+@implementation CDVWKWebViewEngine
+
+@synthesize engineWebView = _engineWebView;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super init];
+    if (self) {
+        self.uiDelegate = [[CDVWKWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
+
+        WKUserContentController* userContentController = [[WKUserContentController alloc] init];
+
+        WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
+        configuration.userContentController = userContentController;
+
+        WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
+
+        wkWebView.UIDelegate = self.uiDelegate;
+        self.engineWebView = wkWebView;
+
+        NSLog(@"Using WKWebView");
+    }
+
+    return self;
+}
+
+// We implement this here because certain versions of iOS 8 do not implement this
+// in WKWebView, so we need to test for this during runtime.
+// It is speculated that this selector will be available in iOS 8.2 for WKWebView
+- (void)loadFileURL:(NSURL*)url allowingReadAccessToURL:(NSURL*)readAccessURL
+{
+    SEL wk_sel = @selector(loadFileURL:allowingReadAccessToURL:);
+    __weak CDVWKWebViewEngine* weakSelf = self;
+
+    // UIKit operations have to be on the main thread. This method does not need to be synchronous
+    dispatch_async(dispatch_get_main_queue(), ^{
+            if ([_engineWebView respondsToSelector:wk_sel] && [[url scheme] isEqualToString:@"file"]) {
+                ((id (*)(id, SEL, id, id))objc_msgSend)(_engineWebView, wk_sel, url, readAccessURL);
+            } else {
+                [weakSelf loadRequest:[NSURLRequest requestWithURL:url]];
+            }
+        });
+}
+
+- (void)updateSettings:(NSDictionary*)settings
+{
+    WKWebView* wkWebView = (WKWebView*)_engineWebView;
+
+    wkWebView.configuration.preferences.minimumFontSize = [settings cordovaFloatSettingForKey:@"MinimumFontSize" defaultValue:0.0];
+    wkWebView.configuration.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
+    wkWebView.configuration.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
+    wkWebView.configuration.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
+    wkWebView.configuration.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
+
+    /*
+     wkWebView.configuration.preferences.javaScriptEnabled = [settings cordovaBoolSettingForKey:@"JavaScriptEnabled" default:YES];
+     wkWebView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = [settings cordovaBoolSettingForKey:@"JavaScriptCanOpenWindowsAutomatically" default:NO];
+     */
+}
+
+- (void)updateWithInfo:(NSDictionary*)info
+{
+    NSDictionary* scriptMessageHandlers = [info objectForKey:kCDVWebViewEngineScriptMessageHandlers];
+    NSDictionary* settings = [info objectForKey:kCDVWebViewEngineWebViewPreferences];
+    id navigationDelegate = [info objectForKey:kCDVWebViewEngineWKNavigationDelegate];
+    id uiDelegate = [info objectForKey:kCDVWebViewEngineWKUIDelegate];
+
+    WKWebView* wkWebView = (WKWebView*)_engineWebView;
+
+    if (scriptMessageHandlers && [scriptMessageHandlers isKindOfClass:[NSDictionary class]]) {
+        NSArray* allKeys = [scriptMessageHandlers allKeys];
+
+        for (NSString* key in allKeys) {
+            id object = [scriptMessageHandlers objectForKey:key];
+            if ([object conformsToProtocol:@protocol(WKScriptMessageHandler)]) {
+                [wkWebView.configuration.userContentController addScriptMessageHandler:object name:key];
+            }
+        }
+    }
+
+    if (navigationDelegate && [navigationDelegate conformsToProtocol:@protocol(WKNavigationDelegate)]) {
+        wkWebView.navigationDelegate = navigationDelegate;
+    }
+
+    if (uiDelegate && [uiDelegate conformsToProtocol:@protocol(WKUIDelegate)]) {
+        wkWebView.UIDelegate = uiDelegate;
+    }
+
+    if (settings && [settings isKindOfClass:[NSDictionary class]]) {
+        [self updateSettings:settings];
+    }
+}
+
+// This forwards the methods that are in the header that are not implemented here.
+// Both WKWebView and UIWebView implement the below:
+//     loadHTMLString:baseURL:
+//     loadRequest:
+- (id)forwardingTargetForSelector:(SEL)aSelector
+{
+    return _engineWebView;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewPreferences.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewPreferences.h b/CordovaLib/Classes/CDVWKWebViewPreferences.h
deleted file mode 100644
index ffa357a..0000000
--- a/CordovaLib/Classes/CDVWKWebViewPreferences.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- 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 "CDVWebViewPreferences.h"
-#import <WebKit/WebKit.h>
-
-@interface CDVWKWebViewPreferences : CDVWebViewPreferences
-
-@property (nonatomic, weak) WKWebView* webView;
-
-- (instancetype)initWithWebView:(WKWebView*)webView settings:(NSDictionary*)settings;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewPreferences.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewPreferences.m b/CordovaLib/Classes/CDVWKWebViewPreferences.m
deleted file mode 100644
index 6cf1a78..0000000
--- a/CordovaLib/Classes/CDVWKWebViewPreferences.m
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- 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 "CDVWKWebViewPreferences.h"
-
-@implementation CDVWKWebViewPreferences
-
-- (instancetype)initWithWebView:(WKWebView*)webView settings:(NSDictionary*)settings
-{
-    self = [super initWithSettings:settings];
-    if (self) {
-        self.webView = webView;
-    }
-
-    return self;
-}
-
-- (void)update
-{
-    self.webView.configuration.preferences.minimumFontSize = [self floatSettingForKey:@"MinimumFontSize" defaultValue:0.0];
-    self.webView.configuration.allowsInlineMediaPlayback = [self boolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
-    self.webView.configuration.mediaPlaybackRequiresUserAction = [self boolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
-    self.webView.configuration.suppressesIncrementalRendering = [self boolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
-    self.webView.configuration.mediaPlaybackAllowsAirPlay = [self boolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
-
-    /*
-     self.webView.configuration.preferences.javaScriptEnabled = [self boolSettingForKey:@"JavaScriptEnabled" default:YES];
-     self.webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = [self boolSettingForKey:@"JavaScriptCanOpenWindowsAutomatically" default:NO];
-     */
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewUIDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewUIDelegate.h b/CordovaLib/Classes/CDVWKWebViewUIDelegate.h
new file mode 100644
index 0000000..f8971a9
--- /dev/null
+++ b/CordovaLib/Classes/CDVWKWebViewUIDelegate.h
@@ -0,0 +1,29 @@
+/*
+ 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>
+#import <WebKit/WebKit.h>
+
+@interface CDVWKWebViewUIDelegate : NSObject <WKUIDelegate>
+
+@property (nonatomic, copy) NSString* title;
+
+- (instancetype)initWithTitle:(NSString*)title;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWKWebViewUIDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWKWebViewUIDelegate.m b/CordovaLib/Classes/CDVWKWebViewUIDelegate.m
new file mode 100644
index 0000000..e3024b0
--- /dev/null
+++ b/CordovaLib/Classes/CDVWKWebViewUIDelegate.m
@@ -0,0 +1,126 @@
+/*
+ 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.
+ */
+
+#ifdef __IPHONE_8_0
+
+#import "CDVWKWebViewUIDelegate.h"
+
+    @implementation CDVWKWebViewUIDelegate
+
+    - (instancetype)initWithTitle:(NSString*)title
+    {
+        self = [super init];
+        if (self) {
+            self.title = title;
+        }
+
+        return self;
+    }
+
+    - (void)     webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message
+        initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)())completionHandler
+    {
+        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
+                                                                       message:message
+                                                                preferredStyle:UIAlertControllerStyleAlert];
+
+        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
+                                                     style:UIAlertActionStyleDefault
+                                                   handler:^(UIAlertAction* action)
+            {
+                completionHandler();
+                [alert dismissViewControllerAnimated:YES completion:nil];
+            }];
+
+        [alert addAction:ok];
+
+        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
+
+        [rootController presentViewController:alert animated:YES completion:nil];
+    }
+
+    - (void)     webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message
+        initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler
+    {
+        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
+                                                                       message:message
+                                                                preferredStyle:UIAlertControllerStyleAlert];
+
+        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
+                                                     style:UIAlertActionStyleDefault
+                                                   handler:^(UIAlertAction* action)
+            {
+                completionHandler(YES);
+                [alert dismissViewControllerAnimated:YES completion:nil];
+            }];
+
+        [alert addAction:ok];
+
+        UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
+                                                         style:UIAlertActionStyleDefault
+                                                       handler:^(UIAlertAction* action)
+            {
+                completionHandler(NO);
+                [alert dismissViewControllerAnimated:YES completion:nil];
+            }];
+        [alert addAction:cancel];
+
+        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
+
+        [rootController presentViewController:alert animated:YES completion:nil];
+    }
+
+    - (void)      webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
+              defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame
+        completionHandler:(void (^)(NSString* result))completionHandler
+    {
+        UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title
+                                                                       message:prompt
+                                                                preferredStyle:UIAlertControllerStyleAlert];
+
+        UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK")
+                                                     style:UIAlertActionStyleDefault
+                                                   handler:^(UIAlertAction* action)
+            {
+                completionHandler(((UITextField*)alert.textFields[0]).text);
+                [alert dismissViewControllerAnimated:YES completion:nil];
+            }];
+
+        [alert addAction:ok];
+
+        UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
+                                                         style:UIAlertActionStyleDefault
+                                                       handler:^(UIAlertAction* action)
+            {
+                completionHandler(nil);
+                [alert dismissViewControllerAnimated:YES completion:nil];
+            }];
+        [alert addAction:cancel];
+
+        [alert addTextFieldWithConfigurationHandler:^(UITextField* textField) {
+            textField.text = defaultText;
+        }];
+
+        UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController;
+
+        [rootController presentViewController:alert animated:YES completion:nil];
+    }
+
+    @end
+#endif /* ifdef __IPHONE_8_0 */

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewDelegate.h b/CordovaLib/Classes/CDVWebViewDelegate.h
deleted file mode 100644
index 4b60bab..0000000
--- a/CordovaLib/Classes/CDVWebViewDelegate.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- 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 <UIKit/UIKit.h>
-#import "CDVAvailability.h"
-
-/**
- * Distinguishes top-level navigations from sub-frame navigations.
- * shouldStartLoadWithRequest is called for every request, but didStartLoad
- * and didFinishLoad is called only for top-level navigations.
- * Relevant bug: CB-2389
- */
-@interface CDVWebViewDelegate : NSObject <UIWebViewDelegate>{
-    __weak NSObject <UIWebViewDelegate>* _delegate;
-    NSInteger _loadCount;
-    NSInteger _state;
-    NSInteger _curLoadToken;
-    NSInteger _loadStartPollCount;
-}
-
-- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
-- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest CDV_DEPRECATED(3.5, "Use request:isEqualToRequestAfterStrippingFragments: instead.");
-
-- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ce6604db/CordovaLib/Classes/CDVWebViewDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewDelegate.m b/CordovaLib/Classes/CDVWebViewDelegate.m
deleted file mode 100644
index 5a187f4..0000000
--- a/CordovaLib/Classes/CDVWebViewDelegate.m
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- 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.
- */
-
-//
-// Testing shows:
-//
-// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
-// When loading a page with a redirect:
-// 1. shouldStartLoading (requestURL is target page)
-// 2. didStartLoading
-// 3. shouldStartLoading (requestURL is redirect target)
-// 4. didFinishLoad (request.URL is redirect target)
-//
-// Note the lack of a second didStartLoading **
-//
-// When loading a page with iframes:
-// 1. shouldStartLoading (requestURL is main page)
-// 2. didStartLoading
-// 3. shouldStartLoading (requestURL is one of the iframes)
-// 4. didStartLoading
-// 5. didFinishLoad
-// 6. didFinishLoad
-//
-// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
-//
-// Loading a page by calling window.history.go(-1):
-// 1. didStartLoading
-// 2. didFinishLoad
-//
-// Note the lack of a shouldStartLoading call **
-// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
-//
-// Loading a page by calling location.reload()
-// 1. shouldStartLoading
-// 2. didStartLoading
-// 3. didFinishLoad
-//
-// Loading a page with an iframe that fails to load:
-// 1. shouldStart (main page)
-// 2. didStart
-// 3. shouldStart (iframe)
-// 4. didStart
-// 5. didFailWithError
-// 6. didFinish
-//
-// Loading a page with an iframe that fails to load due to an invalid URL:
-// 1. shouldStart (main page)
-// 2. didStart
-// 3. shouldStart (iframe)
-// 5. didFailWithError
-// 6. didFinish
-//
-// This case breaks our logic since there is a missing didStart. To prevent this,
-// we check URLs in shouldStart and return NO if they are invalid.
-//
-// Loading a page with an invalid URL
-// 1. shouldStart (main page)
-// 2. didFailWithError
-//
-// TODO: Record order when page is re-navigated before the first navigation finishes.
-//
-
-#import "CDVWebViewDelegate.h"
-#import "CDVAvailability.h"
-
-// #define VerboseLog NSLog
-#define VerboseLog(...) do {} while (0)
-
-typedef enum {
-    STATE_IDLE = 0,
-    STATE_WAITING_FOR_LOAD_START = 1,
-    STATE_WAITING_FOR_LOAD_FINISH = 2,
-    STATE_IOS5_POLLING_FOR_LOAD_START = 3,
-    STATE_IOS5_POLLING_FOR_LOAD_FINISH = 4,
-    STATE_CANCELLED = 5
-} State;
-
-static NSString *stripFragment(NSString* url)
-{
-    NSRange r = [url rangeOfString:@"#"];
-
-    if (r.location == NSNotFound) {
-        return url;
-    }
-    return [url substringToIndex:r.location];
-}
-
-@implementation CDVWebViewDelegate
-
-- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
-{
-    self = [super init];
-    if (self != nil) {
-        _delegate = delegate;
-        _loadCount = -1;
-        _state = STATE_IDLE;
-    }
-    return self;
-}
-
-- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest
-{
-    return [self request:newRequest isEqualToRequestAfterStrippingFragments:originalRequest];
-}
-
-- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
-{
-    if (originalRequest.URL && newRequest.URL) {
-        NSString* originalRequestUrl = [originalRequest.URL absoluteString];
-        NSString* newRequestUrl = [newRequest.URL absoluteString];
-
-        NSString* baseOriginalRequestUrl = stripFragment(originalRequestUrl);
-        NSString* baseNewRequestUrl = stripFragment(newRequestUrl);
-        return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl];
-    }
-
-    return NO;
-}
-
-- (BOOL)isPageLoaded:(UIWebView*)webView
-{
-    NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
-
-    return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
-}
-
-- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
-{
-    NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
-
-    return [[NSString stringWithFormat:@"%ld", (long)_curLoadToken] isEqualToString:loadToken];
-}
-
-- (void)setLoadToken:(UIWebView*)webView
-{
-    _curLoadToken += 1;
-    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%ld", (long)_curLoadToken]];
-}
-
-- (NSString*)evalForCurrentURL:(UIWebView*)webView
-{
-    return [webView stringByEvaluatingJavaScriptFromString:@"location.href"];
-}
-
-- (void)pollForPageLoadStart:(UIWebView*)webView
-{
-    if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
-        return;
-    }
-    if (![self isJsLoadTokenSet:webView]) {
-        VerboseLog(@"Polled for page load start. result = YES!");
-        _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
-        [self setLoadToken:webView];
-        if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
-            [_delegate webViewDidStartLoad:webView];
-        }
-        [self pollForPageLoadFinish:webView];
-    } else {
-        VerboseLog(@"Polled for page load start. result = NO");
-        // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
-        ++_loadStartPollCount;
-        if (_loadStartPollCount < (1000 * .05)) {
-            [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
-        }
-    }
-}
-
-- (void)pollForPageLoadFinish:(UIWebView*)webView
-{
-    if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
-        return;
-    }
-    if ([self isPageLoaded:webView]) {
-        VerboseLog(@"Polled for page load finish. result = YES!");
-        _state = STATE_IDLE;
-        if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
-            [_delegate webViewDidFinishLoad:webView];
-        }
-    } else {
-        VerboseLog(@"Polled for page load finish. result = NO");
-        [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
-    }
-}
-
-- (BOOL)shouldLoadRequest:(NSURLRequest*)request
-{
-    NSString* scheme = [[request URL] scheme];
-
-    if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
-        return YES;
-    }
-
-    return [NSURLConnection canHandleRequest:request];
-}
-
-- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
-{
-    BOOL shouldLoad = YES;
-
-    if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
-        shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
-    }
-
-    VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
-
-    if (shouldLoad) {
-        // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
-        // mainDocumentURL != URL even though it's a top-level navigation.
-        BOOL isDevToolsRefresh = (request == webView.request);
-        BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
-        if (isTopLevelNavigation) {
-            // Ignore hash changes that don't navigate to a different page.
-            // webView.request does actually update when history.replaceState() gets called.
-            if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
-                NSString* prevURL = [self evalForCurrentURL:webView];
-                if ([prevURL isEqualToString:[request.URL absoluteString]]) {
-                    VerboseLog(@"Page reload detected.");
-                } else {
-                    VerboseLog(@"Detected hash change shouldLoad");
-                    return shouldLoad;
-                }
-            }
-
-            switch (_state) {
-                case STATE_WAITING_FOR_LOAD_FINISH:
-                    // Redirect case.
-                    // We expect loadCount == 1.
-                    if (_loadCount != 1) {
-                        NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
-                    }
-                    break;
-
-                case STATE_IDLE:
-                case STATE_IOS5_POLLING_FOR_LOAD_START:
-                case STATE_CANCELLED:
-                    // Page navigation start.
-                    _loadCount = 0;
-                    _state = STATE_WAITING_FOR_LOAD_START;
-                    break;
-
-                default:
-                    {
-                        _loadCount = 0;
-                        _state = STATE_WAITING_FOR_LOAD_START;
-                        NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
-                        NSLog(@"%@", description);
-                        if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
-                            NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
-                            NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary];
-                            [_delegate webView:webView didFailLoadWithError:error];
-                        }
-                    }
-            }
-        } else {
-            // Deny invalid URLs so that we don't get the case where we go straight from
-            // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
-            shouldLoad = shouldLoad && [self shouldLoadRequest:request];
-        }
-        VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
-    }
-    return shouldLoad;
-}
-
-- (void)webViewDidStartLoad:(UIWebView*)webView
-{
-    VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
-    BOOL fireCallback = NO;
-    switch (_state) {
-        case STATE_IDLE:
-            if (IsAtLeastiOSVersion(@"6.0")) {
-                break;
-            }
-            // If history.go(-1) is used pre-iOS6, the shouldStartLoadWithRequest function is not called.
-            // Without shouldLoad, we can't distinguish an iframe from a top-level navigation.
-            // We could try to distinguish using [UIWebView canGoForward], but that's too much complexity,
-            // and would work only on the first time it was used.
-
-            // Our work-around is to set a JS variable and poll until it disappears (from a navigation).
-            _state = STATE_IOS5_POLLING_FOR_LOAD_START;
-            _loadStartPollCount = 0;
-            [self setLoadToken:webView];
-            [self pollForPageLoadStart:webView];
-            break;
-
-        case STATE_CANCELLED:
-            fireCallback = YES;
-            _state = STATE_WAITING_FOR_LOAD_FINISH;
-            _loadCount += 1;
-            break;
-
-        case STATE_WAITING_FOR_LOAD_START:
-            if (_loadCount != 0) {
-                NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%ld", (long)_loadCount);
-            }
-            fireCallback = YES;
-            _state = STATE_WAITING_FOR_LOAD_FINISH;
-            _loadCount = 1;
-            break;
-
-        case STATE_WAITING_FOR_LOAD_FINISH:
-            _loadCount += 1;
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_START:
-            [self pollForPageLoadStart:webView];
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
-            [self pollForPageLoadFinish:webView];
-            break;
-
-        default:
-            NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%ld loadCount=%ld", (long)_state, (long)_loadCount);
-    }
-    VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
-    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
-        [_delegate webViewDidStartLoad:webView];
-    }
-}
-
-- (void)webViewDidFinishLoad:(UIWebView*)webView
-{
-    VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
-    BOOL fireCallback = NO;
-    switch (_state) {
-        case STATE_IDLE:
-            break;
-
-        case STATE_WAITING_FOR_LOAD_START:
-            NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
-            break;
-
-        case STATE_WAITING_FOR_LOAD_FINISH:
-            if (_loadCount == 1) {
-                fireCallback = YES;
-                _state = STATE_IDLE;
-            }
-            _loadCount -= 1;
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_START:
-            [self pollForPageLoadStart:webView];
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
-            [self pollForPageLoadFinish:webView];
-            break;
-    }
-    VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
-    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
-        [_delegate webViewDidFinishLoad:webView];
-    }
-}
-
-- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
-{
-    VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
-    BOOL fireCallback = NO;
-
-    switch (_state) {
-        case STATE_IDLE:
-            break;
-
-        case STATE_WAITING_FOR_LOAD_START:
-            if ([error code] == NSURLErrorCancelled) {
-                _state = STATE_CANCELLED;
-            } else {
-                _state = STATE_IDLE;
-            }
-            fireCallback = YES;
-            break;
-
-        case STATE_WAITING_FOR_LOAD_FINISH:
-            if ([error code] != NSURLErrorCancelled) {
-                if (_loadCount == 1) {
-                    _state = STATE_IDLE;
-                    fireCallback = YES;
-                }
-                _loadCount = -1;
-            } else {
-                fireCallback = YES;
-                _state = STATE_CANCELLED;
-                _loadCount -= 1;
-            }
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_START:
-            [self pollForPageLoadStart:webView];
-            break;
-
-        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
-            [self pollForPageLoadFinish:webView];
-            break;
-    }
-    VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
-    if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
-        [_delegate webView:webView didFailLoadWithError:error];
-    }
-}
-
-@end


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org