summaryrefslogtreecommitdiff
path: root/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios')
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.h112
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.h27
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.m63
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.h50
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.m90
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.h80
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.m (renamed from StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.m)1030
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.h32
-rw-r--r--StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.m127
9 files changed, 1077 insertions, 534 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.h b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.h
deleted file mode 100644
index 6bb0ec16..00000000
--- a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.h
+++ /dev/null
@@ -1,112 +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 <Cordova/CDVPlugin.h>
-#import <Cordova/CDVInvokedUrlCommand.h>
-#import <Cordova/CDVScreenOrientationDelegate.h>
-
-#ifdef __CORDOVA_4_0_0
- #import <Cordova/CDVUIWebViewDelegate.h>
-#else
- #import <Cordova/CDVWebViewDelegate.h>
-#endif
-
-@class CDVInAppBrowserViewController;
-
-@interface CDVInAppBrowser : CDVPlugin {
-}
-
-@property (nonatomic, retain) CDVInAppBrowserViewController* inAppBrowserViewController;
-@property (nonatomic, copy) NSString* callbackId;
-@property (nonatomic, copy) NSRegularExpression *callbackIdPattern;
-
-- (void)open:(CDVInvokedUrlCommand*)command;
-- (void)close:(CDVInvokedUrlCommand*)command;
-- (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
-- (void)show:(CDVInvokedUrlCommand*)command;
-
-@end
-
-@interface CDVInAppBrowserOptions : NSObject {}
-
-@property (nonatomic, assign) BOOL location;
-@property (nonatomic, assign) BOOL toolbar;
-@property (nonatomic, copy) NSString* closebuttoncaption;
-@property (nonatomic, copy) NSString* toolbarposition;
-@property (nonatomic, assign) BOOL clearcache;
-@property (nonatomic, assign) BOOL clearsessioncache;
-
-@property (nonatomic, copy) NSString* presentationstyle;
-@property (nonatomic, copy) NSString* transitionstyle;
-
-@property (nonatomic, assign) BOOL enableviewportscale;
-@property (nonatomic, assign) BOOL mediaplaybackrequiresuseraction;
-@property (nonatomic, assign) BOOL allowinlinemediaplayback;
-@property (nonatomic, assign) BOOL keyboarddisplayrequiresuseraction;
-@property (nonatomic, assign) BOOL suppressesincrementalrendering;
-@property (nonatomic, assign) BOOL hidden;
-@property (nonatomic, assign) BOOL disallowoverscroll;
-
-+ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
-
-@end
-
-@interface CDVInAppBrowserViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{
- @private
- NSString* _userAgent;
- NSString* _prevUserAgent;
- NSInteger _userAgentLockToken;
- CDVInAppBrowserOptions *_browserOptions;
-
-#ifdef __CORDOVA_4_0_0
- CDVUIWebViewDelegate* _webViewDelegate;
-#else
- CDVWebViewDelegate* _webViewDelegate;
-#endif
-
-}
-
-@property (nonatomic, strong) IBOutlet UIWebView* webView;
-@property (nonatomic, strong) IBOutlet UIBarButtonItem* closeButton;
-@property (nonatomic, strong) IBOutlet UILabel* addressLabel;
-@property (nonatomic, strong) IBOutlet UIBarButtonItem* backButton;
-@property (nonatomic, strong) IBOutlet UIBarButtonItem* forwardButton;
-@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinner;
-@property (nonatomic, strong) IBOutlet UIToolbar* toolbar;
-
-@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
-@property (nonatomic, weak) CDVInAppBrowser* navigationDelegate;
-@property (nonatomic) NSURL* currentURL;
-
-- (void)close;
-- (void)navigateTo:(NSURL*)url;
-- (void)showLocationBar:(BOOL)show;
-- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
-- (void)setCloseButtonTitle:(NSString*)title;
-
-- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVInAppBrowserOptions*) browserOptions;
-
-@end
-
-@interface CDVInAppBrowserNavigationController : UINavigationController
-
-@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
-
-@end
-
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.h b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.h
new file mode 100644
index 00000000..bd186a2f
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.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 <Cordova/CDVScreenOrientationDelegate.h>
+
+
+@interface CDVInAppBrowserNavigationController : UINavigationController
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.m b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.m
new file mode 100644
index 00000000..3cc9043f
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserNavigationController.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 "CDVInAppBrowserNavigationController.h"
+
+@implementation CDVInAppBrowserNavigationController : UINavigationController
+
+- (void) dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
+ if ( self.presentedViewController) {
+ [super dismissViewControllerAnimated:flag completion:completion];
+ }
+}
+
+- (void) viewDidLoad {
+ [super viewDidLoad];
+}
+
+- (CGRect) invertFrameIfNeeded:(CGRect)rect {
+ if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
+ CGFloat temp = rect.size.width;
+ rect.size.width = rect.size.height;
+ rect.size.height = temp;
+ }
+ rect.origin = CGPointZero;
+ return rect;
+}
+
+#pragma mark CDVScreenOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+ if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+ return [self.orientationDelegate shouldAutorotate];
+ }
+ return YES;
+}
+
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations
+{
+ if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+ return [self.orientationDelegate supportedInterfaceOrientations];
+ }
+
+ return 1 << UIInterfaceOrientationPortrait;
+}
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.h b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.h
new file mode 100644
index 00000000..c1c9fa53
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.h
@@ -0,0 +1,50 @@
+/*
+ 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.
+ */
+
+
+@interface CDVInAppBrowserOptions : NSObject {}
+
+@property (nonatomic, assign) BOOL location;
+@property (nonatomic, assign) BOOL toolbar;
+@property (nonatomic, copy) NSString* closebuttoncaption;
+@property (nonatomic, copy) NSString* closebuttoncolor;
+@property (nonatomic, assign) BOOL lefttoright;
+@property (nonatomic, copy) NSString* toolbarposition;
+@property (nonatomic, copy) NSString* toolbarcolor;
+@property (nonatomic, assign) BOOL toolbartranslucent;
+@property (nonatomic, assign) BOOL hidenavigationbuttons;
+@property (nonatomic, copy) NSString* navigationbuttoncolor;
+@property (nonatomic, assign) BOOL cleardata;
+@property (nonatomic, assign) BOOL clearcache;
+@property (nonatomic, assign) BOOL clearsessioncache;
+@property (nonatomic, assign) BOOL hidespinner;
+
+@property (nonatomic, copy) NSString* presentationstyle;
+@property (nonatomic, copy) NSString* transitionstyle;
+
+@property (nonatomic, assign) BOOL enableviewportscale;
+@property (nonatomic, assign) BOOL mediaplaybackrequiresuseraction;
+@property (nonatomic, assign) BOOL allowinlinemediaplayback;
+@property (nonatomic, assign) BOOL hidden;
+@property (nonatomic, assign) BOOL disallowoverscroll;
+@property (nonatomic, copy) NSString* beforeload;
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.m b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.m
new file mode 100644
index 00000000..e20d1a8c
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowserOptions.m
@@ -0,0 +1,90 @@
+/*
+ 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 "CDVInAppBrowserOptions.h"
+
+@implementation CDVInAppBrowserOptions
+
+- (id)init
+{
+ if (self = [super init]) {
+ // default values
+ self.location = YES;
+ self.toolbar = YES;
+ self.closebuttoncaption = nil;
+ self.toolbarposition = @"bottom";
+ self.cleardata = NO;
+ self.clearcache = NO;
+ self.clearsessioncache = NO;
+ self.hidespinner = NO;
+
+ self.enableviewportscale = NO;
+ self.mediaplaybackrequiresuseraction = NO;
+ self.allowinlinemediaplayback = NO;
+ self.hidden = NO;
+ self.disallowoverscroll = NO;
+ self.hidenavigationbuttons = NO;
+ self.closebuttoncolor = nil;
+ self.lefttoright = false;
+ self.toolbarcolor = nil;
+ self.toolbartranslucent = YES;
+ self.beforeload = @"";
+ }
+
+ return self;
+}
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
+{
+ CDVInAppBrowserOptions* obj = [[CDVInAppBrowserOptions alloc] init];
+
+ // NOTE: this parsing does not handle quotes within values
+ NSArray* pairs = [options componentsSeparatedByString:@","];
+
+ // parse keys and values, set the properties
+ for (NSString* pair in pairs) {
+ NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
+
+ if ([keyvalue count] == 2) {
+ NSString* key = [[keyvalue objectAtIndex:0] lowercaseString];
+ NSString* value = [keyvalue objectAtIndex:1];
+ NSString* value_lc = [value lowercaseString];
+
+ BOOL isBoolean = [value_lc isEqualToString:@"yes"] || [value_lc isEqualToString:@"no"];
+ NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
+ [numberFormatter setAllowsFloats:YES];
+ BOOL isNumber = [numberFormatter numberFromString:value_lc] != nil;
+
+ // set the property according to the key name
+ if ([obj respondsToSelector:NSSelectorFromString(key)]) {
+ if (isNumber) {
+ [obj setValue:[numberFormatter numberFromString:value_lc] forKey:key];
+ } else if (isBoolean) {
+ [obj setValue:[NSNumber numberWithBool:[value_lc isEqualToString:@"yes"]] forKey:key];
+ } else {
+ [obj setValue:value forKey:key];
+ }
+ }
+ }
+ }
+
+ return obj;
+}
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.h b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.h
new file mode 100644
index 00000000..e339be15
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.h
@@ -0,0 +1,80 @@
+/*
+ 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 <Cordova/CDVPlugin.h>
+#import <Cordova/CDVInvokedUrlCommand.h>
+#import <Cordova/CDVScreenOrientationDelegate.h>
+#import "CDVWKInAppBrowserUIDelegate.h"
+#import "CDVInAppBrowserOptions.h"
+#import "CDVInAppBrowserNavigationController.h"
+
+@class CDVWKInAppBrowserViewController;
+
+@interface CDVWKInAppBrowser : CDVPlugin {
+ UIWindow * tmpWindow;
+
+ @private
+ NSString* _beforeload;
+ BOOL _waitForBeforeload;
+}
+
+@property (nonatomic, retain) CDVWKInAppBrowser* instance;
+@property (nonatomic, retain) CDVWKInAppBrowserViewController* inAppBrowserViewController;
+@property (nonatomic, copy) NSString* callbackId;
+@property (nonatomic, copy) NSRegularExpression *callbackIdPattern;
+
++ (id) getInstance;
+- (void)open:(CDVInvokedUrlCommand*)command;
+- (void)close:(CDVInvokedUrlCommand*)command;
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
+- (void)show:(CDVInvokedUrlCommand*)command;
+- (void)hide:(CDVInvokedUrlCommand*)command;
+- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVWKInAppBrowserViewController : UIViewController <CDVScreenOrientationDelegate,WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler>{
+ @private
+ CDVInAppBrowserOptions *_browserOptions;
+ NSDictionary *_settings;
+}
+
+@property (nonatomic, strong) IBOutlet WKWebView* webView;
+@property (nonatomic, strong) IBOutlet WKWebViewConfiguration* configuration;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* closeButton;
+@property (nonatomic, strong) IBOutlet UILabel* addressLabel;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* backButton;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* forwardButton;
+@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinner;
+@property (nonatomic, strong) IBOutlet UIToolbar* toolbar;
+@property (nonatomic, strong) IBOutlet CDVWKInAppBrowserUIDelegate* webViewUIDelegate;
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+@property (nonatomic, weak) CDVWKInAppBrowser* navigationDelegate;
+@property (nonatomic) NSURL* currentURL;
+
+- (void)close;
+- (void)navigateTo:(NSURL*)url;
+- (void)showLocationBar:(BOOL)show;
+- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
+- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString : (int) buttonIndex;
+
+- (id)initWithBrowserOptions: (CDVInAppBrowserOptions*) browserOptions andSettings:(NSDictionary*) settings;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.m b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.m
index b342ca73..1ec20653 100644
--- a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVInAppBrowser.m
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowser.m
@@ -6,9 +6,9 @@
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
@@ -17,9 +17,13 @@
under the License.
*/
-#import "CDVInAppBrowser.h"
+#import "CDVWKInAppBrowser.h"
+
+#if __has_include("CDVWKProcessPoolFactory.h")
+#import "CDVWKProcessPoolFactory.h"
+#endif
+
#import <Cordova/CDVPluginResult.h>
-#import <Cordova/CDVUserAgentUtil.h>
#define kInAppBrowserTargetSelf @"_self"
#define kInAppBrowserTargetSystem @"_system"
@@ -28,28 +32,34 @@
#define kInAppBrowserToolbarBarPositionBottom @"bottom"
#define kInAppBrowserToolbarBarPositionTop @"top"
+#define IAB_BRIDGE_NAME @"cordova_iab"
+
#define TOOLBAR_HEIGHT 44.0
#define LOCATIONBAR_HEIGHT 21.0
#define FOOTER_HEIGHT ((TOOLBAR_HEIGHT) + (LOCATIONBAR_HEIGHT))
-#pragma mark CDVInAppBrowser
+#pragma mark CDVWKInAppBrowser
-@interface CDVInAppBrowser () {
+@interface CDVWKInAppBrowser () {
NSInteger _previousStatusBarStyle;
}
@end
-@implementation CDVInAppBrowser
+@implementation CDVWKInAppBrowser
+
+static CDVWKInAppBrowser* instance = nil;
+
++ (id) getInstance{
+ return instance;
+}
- (void)pluginInitialize
{
+ instance = self;
_previousStatusBarStyle = -1;
_callbackIdPattern = nil;
-}
-
-- (id)settingForKey:(NSString*)key
-{
- return [self.commandDelegate.settings objectForKey:[key lowercaseString]];
+ _beforeload = @"";
+ _waitForBeforeload = NO;
}
- (void)onReset
@@ -63,41 +73,38 @@
NSLog(@"IAB.close() called but it was already closed.");
return;
}
+
// Things are cleaned up in browserExit.
[self.inAppBrowserViewController close];
}
- (BOOL) isSystemUrl:(NSURL*)url
{
- if ([[url host] isEqualToString:@"itunes.apple.com"]) {
- return YES;
- }
-
- return NO;
+ if ([[url host] isEqualToString:@"itunes.apple.com"]) {
+ return YES;
+ }
+
+ return NO;
}
- (void)open:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult;
-
+
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
-
+
self.callbackId = command.callbackId;
-
+
if (url != nil) {
-#ifdef __CORDOVA_4_0_0
NSURL* baseUrl = [self.webViewEngine URL];
-#else
- NSURL* baseUrl = [self.webView.request URL];
-#endif
NSURL* absoluteUrl = [[NSURL URLWithString:url relativeToURL:baseUrl] absoluteURL];
-
+
if ([self isSystemUrl:absoluteUrl]) {
target = kInAppBrowserTargetSystem;
}
-
+
if ([target isEqualToString:kInAppBrowserTargetSelf]) {
[self openInCordovaWebView:absoluteUrl withOptions:options];
} else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
@@ -105,12 +112,12 @@
} else { // _blank or anything else
[self openInInAppBrowser:absoluteUrl withOptions:options];
}
-
+
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"];
}
-
+
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@@ -118,51 +125,92 @@
- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
{
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
-
+
+ WKWebsiteDataStore* dataStore = [WKWebsiteDataStore defaultDataStore];
+ if (browserOptions.cleardata) {
+
+ NSDate* dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
+ [dataStore removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:dateFrom completionHandler:^{
+ NSLog(@"Removed all WKWebView data");
+ self.inAppBrowserViewController.webView.configuration.processPool = [[WKProcessPool alloc] init]; // create new process pool to flush all data
+ }];
+ }
+
if (browserOptions.clearcache) {
- NSHTTPCookie *cookie;
- NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
- for (cookie in [storage cookies])
- {
- if (![cookie.domain isEqual: @".^filecookies^"]) {
- [storage deleteCookie:cookie];
- }
+ bool isAtLeastiOS11 = false;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+ if (@available(iOS 11.0, *)) {
+ isAtLeastiOS11 = true;
+ }
+#endif
+
+ if(isAtLeastiOS11){
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+ // Deletes all cookies
+ WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
+ [cookieStore getAllCookies:^(NSArray* cookies) {
+ NSHTTPCookie* cookie;
+ for(cookie in cookies){
+ [cookieStore deleteCookie:cookie completionHandler:nil];
+ }
+ }];
+#endif
+ }else{
+ // https://stackoverflow.com/a/31803708/777265
+ // Only deletes domain cookies (not session cookies)
+ [dataStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
+ completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records) {
+ for (WKWebsiteDataRecord *record in records){
+ NSSet<NSString*>* dataTypes = record.dataTypes;
+ if([dataTypes containsObject:WKWebsiteDataTypeCookies]){
+ [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes
+ forDataRecords:@[record]
+ completionHandler:^{}];
+ }
+ }
+ }];
}
}
-
+
if (browserOptions.clearsessioncache) {
- NSHTTPCookie *cookie;
- NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
- for (cookie in [storage cookies])
- {
- if (![cookie.domain isEqual: @".^filecookies^"] && cookie.isSessionOnly) {
- [storage deleteCookie:cookie];
- }
+ bool isAtLeastiOS11 = false;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+ if (@available(iOS 11.0, *)) {
+ isAtLeastiOS11 = true;
+ }
+#endif
+ if (isAtLeastiOS11) {
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+ // Deletes session cookies
+ WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
+ [cookieStore getAllCookies:^(NSArray* cookies) {
+ NSHTTPCookie* cookie;
+ for(cookie in cookies){
+ if(cookie.sessionOnly){
+ [cookieStore deleteCookie:cookie completionHandler:nil];
+ }
+ }
+ }];
+#endif
+ }else{
+ NSLog(@"clearsessioncache not available below iOS 11.0");
}
}
if (self.inAppBrowserViewController == nil) {
- NSString* userAgent = [CDVUserAgentUtil originalUserAgent];
- NSString* overrideUserAgent = [self settingForKey:@"OverrideUserAgent"];
- NSString* appendUserAgent = [self settingForKey:@"AppendUserAgent"];
- if(overrideUserAgent){
- userAgent = overrideUserAgent;
- }
- if(appendUserAgent){
- userAgent = [userAgent stringByAppendingString: appendUserAgent];
- }
- self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] initWithUserAgent:userAgent prevUserAgent:[self.commandDelegate userAgent] browserOptions: browserOptions];
+ self.inAppBrowserViewController = [[CDVWKInAppBrowserViewController alloc] initWithBrowserOptions: browserOptions andSettings:self.commandDelegate.settings];
self.inAppBrowserViewController.navigationDelegate = self;
-
+
if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) {
self.inAppBrowserViewController.orientationDelegate = (UIViewController <CDVScreenOrientationDelegate>*)self.viewController;
}
}
-
+
[self.inAppBrowserViewController showLocationBar:browserOptions.location];
[self.inAppBrowserViewController showToolBar:browserOptions.toolbar :browserOptions.toolbarposition];
- if (browserOptions.closebuttoncaption != nil) {
- [self.inAppBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption];
+ if (browserOptions.closebuttoncaption != nil || browserOptions.closebuttoncolor != nil) {
+ int closeButtonIndex = browserOptions.lefttoright ? (browserOptions.hidenavigationbuttons ? 1 : 4) : 0;
+ [self.inAppBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption :browserOptions.closebuttoncolor :closeButtonIndex];
}
// Set Presentation Style
UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default
@@ -174,7 +222,7 @@
}
}
self.inAppBrowserViewController.modalPresentationStyle = presentationStyle;
-
+
// Set Transition Style
UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default
if (browserOptions.transitionstyle != nil) {
@@ -185,8 +233,8 @@
}
}
self.inAppBrowserViewController.modalTransitionStyle = transitionStyle;
-
- // prevent webView from bouncing
+
+ //prevent webView from bouncing
if (browserOptions.disallowoverscroll) {
if ([self.inAppBrowserViewController.webView respondsToSelector:@selector(scrollView)]) {
((UIScrollView*)[self.inAppBrowserViewController.webView scrollView]).bounces = NO;
@@ -198,24 +246,32 @@
}
}
}
-
- // UIWebView options
- self.inAppBrowserViewController.webView.scalesPageToFit = browserOptions.enableviewportscale;
- self.inAppBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction;
- self.inAppBrowserViewController.webView.allowsInlineMediaPlayback = browserOptions.allowinlinemediaplayback;
- if (IsAtLeastiOSVersion(@"6.0")) {
- self.inAppBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction;
- self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
+
+ // use of beforeload event
+ if([browserOptions.beforeload isKindOfClass:[NSString class]]){
+ _beforeload = browserOptions.beforeload;
+ }else{
+ _beforeload = @"yes";
}
-
+ _waitForBeforeload = ![_beforeload isEqualToString:@""];
+
[self.inAppBrowserViewController navigateTo:url];
if (!browserOptions.hidden) {
- [self show:nil];
+ [self show:nil withNoAnimate:browserOptions.hidden];
}
}
-- (void)show:(CDVInvokedUrlCommand*)command
+- (void)show:(CDVInvokedUrlCommand*)command{
+ [self show:command withNoAnimate:NO];
+}
+
+- (void)show:(CDVInvokedUrlCommand*)command withNoAnimate:(BOOL)noAnimate
{
+ BOOL initHidden = NO;
+ if(command == nil && noAnimate == YES){
+ initHidden = YES;
+ }
+
if (self.inAppBrowserViewController == nil) {
NSLog(@"Tried to show IAB after it was closed.");
return;
@@ -224,21 +280,69 @@
NSLog(@"Tried to show IAB while already shown");
return;
}
-
- _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
-
+
+ if(!initHidden){
+ _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
+ }
+
__block CDVInAppBrowserNavigationController* nav = [[CDVInAppBrowserNavigationController alloc]
- initWithRootViewController:self.inAppBrowserViewController];
+ initWithRootViewController:self.inAppBrowserViewController];
nav.orientationDelegate = self.inAppBrowserViewController;
nav.navigationBarHidden = YES;
nav.modalPresentationStyle = self.inAppBrowserViewController.modalPresentationStyle;
+
+ __weak CDVWKInAppBrowser* weakSelf = self;
+
+ // Run later to avoid the "took a long time" log message.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (weakSelf.inAppBrowserViewController != nil) {
+ float osVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
+ __strong __typeof(weakSelf) strongSelf = weakSelf;
+ if (!strongSelf->tmpWindow) {
+ CGRect frame = [[UIScreen mainScreen] bounds];
+ if(initHidden && osVersion < 11){
+ frame.origin.x = -10000;
+ }
+ strongSelf->tmpWindow = [[UIWindow alloc] initWithFrame:frame];
+ }
+ UIViewController *tmpController = [[UIViewController alloc] init];
+
+ [strongSelf->tmpWindow setRootViewController:tmpController];
+ [strongSelf->tmpWindow setWindowLevel:UIWindowLevelNormal];
- __weak CDVInAppBrowser* weakSelf = self;
+ if(!initHidden || osVersion < 11){
+ [self->tmpWindow makeKeyAndVisible];
+ }
+ [tmpController presentViewController:nav animated:!noAnimate completion:nil];
+ }
+ });
+}
+- (void)hide:(CDVInvokedUrlCommand*)command
+{
+ // Set tmpWindow to hidden to make main webview responsive to touch again
+ // https://stackoverflow.com/questions/4544489/how-to-remove-a-uiwindow
+ self->tmpWindow.hidden = YES;
+ self->tmpWindow = nil;
+
+ if (self.inAppBrowserViewController == nil) {
+ NSLog(@"Tried to hide IAB after it was closed.");
+ return;
+
+
+ }
+ if (_previousStatusBarStyle == -1) {
+ NSLog(@"Tried to hide IAB while already hidden");
+ return;
+ }
+
+ _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
+
// Run later to avoid the "took a long time" log message.
dispatch_async(dispatch_get_main_queue(), ^{
- if (weakSelf.inAppBrowserViewController != nil) {
- [weakSelf.viewController presentViewController:nav animated:YES completion:nil];
+ if (self.inAppBrowserViewController != nil) {
+ _previousStatusBarStyle = -1;
+ [self.inAppBrowserViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
});
}
@@ -246,24 +350,39 @@
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
-
-#ifdef __CORDOVA_4_0_0
// the webview engine itself will filter for this according to <allow-navigation> policy
// in config.xml for cordova-ios-4.0
[self.webViewEngine loadRequest:request];
-#else
- if ([self.commandDelegate URLIsWhitelisted:url]) {
- [self.webView loadRequest:request];
- } else { // this assumes the InAppBrowser can be excepted from the white-list
- [self openInInAppBrowser:url withOptions:options];
- }
-#endif
}
- (void)openInSystem:(NSURL*)url
{
- [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
- [[UIApplication sharedApplication] openURL:url];
+ if ([[UIApplication sharedApplication] openURL:url] == NO) {
+ [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+ [[UIApplication sharedApplication] openURL:url];
+ }
+}
+
+- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
+{
+ NSString* urlStr = [command argumentAtIndex:0];
+
+ if ([_beforeload isEqualToString:@""]) {
+ NSLog(@"unexpected loadAfterBeforeload called without feature beforeload=get|post");
+ }
+ if (self.inAppBrowserViewController == nil) {
+ NSLog(@"Tried to invoke loadAfterBeforeload on IAB after it was closed.");
+ return;
+ }
+ if (urlStr == nil) {
+ NSLog(@"loadAfterBeforeload called with nil argument, ignoring.");
+ return;
+ }
+
+ NSURL* url = [NSURL URLWithString:urlStr];
+ //_beforeload = @"";
+ _waitForBeforeload = NO;
+ [self.inAppBrowserViewController navigateTo:url];
}
// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
@@ -277,28 +396,43 @@
- (void)injectDeferredObject:(NSString*)source withWrapper:(NSString*)jsWrapper
{
- // Ensure an iframe bridge is created to communicate with the CDVInAppBrowserViewController
- [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:@"(function(d){_cdvIframeBridge=d.getElementById('_cdvIframeBridge');if(!_cdvIframeBridge) {var e = _cdvIframeBridge = d.createElement('iframe');e.id='_cdvIframeBridge'; e.style.display='none';d.body.appendChild(e);}})(document)"];
-
+ // Ensure a message handler bridge is created to communicate with the CDVWKInAppBrowserViewController
+ [self evaluateJavaScript: [NSString stringWithFormat:@"(function(w){if(!w._cdvMessageHandler) {w._cdvMessageHandler = function(id,d){w.webkit.messageHandlers.%@.postMessage({d:d, id:id});}}})(window)", IAB_BRIDGE_NAME]];
+
if (jsWrapper != nil) {
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@[source] options:0 error:nil];
NSString* sourceArrayString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (sourceArrayString) {
NSString* sourceString = [sourceArrayString substringWithRange:NSMakeRange(1, [sourceArrayString length] - 2)];
NSString* jsToInject = [NSString stringWithFormat:jsWrapper, sourceString];
- [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:jsToInject];
+ [self evaluateJavaScript:jsToInject];
}
} else {
- [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:source];
+ [self evaluateJavaScript:source];
}
}
+
+//Synchronus helper for javascript evaluation
+- (void)evaluateJavaScript:(NSString *)script {
+ __block NSString* _script = script;
+ [self.inAppBrowserViewController.webView evaluateJavaScript:script completionHandler:^(id result, NSError *error) {
+ if (error == nil) {
+ if (result != nil) {
+ NSLog(@"%@", result);
+ }
+ } else {
+ NSLog(@"evaluateJavaScript error : %@ : %@", error.localizedDescription, _script);
+ }
+ }];
+}
+
- (void)injectScriptCode:(CDVInvokedUrlCommand*)command
{
NSString* jsWrapper = nil;
-
+
if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
- jsWrapper = [NSString stringWithFormat:@"_cdvIframeBridge.src='gap-iab://%@/'+encodeURIComponent(JSON.stringify([eval(%%@)]));", command.callbackId];
+ jsWrapper = [NSString stringWithFormat:@"_cdvMessageHandler('%@',JSON.stringify([eval(%%@)]));", command.callbackId];
}
[self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
}
@@ -306,9 +440,9 @@
- (void)injectScriptFile:(CDVInvokedUrlCommand*)command
{
NSString* jsWrapper;
-
+
if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
- jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvMessageHandler('%@'); }; d.body.appendChild(c); })(document)", command.callbackId];
} else {
jsWrapper = @"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)";
}
@@ -318,9 +452,9 @@
- (void)injectStyleCode:(CDVInvokedUrlCommand*)command
{
NSString* jsWrapper;
-
+
if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
- jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvMessageHandler('%@'); }; d.body.appendChild(c); })(document)", command.callbackId];
} else {
jsWrapper = @"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)";
}
@@ -330,9 +464,9 @@
- (void)injectStyleFile:(CDVInvokedUrlCommand*)command
{
NSString* jsWrapper;
-
+
if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
- jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvMessageHandler('%@'); }; d.body.appendChild(c); })(document)", command.callbackId];
} else {
jsWrapper = @"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document)";
}
@@ -357,94 +491,163 @@
}
/**
- * The iframe bridge provided for the InAppBrowser is capable of executing any oustanding callback belonging
+ * The message handler bridge provided for the InAppBrowser is capable of executing any oustanding callback belonging
* to the InAppBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no
* other code execution is possible.
- *
- * To trigger the bridge, the iframe (or any other resource) should attempt to load a url of the form:
- *
- * gap-iab://<callbackId>/<arguments>
- *
- * where <callbackId> is the string id of the callback to trigger (something like "InAppBrowser0123456789")
- *
- * If present, the path component of the special gap-iab:// url is expected to be a URL-escaped JSON-encoded
- * value to pass to the callback. [NSURL path] should take care of the URL-unescaping, and a JSON_EXCEPTION
- * is returned if the JSON is invalid.
*/
-- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
-{
- NSURL* url = request.URL;
- BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
-
- // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
- // and the path, if present, should be a JSON-encoded value to pass to the callback.
- if ([[url scheme] isEqualToString:@"gap-iab"]) {
- NSString* scriptCallbackId = [url host];
- CDVPluginResult* pluginResult = nil;
-
- if ([self isValidCallbackId:scriptCallbackId]) {
- NSString* scriptResult = [url path];
- NSError* __autoreleasing error = nil;
+- (void)webView:(WKWebView *)theWebView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
+
+ NSURL* url = navigationAction.request.URL;
+ NSURL* mainDocumentURL = navigationAction.request.mainDocumentURL;
+ BOOL isTopLevelNavigation = [url isEqual:mainDocumentURL];
+ BOOL shouldStart = YES;
+ BOOL useBeforeLoad = NO;
+ NSString* httpMethod = navigationAction.request.HTTPMethod;
+ NSString* errorMessage = nil;
+
+ if([_beforeload isEqualToString:@"post"]){
+ //TODO handle POST requests by preserving POST data then remove this condition
+ errorMessage = @"beforeload doesn't yet support POST requests";
+ }
+ else if(isTopLevelNavigation && (
+ [_beforeload isEqualToString:@"yes"]
+ || ([_beforeload isEqualToString:@"get"] && [httpMethod isEqualToString:@"GET"])
+ // TODO comment in when POST requests are handled
+ // || ([_beforeload isEqualToString:@"post"] && [httpMethod isEqualToString:@"POST"])
+ )){
+ useBeforeLoad = YES;
+ }
- // The message should be a JSON-encoded array of the result of the script which executed.
- if ((scriptResult != nil) && ([scriptResult length] > 1)) {
- scriptResult = [scriptResult substringFromIndex:1];
- NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
- if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult];
- } else {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION];
- }
- } else {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]];
- }
- [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
- return NO;
- }
- }
+ // When beforeload, on first URL change, initiate JS callback. Only after the beforeload event, continue.
+ if (_waitForBeforeload && useBeforeLoad) {
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+ messageAsDictionary:@{@"type":@"beforeload", @"url":[url absoluteString]}];
+ [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+ decisionHandler(WKNavigationActionPolicyCancel);
+ return;
+ }
+
+ if(errorMessage != nil){
+ NSLog(errorMessage);
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+ messageAsDictionary:@{@"type":@"loaderror", @"url":[url absoluteString], @"code": @"-1", @"message": errorMessage}];
+ [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+ }
+
//if is an app store link, let the system handle it, otherwise it fails to load it
- else if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
+ if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
[theWebView stopLoading];
[self openInSystem:url];
- return NO;
+ shouldStart = NO;
}
else if ((self.callbackId != nil) && isTopLevelNavigation) {
// Send a loadstart event for each top-level navigation (includes redirects).
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
-
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}
- return YES;
+ if (useBeforeLoad) {
+ _waitForBeforeload = YES;
+ }
+
+ if(shouldStart){
+ // Fix GH-417 & GH-424: Handle non-default target attribute
+ // Based on https://stackoverflow.com/a/25713070/777265
+ if (!navigationAction.targetFrame){
+ [theWebView loadRequest:navigationAction.request];
+ decisionHandler(WKNavigationActionPolicyCancel);
+ }else{
+ decisionHandler(WKNavigationActionPolicyAllow);
+ }
+ }else{
+ decisionHandler(WKNavigationActionPolicyCancel);
+ }
}
-- (void)webViewDidStartLoad:(UIWebView*)theWebView
+#pragma mark WKScriptMessageHandler delegate
+- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
+
+ CDVPluginResult* pluginResult = nil;
+
+ if([message.body isKindOfClass:[NSDictionary class]]){
+ NSDictionary* messageContent = (NSDictionary*) message.body;
+ NSString* scriptCallbackId = messageContent[@"id"];
+
+ if([messageContent objectForKey:@"d"]){
+ NSString* scriptResult = messageContent[@"d"];
+ NSError* __autoreleasing error = nil;
+ NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
+ if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult];
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION];
+ }
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]];
+ }
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
+ }else if(self.callbackId != nil){
+ // Send a message event
+ NSString* messageContent = (NSString*) message.body;
+ NSError* __autoreleasing error = nil;
+ NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[messageContent dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
+ if (error == nil) {
+ NSMutableDictionary* dResult = [NSMutableDictionary new];
+ [dResult setValue:@"message" forKey:@"type"];
+ [dResult setObject:decodedResult forKey:@"data"];
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dResult];
+ [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+ }
+ }
+}
+
+- (void)didStartProvisionalNavigation:(WKWebView*)theWebView
{
+ NSLog(@"didStartProvisionalNavigation");
+// self.inAppBrowserViewController.currentURL = theWebView.URL;
}
-- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+- (void)didFinishNavigation:(WKWebView*)theWebView
{
if (self.callbackId != nil) {
- // TODO: It would be more useful to return the URL the page is actually on (e.g. if it's been redirected).
- NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
+ NSString* url = [theWebView.URL absoluteString];
+ if(url == nil){
+ if(self.inAppBrowserViewController.currentURL != nil){
+ url = [self.inAppBrowserViewController.currentURL absoluteString];
+ }else{
+ url = @"";
+ }
+ }
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"type":@"loadstop", @"url":url}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
-
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}
}
-- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+- (void)webView:(WKWebView*)theWebView didFailNavigation:(NSError*)error
{
if (self.callbackId != nil) {
- NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
+ NSString* url = [theWebView.URL absoluteString];
+ if(url == nil){
+ if(self.inAppBrowserViewController.currentURL != nil){
+ url = [self.inAppBrowserViewController.currentURL absoluteString];
+ }else{
+ url = @"";
+ }
+ }
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
messageAsDictionary:@{@"type":@"loaderror", @"url":url, @"code": [NSNumber numberWithInteger:error.code], @"message": error.localizedDescription}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
-
+
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}
}
@@ -457,78 +660,135 @@
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
self.callbackId = nil;
}
+
+ [self.inAppBrowserViewController.configuration.userContentController removeScriptMessageHandlerForName:IAB_BRIDGE_NAME];
+ self.inAppBrowserViewController.configuration = nil;
+
+ [self.inAppBrowserViewController.webView stopLoading];
+ [self.inAppBrowserViewController.webView removeFromSuperview];
+ [self.inAppBrowserViewController.webView setUIDelegate:nil];
+ [self.inAppBrowserViewController.webView setNavigationDelegate:nil];
+ self.inAppBrowserViewController.webView = nil;
+
// Set navigationDelegate to nil to ensure no callbacks are received from it.
self.inAppBrowserViewController.navigationDelegate = nil;
- // Don't recycle the ViewController since it may be consuming a lot of memory.
- // Also - this is required for the PDF/User-Agent bug work-around.
self.inAppBrowserViewController = nil;
+ // Set tmpWindow to hidden to make main webview responsive to touch again
+ // Based on https://stackoverflow.com/questions/4544489/how-to-remove-a-uiwindow
+ self->tmpWindow.hidden = YES;
+ self->tmpWindow = nil;
+
if (IsAtLeastiOSVersion(@"7.0")) {
if (_previousStatusBarStyle != -1) {
[[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle];
+
}
}
-
+
_previousStatusBarStyle = -1; // this value was reset before reapplying it. caused statusbar to stay black on ios7
}
-@end
+@end //CDVWKInAppBrowser
-#pragma mark CDVInAppBrowserViewController
+#pragma mark CDVWKInAppBrowserViewController
-@implementation CDVInAppBrowserViewController
+@implementation CDVWKInAppBrowserViewController
@synthesize currentURL;
-- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVInAppBrowserOptions*) browserOptions
+CGFloat lastReducedStatusBarHeight = 0.0;
+BOOL isExiting = FALSE;
+
+- (id)initWithBrowserOptions: (CDVInAppBrowserOptions*) browserOptions andSettings:(NSDictionary *)settings
{
self = [super init];
if (self != nil) {
- _userAgent = userAgent;
- _prevUserAgent = prevUserAgent;
_browserOptions = browserOptions;
-#ifdef __CORDOVA_4_0_0
- _webViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:self];
-#else
- _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
-#endif
+ _settings = settings;
+ self.webViewUIDelegate = [[CDVWKInAppBrowserUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
+ [self.webViewUIDelegate setViewController:self];
[self createViews];
}
-
+
return self;
}
-// Prevent crashes on closing windows
-(void)dealloc {
- self.webView.delegate = nil;
+ //NSLog(@"dealloc");
}
- (void)createViews
{
// We create the views in code for primarily for ease of upgrades and not requiring an external .xib to be included
-
+
CGRect webViewBounds = self.view.bounds;
BOOL toolbarIsAtBottom = ![_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop];
webViewBounds.size.height -= _browserOptions.location ? FOOTER_HEIGHT : TOOLBAR_HEIGHT;
- self.webView = [[UIWebView alloc] initWithFrame:webViewBounds];
-
- self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+ WKUserContentController* userContentController = [[WKUserContentController alloc] init];
+
+ WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
+
+ NSString *userAgent = configuration.applicationNameForUserAgent;
+ if (
+ [self settingForKey:@"OverrideUserAgent"] == nil &&
+ [self settingForKey:@"AppendUserAgent"] != nil
+ ) {
+ userAgent = [NSString stringWithFormat:@"%@ %@", userAgent, [self settingForKey:@"AppendUserAgent"]];
+ }
+ configuration.applicationNameForUserAgent = userAgent;
+ configuration.userContentController = userContentController;
+#if __has_include("CDVWKProcessPoolFactory.h")
+ configuration.processPool = [[CDVWKProcessPoolFactory sharedFactory] sharedProcessPool];
+#endif
+ [configuration.userContentController addScriptMessageHandler:self name:IAB_BRIDGE_NAME];
+
+ //WKWebView options
+ configuration.allowsInlineMediaPlayback = _browserOptions.allowinlinemediaplayback;
+ if (IsAtLeastiOSVersion(@"10.0")) {
+ configuration.ignoresViewportScaleLimits = _browserOptions.enableviewportscale;
+ if(_browserOptions.mediaplaybackrequiresuseraction == YES){
+ configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeAll;
+ }else{
+ configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
+ }
+ }else{ // iOS 9
+ configuration.mediaPlaybackRequiresUserAction = _browserOptions.mediaplaybackrequiresuseraction;
+ }
+
+
+ self.webView = [[WKWebView alloc] initWithFrame:webViewBounds configuration:configuration];
+
[self.view addSubview:self.webView];
[self.view sendSubviewToBack:self.webView];
-
- self.webView.delegate = _webViewDelegate;
+
+
+ self.webView.navigationDelegate = self;
+ self.webView.UIDelegate = self.webViewUIDelegate;
self.webView.backgroundColor = [UIColor whiteColor];
-
+ if ([self settingForKey:@"OverrideUserAgent"] != nil) {
+ self.webView.customUserAgent = [self settingForKey:@"OverrideUserAgent"];
+ }
+
self.webView.clearsContextBeforeDrawing = YES;
self.webView.clipsToBounds = YES;
self.webView.contentMode = UIViewContentModeScaleToFill;
self.webView.multipleTouchEnabled = YES;
self.webView.opaque = YES;
- self.webView.scalesPageToFit = NO;
self.webView.userInteractionEnabled = YES;
-
+ self.automaticallyAdjustsScrollViewInsets = YES ;
+ [self.webView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
+ self.webView.allowsLinkPreview = NO;
+ self.webView.allowsBackForwardNavigationGestures = NO;
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+ if (@available(iOS 11.0, *)) {
+ [self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
+ }
+#endif
+
self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.spinner.alpha = 1.000;
self.spinner.autoresizesSubviews = YES;
@@ -543,18 +803,18 @@
self.spinner.opaque = NO;
self.spinner.userInteractionEnabled = NO;
[self.spinner stopAnimating];
-
+
self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
self.closeButton.enabled = YES;
-
+
UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
-
+
UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedSpaceButton.width = 20;
-
+
float toolbarY = toolbarIsAtBottom ? self.view.bounds.size.height - TOOLBAR_HEIGHT : 0.0;
CGRect toolbarFrame = CGRectMake(0.0, toolbarY, self.view.bounds.size.width, TOOLBAR_HEIGHT);
-
+
self.toolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame];
self.toolbar.alpha = 1.000;
self.toolbar.autoresizesSubviews = YES;
@@ -567,10 +827,16 @@
self.toolbar.multipleTouchEnabled = NO;
self.toolbar.opaque = NO;
self.toolbar.userInteractionEnabled = YES;
-
+ if (_browserOptions.toolbarcolor != nil) { // Set toolbar color if user sets it in options
+ self.toolbar.barTintColor = [self colorFromHexString:_browserOptions.toolbarcolor];
+ }
+ if (!_browserOptions.toolbartranslucent) { // Set toolbar translucent to no if user sets it in options
+ self.toolbar.translucent = NO;
+ }
+
CGFloat labelInset = 5.0;
float locationBarY = toolbarIsAtBottom ? self.view.bounds.size.height - FOOTER_HEIGHT : self.view.bounds.size.height - LOCATIONBAR_HEIGHT;
-
+
self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelInset, locationBarY, self.view.bounds.size.width - labelInset, LOCATIONBAR_HEIGHT)];
self.addressLabel.adjustsFontSizeToFitWidth = NO;
self.addressLabel.alpha = 1.000;
@@ -584,13 +850,13 @@
self.addressLabel.enabled = YES;
self.addressLabel.hidden = NO;
self.addressLabel.lineBreakMode = NSLineBreakByTruncatingTail;
-
+
if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumScaleFactor:")]) {
[self.addressLabel setValue:@(10.0/[UIFont labelFontSize]) forKey:@"minimumScaleFactor"];
} else if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumFontSize:")]) {
[self.addressLabel setValue:@(10.0) forKey:@"minimumFontSize"];
}
-
+
self.addressLabel.multipleTouchEnabled = NO;
self.addressLabel.numberOfLines = 1;
self.addressLabel.opaque = NO;
@@ -599,84 +865,108 @@
self.addressLabel.textAlignment = NSTextAlignmentLeft;
self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000];
self.addressLabel.userInteractionEnabled = NO;
-
+
NSString* frontArrowString = NSLocalizedString(@"►", nil); // create arrow from Unicode char
self.forwardButton = [[UIBarButtonItem alloc] initWithTitle:frontArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goForward:)];
self.forwardButton.enabled = YES;
self.forwardButton.imageInsets = UIEdgeInsetsZero;
+ if (_browserOptions.navigationbuttoncolor != nil) { // Set button color if user sets it in options
+ self.forwardButton.tintColor = [self colorFromHexString:_browserOptions.navigationbuttoncolor];
+ }
NSString* backArrowString = NSLocalizedString(@"◄", nil); // create arrow from Unicode char
self.backButton = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goBack:)];
self.backButton.enabled = YES;
self.backButton.imageInsets = UIEdgeInsetsZero;
+ if (_browserOptions.navigationbuttoncolor != nil) { // Set button color if user sets it in options
+ self.backButton.tintColor = [self colorFromHexString:_browserOptions.navigationbuttoncolor];
+ }
- [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]];
-
- self.view.backgroundColor = [UIColor grayColor];
+ // Filter out Navigation Buttons if user requests so
+ if (_browserOptions.hidenavigationbuttons) {
+ if (_browserOptions.lefttoright) {
+ [self.toolbar setItems:@[flexibleSpaceButton, self.closeButton]];
+ } else {
+ [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton]];
+ }
+ } else if (_browserOptions.lefttoright) {
+ [self.toolbar setItems:@[self.backButton, fixedSpaceButton, self.forwardButton, flexibleSpaceButton, self.closeButton]];
+ } else {
+ [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]];
+ }
+
+ self.view.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.toolbar];
[self.view addSubview:self.addressLabel];
[self.view addSubview:self.spinner];
}
+- (id)settingForKey:(NSString*)key
+{
+ return [_settings objectForKey:[key lowercaseString]];
+}
+
- (void) setWebViewFrame : (CGRect) frame {
NSLog(@"Setting the WebView's frame to %@", NSStringFromCGRect(frame));
[self.webView setFrame:frame];
}
-- (void)setCloseButtonTitle:(NSString*)title
+- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString : (int) buttonIndex
{
// the advantage of using UIBarButtonSystemItemDone is the system will localize it for you automatically
// but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one)
self.closeButton = nil;
- self.closeButton = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)];
+ // Initialize with title if title is set, otherwise the title will be 'Done' localized
+ self.closeButton = title != nil ? [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)] : [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
self.closeButton.enabled = YES;
- self.closeButton.tintColor = [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
-
+ // If color on closebutton is requested then initialize with that that color, otherwise use initialize with default
+ self.closeButton.tintColor = colorString != nil ? [self colorFromHexString:colorString] : [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
+
NSMutableArray* items = [self.toolbar.items mutableCopy];
- [items replaceObjectAtIndex:0 withObject:self.closeButton];
+ [items replaceObjectAtIndex:buttonIndex withObject:self.closeButton];
[self.toolbar setItems:items];
}
- (void)showLocationBar:(BOOL)show
{
CGRect locationbarFrame = self.addressLabel.frame;
-
+
BOOL toolbarVisible = !self.toolbar.hidden;
-
+
// prevent double show/hide
if (show == !(self.addressLabel.hidden)) {
return;
}
-
+
if (show) {
self.addressLabel.hidden = NO;
-
+
if (toolbarVisible) {
// toolBar at the bottom, leave as is
// put locationBar on top of the toolBar
-
+
CGRect webViewBounds = self.view.bounds;
webViewBounds.size.height -= FOOTER_HEIGHT;
[self setWebViewFrame:webViewBounds];
-
+
locationbarFrame.origin.y = webViewBounds.size.height;
self.addressLabel.frame = locationbarFrame;
} else {
// no toolBar, so put locationBar at the bottom
-
+
CGRect webViewBounds = self.view.bounds;
webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
[self setWebViewFrame:webViewBounds];
-
+
locationbarFrame.origin.y = webViewBounds.size.height;
self.addressLabel.frame = locationbarFrame;
}
} else {
self.addressLabel.hidden = YES;
-
+
if (toolbarVisible) {
// locationBar is on top of toolBar, hide locationBar
-
+
// webView take up whole height less toolBar height
CGRect webViewBounds = self.view.bounds;
webViewBounds.size.height -= TOOLBAR_HEIGHT;
@@ -692,18 +982,18 @@
{
CGRect toolbarFrame = self.toolbar.frame;
CGRect locationbarFrame = self.addressLabel.frame;
-
+
BOOL locationbarVisible = !self.addressLabel.hidden;
-
+
// prevent double show/hide
if (show == !(self.toolbar.hidden)) {
return;
}
-
+
if (show) {
self.toolbar.hidden = NO;
CGRect webViewBounds = self.view.bounds;
-
+
if (locationbarVisible) {
// locationBar at the bottom, move locationBar up
// put toolBar at the bottom
@@ -717,7 +1007,7 @@
webViewBounds.size.height -= TOOLBAR_HEIGHT;
self.toolbar.frame = toolbarFrame;
}
-
+
if ([toolbarPosition isEqualToString:kInAppBrowserToolbarBarPositionTop]) {
toolbarFrame.origin.y = 0;
webViewBounds.origin.y += toolbarFrame.size.height;
@@ -726,19 +1016,19 @@
toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT);
}
[self setWebViewFrame:webViewBounds];
-
+
} else {
self.toolbar.hidden = YES;
-
+
if (locationbarVisible) {
// locationBar is on top of toolBar, hide toolBar
// put locationBar at the bottom
-
+
// webView take up whole height less locationBar height
CGRect webViewBounds = self.view.bounds;
webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
[self setWebViewFrame:webViewBounds];
-
+
// move locationBar down
locationbarFrame.origin.y = webViewBounds.size.height;
self.addressLabel.frame = locationbarFrame;
@@ -754,11 +1044,13 @@
[super viewDidLoad];
}
-- (void)viewDidUnload
+- (void)viewDidDisappear:(BOOL)animated
{
- [self.webView loadHTMLString:nil baseURL:nil];
- [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
- [super viewDidUnload];
+ [super viewDidDisappear:animated];
+ if (isExiting && (self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) {
+ [self.navigationDelegate browserExit];
+ isExiting = FALSE;
+ }
}
- (UIStatusBarStyle)preferredStatusBarStyle
@@ -772,17 +1064,13 @@
- (void)close
{
- [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
self.currentURL = nil;
-
- if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) {
- [self.navigationDelegate browserExit];
- }
-
+
__weak UIViewController* weakSelf = self;
-
+
// Run later to avoid the "took a long time" log message.
dispatch_async(dispatch_get_main_queue(), ^{
+ isExiting = TRUE;
if ([weakSelf respondsToSelector:@selector(presentingViewController)]) {
[[weakSelf presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} else {
@@ -793,17 +1081,11 @@
- (void)navigateTo:(NSURL*)url
{
- NSURLRequest* request = [NSURLRequest requestWithURL:url];
-
- if (_userAgentLockToken != 0) {
- [self.webView loadRequest:request];
+ if ([url.scheme isEqualToString:@"file"]) {
+ [self.webView loadFileURL:url allowingReadAccessToURL:url];
} else {
- __weak CDVInAppBrowserViewController* weakSelf = self;
- [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
- _userAgentLockToken = lockToken;
- [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken];
- [weakSelf.webView loadRequest:request];
- }];
+ NSURLRequest* request = [NSURLRequest requestWithURL:url];
+ [self.webView loadRequest:request];
}
}
@@ -819,11 +1101,8 @@
- (void)viewWillAppear:(BOOL)animated
{
- if (IsAtLeastiOSVersion(@"7.0")) {
- [[UIApplication sharedApplication] setStatusBarStyle:[self preferredStatusBarStyle]];
- }
[self rePositionViews];
-
+
[super viewWillAppear:animated];
}
@@ -833,213 +1112,117 @@
// change that value.
//
- (float) getStatusBarOffset {
- CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
- float statusBarOffset = IsAtLeastiOSVersion(@"7.0") ? MIN(statusBarFrame.size.width, statusBarFrame.size.height) : 0.0;
- return statusBarOffset;
+ return (float) IsAtLeastiOSVersion(@"7.0") ? [[UIApplication sharedApplication] statusBarFrame].size.height : 0.0;
}
- (void) rePositionViews {
- if ([_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop]) {
- [self.webView setFrame:CGRectMake(self.webView.frame.origin.x, TOOLBAR_HEIGHT, self.webView.frame.size.width, self.webView.frame.size.height)];
- [self.toolbar setFrame:CGRectMake(self.toolbar.frame.origin.x, [self getStatusBarOffset], self.toolbar.frame.size.width, self.toolbar.frame.size.height)];
+ CGRect viewBounds = [self.webView bounds];
+ CGFloat statusBarHeight = [self getStatusBarOffset];
+
+ // orientation portrait or portraitUpsideDown: status bar is on the top and web view is to be aligned to the bottom of the status bar
+ // orientation landscapeLeft or landscapeRight: status bar height is 0 in but lets account for it in case things ever change in the future
+ viewBounds.origin.y = statusBarHeight;
+
+ // account for web view height portion that may have been reduced by a previous call to this method
+ viewBounds.size.height = viewBounds.size.height - statusBarHeight + lastReducedStatusBarHeight;
+ lastReducedStatusBarHeight = statusBarHeight;
+
+ if ((_browserOptions.toolbar) && ([_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop])) {
+ // if we have to display the toolbar on top of the web view, we need to account for its height
+ viewBounds.origin.y += TOOLBAR_HEIGHT;
+ self.toolbar.frame = CGRectMake(self.toolbar.frame.origin.x, statusBarHeight, self.toolbar.frame.size.width, self.toolbar.frame.size.height);
}
+
+ self.webView.frame = viewBounds;
}
-#pragma mark UIWebViewDelegate
+// Helper function to convert hex color string to UIColor
+// Assumes input like "#00FF00" (#RRGGBB).
+// Taken from https://stackoverflow.com/questions/1560081/how-can-i-create-a-uicolor-from-a-hex-string
+- (UIColor *)colorFromHexString:(NSString *)hexString {
+ unsigned rgbValue = 0;
+ NSScanner *scanner = [NSScanner scannerWithString:hexString];
+ [scanner setScanLocation:1]; // bypass '#' character
+ [scanner scanHexInt:&rgbValue];
+ return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
+}
-- (void)webViewDidStartLoad:(UIWebView*)theWebView
-{
- // loading url, start spinner, update back/forward
+#pragma mark WKNavigationDelegate
+- (void)webView:(WKWebView *)theWebView didStartProvisionalNavigation:(WKNavigation *)navigation{
+
+ // loading url, start spinner, update back/forward
+
self.addressLabel.text = NSLocalizedString(@"Loading...", nil);
self.backButton.enabled = theWebView.canGoBack;
self.forwardButton.enabled = theWebView.canGoForward;
-
- [self.spinner startAnimating];
-
- return [self.navigationDelegate webViewDidStartLoad:theWebView];
+
+ NSLog(_browserOptions.hidespinner ? @"Yes" : @"No");
+ if(!_browserOptions.hidespinner) {
+ [self.spinner startAnimating];
+ }
+
+ return [self.navigationDelegate didStartProvisionalNavigation:theWebView];
}
-- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+- (void)webView:(WKWebView *)theWebView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
- BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
-
+ NSURL *url = navigationAction.request.URL;
+ NSURL *mainDocumentURL = navigationAction.request.mainDocumentURL;
+
+ BOOL isTopLevelNavigation = [url isEqual:mainDocumentURL];
+
if (isTopLevelNavigation) {
- self.currentURL = request.URL;
+ self.currentURL = url;
}
- return [self.navigationDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
+
+ [self.navigationDelegate webView:theWebView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
}
-- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+- (void)webView:(WKWebView *)theWebView didFinishNavigation:(WKNavigation *)navigation
{
// update url, stop spinner, update back/forward
-
+
self.addressLabel.text = [self.currentURL absoluteString];
self.backButton.enabled = theWebView.canGoBack;
self.forwardButton.enabled = theWebView.canGoForward;
-
+ theWebView.scrollView.contentInset = UIEdgeInsetsZero;
+
[self.spinner stopAnimating];
-
- // Work around a bug where the first time a PDF is opened, all UIWebViews
- // reload their User-Agent from NSUserDefaults.
- // This work-around makes the following assumptions:
- // 1. The app has only a single Cordova Webview. If not, then the app should
- // take it upon themselves to load a PDF in the background as a part of
- // their start-up flow.
- // 2. That the PDF does not require any additional network requests. We change
- // the user-agent here back to that of the CDVViewController, so requests
- // from it must pass through its white-list. This *does* break PDFs that
- // contain links to other remote PDF/websites.
- // More info at https://issues.apache.org/jira/browse/CB-2225
- BOOL isPDF = [@"true" isEqualToString :[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]];
- if (isPDF) {
- [CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken];
- }
-
- [self.navigationDelegate webViewDidFinishLoad:theWebView];
+
+ [self.navigationDelegate didFinishNavigation:theWebView];
}
-
-- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
-{
+
+- (void)webView:(WKWebView*)theWebView failedNavigation:(NSString*) delegateName withError:(nonnull NSError *)error{
// log fail message, stop spinner, update back/forward
- NSLog(@"webView:didFailLoadWithError - %ld: %@", (long)error.code, [error localizedDescription]);
-
+ NSLog(@"webView:%@ - %ld: %@", delegateName, (long)error.code, [error localizedDescription]);
+
self.backButton.enabled = theWebView.canGoBack;
self.forwardButton.enabled = theWebView.canGoForward;
[self.spinner stopAnimating];
-
+
self.addressLabel.text = NSLocalizedString(@"Load Error", nil);
-
- [self.navigationDelegate webView:theWebView didFailLoadWithError:error];
-}
-
-#pragma mark CDVScreenOrientationDelegate
-
-- (BOOL)shouldAutorotate
-{
- if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
- return [self.orientationDelegate shouldAutorotate];
- }
- return YES;
-}
-
-- (NSUInteger)supportedInterfaceOrientations
-{
- if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
- return [self.orientationDelegate supportedInterfaceOrientations];
- }
-
- return 1 << UIInterfaceOrientationPortrait;
-}
-
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-{
- if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
- return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
- }
-
- return YES;
+
+ [self.navigationDelegate webView:theWebView didFailNavigation:error];
}
-@end
-
-@implementation CDVInAppBrowserOptions
-
-- (id)init
+- (void)webView:(WKWebView*)theWebView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(nonnull NSError *)error
{
- if (self = [super init]) {
- // default values
- self.location = YES;
- self.toolbar = YES;
- self.closebuttoncaption = nil;
- self.toolbarposition = kInAppBrowserToolbarBarPositionBottom;
- self.clearcache = NO;
- self.clearsessioncache = NO;
-
- self.enableviewportscale = NO;
- self.mediaplaybackrequiresuseraction = NO;
- self.allowinlinemediaplayback = NO;
- self.keyboarddisplayrequiresuseraction = YES;
- self.suppressesincrementalrendering = NO;
- self.hidden = NO;
- self.disallowoverscroll = NO;
- }
-
- return self;
+ [self webView:theWebView failedNavigation:@"didFailNavigation" withError:error];
}
-
-+ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
+
+- (void)webView:(WKWebView*)theWebView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(nonnull NSError *)error
{
- CDVInAppBrowserOptions* obj = [[CDVInAppBrowserOptions alloc] init];
-
- // NOTE: this parsing does not handle quotes within values
- NSArray* pairs = [options componentsSeparatedByString:@","];
-
- // parse keys and values, set the properties
- for (NSString* pair in pairs) {
- NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
-
- if ([keyvalue count] == 2) {
- NSString* key = [[keyvalue objectAtIndex:0] lowercaseString];
- NSString* value = [keyvalue objectAtIndex:1];
- NSString* value_lc = [value lowercaseString];
-
- BOOL isBoolean = [value_lc isEqualToString:@"yes"] || [value_lc isEqualToString:@"no"];
- NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
- [numberFormatter setAllowsFloats:YES];
- BOOL isNumber = [numberFormatter numberFromString:value_lc] != nil;
-
- // set the property according to the key name
- if ([obj respondsToSelector:NSSelectorFromString(key)]) {
- if (isNumber) {
- [obj setValue:[numberFormatter numberFromString:value_lc] forKey:key];
- } else if (isBoolean) {
- [obj setValue:[NSNumber numberWithBool:[value_lc isEqualToString:@"yes"]] forKey:key];
- } else {
- [obj setValue:value forKey:key];
- }
- }
- }
- }
-
- return obj;
+ [self webView:theWebView failedNavigation:@"didFailProvisionalNavigation" withError:error];
}
-@end
-
-@implementation CDVInAppBrowserNavigationController : UINavigationController
-
-- (void) dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
- if ( self.presentedViewController) {
- [super dismissViewControllerAnimated:flag completion:completion];
- }
-}
-
-- (void) viewDidLoad {
-
- CGRect frame = [UIApplication sharedApplication].statusBarFrame;
-
- // simplified from: http://stackoverflow.com/a/25669695/219684
-
- UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:[self invertFrameIfNeeded:frame]];
- bgToolbar.barStyle = UIBarStyleDefault;
- [bgToolbar setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
- [self.view addSubview:bgToolbar];
-
- [super viewDidLoad];
-}
-
-- (CGRect) invertFrameIfNeeded:(CGRect)rect {
- // We need to invert since on iOS 7 frames are always in Portrait context
- if (!IsAtLeastiOSVersion(@"8.0")) {
- if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
- CGFloat temp = rect.size.width;
- rect.size.width = rect.size.height;
- rect.size.height = temp;
- }
- rect.origin = CGPointZero;
+#pragma mark WKScriptMessageHandler delegate
+- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
+ if (![message.name isEqualToString:IAB_BRIDGE_NAME]) {
+ return;
}
- return rect;
+ //NSLog(@"Received script message %@", message.body);
+ [self.navigationDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
#pragma mark CDVScreenOrientationDelegate
@@ -1052,24 +1235,27 @@
return YES;
}
-- (NSUInteger)supportedInterfaceOrientations
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
return [self.orientationDelegate supportedInterfaceOrientations];
}
-
+
return 1 << UIInterfaceOrientationPortrait;
}
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
- if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
- return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
- }
+ [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
+ {
+ [self rePositionViews];
+ } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
+ {
- return YES;
-}
+ }];
+ [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+}
-@end
+@end //CDVWKInAppBrowserViewController
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.h b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.h
new file mode 100644
index 00000000..1a6ea220
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.h
@@ -0,0 +1,32 @@
+/*
+ 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 CDVWKInAppBrowserUIDelegate : NSObject <WKUIDelegate>{
+ @private
+ UIViewController* _viewController;
+}
+
+@property (nonatomic, copy) NSString* title;
+
+- (instancetype)initWithTitle:(NSString*)title;
+-(void) setViewController:(UIViewController*) viewController;
+
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.m b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.m
new file mode 100644
index 00000000..4bc7a76b
--- /dev/null
+++ b/StoneIsland/plugins/cordova-plugin-inappbrowser/src/ios/CDVWKInAppBrowserUIDelegate.m
@@ -0,0 +1,127 @@
+/*
+ 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 "CDVWKInAppBrowserUIDelegate.h"
+
+@implementation CDVWKInAppBrowserUIDelegate
+
+- (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];
+
+ [[self getViewController] 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];
+
+ [[self getViewController] 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;
+ }];
+
+ [[self getViewController] presentViewController:alert animated:YES completion:nil];
+}
+
+-(UIViewController*) getViewController
+{
+ return _viewController;
+}
+
+-(void) setViewController:(UIViewController*) viewController
+{
+ _viewController = viewController;
+}
+
+@end