summaryrefslogtreecommitdiff
path: root/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-wkwebview-engine/src')
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.h27
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.m49
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.h27
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.m480
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.h28
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.m123
-rw-r--r--StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/www/ios/ios-wkwebview-exec.js177
7 files changed, 911 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.h b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.h
new file mode 100644
index 00000000..f4f8816e
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.h
@@ -0,0 +1,27 @@
+/*
+ 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 <WebKit/WebKit.h>
+
+@interface CDVWKProcessPoolFactory : NSObject
+@property (nonatomic, retain) WKProcessPool* sharedPool;
+
++(instancetype) sharedFactory;
+-(WKProcessPool*) sharedProcessPool;
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.m b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.m
new file mode 100644
index 00000000..48ac09e6
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKProcessPoolFactory.m
@@ -0,0 +1,49 @@
+/*
+ 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>
+#import "CDVWKProcessPoolFactory.h"
+
+static CDVWKProcessPoolFactory *factory = nil;
+
+@implementation CDVWKProcessPoolFactory
+
++ (instancetype)sharedFactory
+{
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ factory = [[CDVWKProcessPoolFactory alloc] init];
+ });
+
+ return factory;
+}
+
+- (instancetype)init
+{
+ if (self = [super init]) {
+ _sharedPool = [[WKProcessPool alloc] init];
+ }
+ return self;
+}
+
+- (WKProcessPool*) sharedProcessPool {
+ return _sharedPool;
+}
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.h b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.h
new file mode 100644
index 00000000..2fe4bc21
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.h
@@ -0,0 +1,27 @@
+/*
+ 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 <WebKit/WebKit.h>
+#import <Cordova/CDV.h>
+
+@interface CDVWKWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol, WKScriptMessageHandler, WKNavigationDelegate>
+
+@property (nonatomic, strong, readonly) id <WKUIDelegate> uiDelegate;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.m b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.m
new file mode 100644
index 00000000..e9ff2466
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewEngine.m
@@ -0,0 +1,480 @@
+/*
+ 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 "CDVWKProcessPoolFactory.h"
+#import <Cordova/NSDictionary+CordovaPreferences.h>
+
+#import <objc/message.h>
+
+#define CDV_BRIDGE_NAME @"cordova"
+#define CDV_WKWEBVIEW_FILE_URL_LOAD_SELECTOR @"loadFileURL:allowingReadAccessToURL:"
+
+@interface CDVWKWeakScriptMessageHandler : NSObject <WKScriptMessageHandler>
+
+@property (nonatomic, weak, readonly) id<WKScriptMessageHandler>scriptMessageHandler;
+
+- (instancetype)initWithScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler;
+
+@end
+
+
+@interface CDVWKWebViewEngine ()
+
+@property (nonatomic, strong, readwrite) UIView* engineWebView;
+@property (nonatomic, strong, readwrite) id <WKUIDelegate> uiDelegate;
+@property (nonatomic, weak) id <WKScriptMessageHandler> weakScriptMessageHandler;
+
+@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) {
+ if (NSClassFromString(@"WKWebView") == nil) {
+ return nil;
+ }
+
+ self.engineWebView = [[WKWebView alloc] initWithFrame:frame];
+ }
+
+ return self;
+}
+
+- (WKWebViewConfiguration*) createConfigurationFromSettings:(NSDictionary*)settings
+{
+ WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
+ configuration.processPool = [[CDVWKProcessPoolFactory sharedFactory] sharedProcessPool];
+ if (settings == nil) {
+ return configuration;
+ }
+
+ configuration.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
+ configuration.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
+ configuration.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
+ configuration.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
+ return configuration;
+}
+
+- (void)pluginInitialize
+{
+ // viewController would be available now. we attempt to set all possible delegates to it, by default
+ NSDictionary* settings = self.commandDelegate.settings;
+
+ self.uiDelegate = [[CDVWKWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
+
+ CDVWKWeakScriptMessageHandler *weakScriptMessageHandler = [[CDVWKWeakScriptMessageHandler alloc] initWithScriptMessageHandler:self];
+
+ WKUserContentController* userContentController = [[WKUserContentController alloc] init];
+ [userContentController addScriptMessageHandler:weakScriptMessageHandler name:CDV_BRIDGE_NAME];
+
+ WKWebViewConfiguration* configuration = [self createConfigurationFromSettings:settings];
+ configuration.userContentController = userContentController;
+
+ // re-create WKWebView, since we need to update configuration
+ WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:self.engineWebView.frame configuration:configuration];
+ wkWebView.UIDelegate = self.uiDelegate;
+ self.engineWebView = wkWebView;
+
+ if (IsAtLeastiOSVersion(@"9.0") && [self.viewController isKindOfClass:[CDVViewController class]]) {
+ wkWebView.customUserAgent = ((CDVViewController*) self.viewController).userAgent;
+ }
+
+ if ([self.viewController conformsToProtocol:@protocol(WKUIDelegate)]) {
+ wkWebView.UIDelegate = (id <WKUIDelegate>)self.viewController;
+ }
+
+ if ([self.viewController conformsToProtocol:@protocol(WKNavigationDelegate)]) {
+ wkWebView.navigationDelegate = (id <WKNavigationDelegate>)self.viewController;
+ } else {
+ wkWebView.navigationDelegate = (id <WKNavigationDelegate>)self;
+ }
+
+ if ([self.viewController conformsToProtocol:@protocol(WKScriptMessageHandler)]) {
+ [wkWebView.configuration.userContentController addScriptMessageHandler:(id < WKScriptMessageHandler >)self.viewController name:CDV_BRIDGE_NAME];
+ }
+
+ [self updateSettings:settings];
+
+ // check if content thread has died on resume
+ NSLog(@"%@", @"CDVWKWebViewEngine will reload WKWebView if required on resume");
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onAppWillEnterForeground:)
+ name:UIApplicationWillEnterForegroundNotification object:nil];
+
+ NSLog(@"Using WKWebView");
+
+ [self addURLObserver];
+}
+
+- (void)onReset {
+ [self addURLObserver];
+}
+
+static void * KVOContext = &KVOContext;
+
+- (void)addURLObserver {
+ if(!IsAtLeastiOSVersion(@"9.0")){
+ [self.webView addObserver:self forKeyPath:@"URL" options:0 context:KVOContext];
+ }
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
+{
+ if (context == KVOContext) {
+ if (object == [self webView] && [keyPath isEqualToString: @"URL"] && [object valueForKeyPath:keyPath] == nil){
+ NSLog(@"URL is nil. Reloading WKWebView");
+ [(WKWebView*)_engineWebView reload];
+ }
+ } else {
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ }
+}
+
+- (void) onAppWillEnterForeground:(NSNotification*)notification {
+ if ([self shouldReloadWebView]) {
+ NSLog(@"%@", @"CDVWKWebViewEngine reloading!");
+ [(WKWebView*)_engineWebView reload];
+ }
+}
+
+- (BOOL)shouldReloadWebView
+{
+ WKWebView* wkWebView = (WKWebView*)_engineWebView;
+ return [self shouldReloadWebView:wkWebView.URL title:wkWebView.title];
+}
+
+- (BOOL)shouldReloadWebView:(NSURL*)location title:(NSString*)title
+{
+ BOOL title_is_nil = (title == nil);
+ BOOL location_is_blank = [[location absoluteString] isEqualToString:@"about:blank"];
+
+ BOOL reload = (title_is_nil || location_is_blank);
+
+#ifdef DEBUG
+ NSLog(@"%@", @"CDVWKWebViewEngine shouldReloadWebView::");
+ NSLog(@"CDVWKWebViewEngine shouldReloadWebView title: %@", title);
+ NSLog(@"CDVWKWebViewEngine shouldReloadWebView location: %@", [location absoluteString]);
+ NSLog(@"CDVWKWebViewEngine shouldReloadWebView reload: %u", reload);
+#endif
+
+ return reload;
+}
+
+
+- (id)loadRequest:(NSURLRequest*)request
+{
+ if ([self canLoadRequest:request]) { // can load, differentiate between file urls and other schemes
+ if (request.URL.fileURL) {
+ SEL wk_sel = NSSelectorFromString(CDV_WKWEBVIEW_FILE_URL_LOAD_SELECTOR);
+ NSURL* readAccessUrl = [request.URL URLByDeletingLastPathComponent];
+ return ((id (*)(id, SEL, id, id))objc_msgSend)(_engineWebView, wk_sel, request.URL, readAccessUrl);
+ } else {
+ return [(WKWebView*)_engineWebView loadRequest:request];
+ }
+ } else { // can't load, print out error
+ NSString* errorHtml = [NSString stringWithFormat:
+ @"<!doctype html>"
+ @"<title>Error</title>"
+ @"<div style='font-size:2em'>"
+ @" <p>The WebView engine '%@' is unable to load the request: %@</p>"
+ @" <p>Most likely the cause of the error is that the loading of file urls is not supported in iOS %@.</p>"
+ @"</div>",
+ NSStringFromClass([self class]),
+ [request.URL description],
+ [[UIDevice currentDevice] systemVersion]
+ ];
+ return [self loadHTMLString:errorHtml baseURL:nil];
+ }
+}
+
+- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL
+{
+ return [(WKWebView*)_engineWebView loadHTMLString:string baseURL:baseURL];
+}
+
+- (NSURL*) URL
+{
+ return [(WKWebView*)_engineWebView URL];
+}
+
+- (BOOL) canLoadRequest:(NSURLRequest*)request
+{
+ // See: https://issues.apache.org/jira/browse/CB-9636
+ SEL wk_sel = NSSelectorFromString(CDV_WKWEBVIEW_FILE_URL_LOAD_SELECTOR);
+
+ // if it's a file URL, check whether WKWebView has the selector (which is in iOS 9 and up only)
+ if (request.URL.fileURL) {
+ return [_engineWebView respondsToSelector:wk_sel];
+ } else {
+ return YES;
+ }
+}
+
+- (void)updateSettings:(NSDictionary*)settings
+{
+ WKWebView* wkWebView = (WKWebView*)_engineWebView;
+
+ wkWebView.configuration.preferences.minimumFontSize = [settings cordovaFloatSettingForKey:@"MinimumFontSize" defaultValue:0.0];
+
+ /*
+ wkWebView.configuration.preferences.javaScriptEnabled = [settings cordovaBoolSettingForKey:@"JavaScriptEnabled" default:YES];
+ wkWebView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = [settings cordovaBoolSettingForKey:@"JavaScriptCanOpenWindowsAutomatically" default:NO];
+ */
+
+ // By default, DisallowOverscroll is false (thus bounce is allowed)
+ BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);
+
+ // prevent webView from bouncing
+ if (!bounceAllowed) {
+ if ([wkWebView respondsToSelector:@selector(scrollView)]) {
+ ((UIScrollView*)[wkWebView scrollView]).bounces = NO;
+ } else {
+ for (id subview in wkWebView.subviews) {
+ if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+ ((UIScrollView*)subview).bounces = NO;
+ }
+ }
+ }
+ }
+
+ NSString* decelerationSetting = [settings cordovaSettingForKey:@"WKWebViewDecelerationSpeed"];
+ if (!decelerationSetting) {
+ // Fallback to the UIWebView-named preference
+ decelerationSetting = [settings cordovaSettingForKey:@"UIWebViewDecelerationSpeed"];
+ }
+
+ if (![@"fast" isEqualToString:decelerationSetting]) {
+ [wkWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
+ } else {
+ [wkWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateFast];
+ }
+
+ wkWebView.allowsBackForwardNavigationGestures = [settings cordovaBoolSettingForKey:@"AllowBackForwardNavigationGestures" defaultValue: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;
+}
+
+- (UIView*)webView
+{
+ return self.engineWebView;
+}
+
+#pragma mark WKScriptMessageHandler implementation
+
+- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message
+{
+ if (![message.name isEqualToString:CDV_BRIDGE_NAME]) {
+ return;
+ }
+
+ CDVViewController* vc = (CDVViewController*)self.viewController;
+
+ NSArray* jsonEntry = message.body; // NSString:callbackId, NSString:service, NSString:action, NSArray:args
+ CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry];
+ CDV_EXEC_LOG(@"Exec(%@): Calling %@.%@", command.callbackId, command.className, command.methodName);
+
+ if (![vc.commandQueue execute:command]) {
+#ifdef DEBUG
+ NSError* error = nil;
+ NSString* commandJson = nil;
+ NSData* jsonData = [NSJSONSerialization dataWithJSONObject:jsonEntry
+ options:0
+ error:&error];
+
+ if (error == nil) {
+ commandJson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+ }
+
+ static NSUInteger maxLogLength = 1024;
+ NSString* commandString = ([commandJson length] > maxLogLength) ?
+ [NSString stringWithFormat : @"%@[...]", [commandJson substringToIndex:maxLogLength]] :
+ commandJson;
+
+ NSLog(@"FAILED pluginJSON = %@", commandString);
+#endif
+ }
+}
+
+#pragma mark WKNavigationDelegate implementation
+
+- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation*)navigation
+{
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:webView]];
+}
+
+- (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation
+{
+ CDVViewController* vc = (CDVViewController*)self.viewController;
+ [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
+
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:webView]];
+}
+
+- (void)webView:(WKWebView*)theWebView didFailProvisionalNavigation:(WKNavigation*)navigation withError:(NSError*)error
+{
+ [self webView:theWebView didFailNavigation:navigation withError:error];
+}
+
+- (void)webView:(WKWebView*)theWebView didFailNavigation:(WKNavigation*)navigation withError:(NSError*)error
+{
+ CDVViewController* vc = (CDVViewController*)self.viewController;
+ [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
+
+ NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]];
+ NSLog(@"%@", message);
+
+ NSURL* errorUrl = vc.errorURL;
+ if (errorUrl) {
+ errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl];
+ NSLog(@"%@", [errorUrl absoluteString]);
+ [theWebView loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+ }
+}
+
+- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
+{
+ [webView reload];
+}
+
+- (BOOL)defaultResourcePolicyForURL:(NSURL*)url
+{
+ // all file:// urls are allowed
+ if ([url isFileURL]) {
+ return YES;
+ }
+
+ return NO;
+}
+
+- (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (WKNavigationAction*) navigationAction decisionHandler: (void (^)(WKNavigationActionPolicy)) decisionHandler
+{
+ NSURL* url = [navigationAction.request URL];
+ CDVViewController* vc = (CDVViewController*)self.viewController;
+
+ /*
+ * Give plugins the chance to handle the url
+ */
+ BOOL anyPluginsResponded = NO;
+ BOOL shouldAllowRequest = NO;
+
+ for (NSString* pluginName in vc.pluginObjects) {
+ CDVPlugin* plugin = [vc.pluginObjects objectForKey:pluginName];
+ SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:");
+ if ([plugin respondsToSelector:selector]) {
+ anyPluginsResponded = YES;
+ // https://issues.apache.org/jira/browse/CB-12497
+ int navType = (int)navigationAction.navigationType;
+ if (WKNavigationTypeOther == navigationAction.navigationType) {
+ navType = (int)UIWebViewNavigationTypeOther;
+ }
+ shouldAllowRequest = (((BOOL (*)(id, SEL, id, int))objc_msgSend)(plugin, selector, navigationAction.request, navType));
+ if (!shouldAllowRequest) {
+ break;
+ }
+ }
+ }
+
+ if (anyPluginsResponded) {
+ return decisionHandler(shouldAllowRequest);
+ }
+
+ /*
+ * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview.
+ */
+ BOOL shouldAllowNavigation = [self defaultResourcePolicyForURL:url];
+ if (shouldAllowNavigation) {
+ return decisionHandler(YES);
+ } else {
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+ }
+
+ return decisionHandler(NO);
+}
+
+@end
+
+#pragma mark - CDVWKWeakScriptMessageHandler
+
+@implementation CDVWKWeakScriptMessageHandler
+
+- (instancetype)initWithScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler
+{
+ self = [super init];
+ if (self) {
+ _scriptMessageHandler = scriptMessageHandler;
+ }
+ return self;
+}
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+ [self.scriptMessageHandler userContentController:userContentController didReceiveScriptMessage:message];
+}
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.h b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.h
new file mode 100644
index 00000000..33a179b0
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.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 <WebKit/WebKit.h>
+
+@interface CDVWKWebViewUIDelegate : NSObject <WKUIDelegate>
+
+@property (nonatomic, copy) NSString* title;
+
+- (instancetype)initWithTitle:(NSString*)title;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.m b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.m
new file mode 100644
index 00000000..a7a16f2c
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/ios/CDVWKWebViewUIDelegate.m
@@ -0,0 +1,123 @@
+/*
+ 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 "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 (^)(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
diff --git a/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/www/ios/ios-wkwebview-exec.js b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/www/ios/ios-wkwebview-exec.js
new file mode 100644
index 00000000..2766acc4
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-wkwebview-engine/src/www/ios/ios-wkwebview-exec.js
@@ -0,0 +1,177 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Creates the exec bridge used to notify the native code of
+ * commands.
+ */
+var cordova = require('cordova'),
+ utils = require('cordova/utils'),
+ base64 = require('cordova/base64');
+
+function massageArgsJsToNative(args) {
+ if (!args || utils.typeName(args) != 'Array') {
+ return args;
+ }
+ var ret = [];
+ args.forEach(function(arg, i) {
+ if (utils.typeName(arg) == 'ArrayBuffer') {
+ ret.push({
+ 'CDVType': 'ArrayBuffer',
+ 'data': base64.fromArrayBuffer(arg)
+ });
+ } else {
+ ret.push(arg);
+ }
+ });
+ return ret;
+}
+
+function massageMessageNativeToJs(message) {
+ if (message.CDVType == 'ArrayBuffer') {
+ var stringToArrayBuffer = function(str) {
+ var ret = new Uint8Array(str.length);
+ for (var i = 0; i < str.length; i++) {
+ ret[i] = str.charCodeAt(i);
+ }
+ return ret.buffer;
+ };
+ var base64ToArrayBuffer = function(b64) {
+ return stringToArrayBuffer(atob(b64));
+ };
+ message = base64ToArrayBuffer(message.data);
+ }
+ return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+ var args = [];
+ if (!message || !message.hasOwnProperty('CDVType')) {
+ args.push(message);
+ } else if (message.CDVType == 'MultiPart') {
+ message.messages.forEach(function(e) {
+ args.push(massageMessageNativeToJs(e));
+ });
+ } else {
+ args.push(massageMessageNativeToJs(message));
+ }
+ return args;
+}
+
+var iOSExec = function() {
+
+ // detect change in bridge, if there is a change, we forward to new bridge
+
+ // if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
+ // bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING;
+ // }
+
+ var successCallback, failCallback, service, action, actionArgs;
+ var callbackId = null;
+ if (typeof arguments[0] !== "string") {
+ // FORMAT ONE
+ successCallback = arguments[0];
+ failCallback = arguments[1];
+ service = arguments[2];
+ action = arguments[3];
+ actionArgs = arguments[4];
+
+ // Since we need to maintain backwards compatibility, we have to pass
+ // an invalid callbackId even if no callback was provided since plugins
+ // will be expecting it. The Cordova.exec() implementation allocates
+ // an invalid callbackId and passes it even if no callbacks were given.
+ callbackId = 'INVALID';
+ } else {
+ throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+ 'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);');
+ }
+
+ // If actionArgs is not provided, default to an empty array
+ actionArgs = actionArgs || [];
+
+ // Register the callbacks and add the callbackId to the positional
+ // arguments if given.
+ if (successCallback || failCallback) {
+ callbackId = service + cordova.callbackId++;
+ cordova.callbacks[callbackId] =
+ {success:successCallback, fail:failCallback};
+ }
+
+ actionArgs = massageArgsJsToNative(actionArgs);
+
+ // CB-10133 DataClone DOM Exception 25 guard (fast function remover)
+ var command = [callbackId, service, action, JSON.parse(JSON.stringify(actionArgs))];
+ window.webkit.messageHandlers.cordova.postMessage(command);
+
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+
+ var success = status === 0 || status === 1;
+ var args = convertMessageToArgsNativeToJs(message);
+ setTimeout(function(){
+ cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+ }, 0);
+};
+
+// for backwards compatibility
+iOSExec.nativeEvalAndFetch = function(func) {
+ try {
+ func();
+ } catch (e) {
+ console.log(e);
+ }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+ var cexec = require('cordova/exec');
+ var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+ return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+ cordovaExec().apply(null, arguments);
+}
+
+execProxy.nativeFetchMessages = function() {
+ return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+ return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+ return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
+
+if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) {
+ // unregister the old bridge
+ cordova.define.remove('cordova/exec');
+ // redefine bridge to our new bridge
+ cordova.define("cordova/exec", function(require, exports, module) {
+ module.exports = execProxy;
+ });
+} \ No newline at end of file