diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4bd6da9..91582f4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,7 +17,6 @@ Thanks! ### Checklist -- [ ] [ICLA](http://www.apache.org/licenses/icla.txt) has been signed and submitted to secretary@apache.org. - [ ] [Reported an issue](http://cordova.apache.org/contribute/issues.html) in the JIRA database - [ ] Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected. - [ ] Added automated test coverage as appropriate for this change. diff --git a/.travis.yml b/.travis.yml index b9af4c5..83aaf0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,12 @@ -language: node_js +osx_image: xcode7.3 +language: objective-c sudo: false -node_js: - - "4.2" +before_install: + - npm cache clean -f + - npm install -g n + - n stable + - node --version +install: + - npm install +script: + - npm test diff --git a/README.md b/README.md index 11ca96d..7c416e7 100644 --- a/README.md +++ b/README.md @@ -45,13 +45,14 @@ To test the development version: cordova platform add https://github.com/apache/cordova-ios.git#master cordova plugin add https://github.com/apache/cordova-plugin-wkwebview-engine.git#master -You also must have Xcode 7 (iOS 9 SDK) installed. Check your Xcode version by running: +You also must have at least Xcode 7 (iOS 9 SDK) installed. Check your Xcode version by running: xcode-select --print-path Required Permissions ----------- -WKWebView may not fully launch (the deviceready event may not fire) unless if the following is included in config.xml: +WKWebView may not fully launch (the deviceready event may not fire) unless if the following is included in config.xml. This should already be installed by Cordova in your platform config.xml when the plugin is installed. + #### config.xml @@ -71,7 +72,9 @@ We have an [experimental plugin](https://github.com/apache/cordova-plugins/tree/ Application Transport Security (ATS) in iOS 9 ----------- -The next released version of the [cordova-cli 5.4.0](https://www.npmjs.com/package/cordova) will support automatic conversion of the [<access>](http://cordova.apache.org/docs/en/edge/guide/appdev/whitelist/index.html) tags in config.xml to Application Transport Security [ATS](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) directives. Upgrade to the version 5.4.0 to use this new functionality. +Starting with [cordova-cli 5.4.0](https://www.npmjs.com/package/cordova), it will support automatic conversion of the [<access>](http://cordova.apache.org/docs/en/edge/guide/appdev/whitelist/index.html) tags in config.xml to Application Transport Security [ATS](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) directives. + +Upgrade to at least version 5.4.0 of the cordova-cli to use this new functionality. Limitations -------- diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 007962d..b89b5df 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -21,8 +21,34 @@ # Release Notes +### 1.1.1 (Dec 07, 2016) +* Updated README.md +* added check for at least iOS 9.0 +* CB-10228:(iOS) AppendUserAgent not working with WKWebView +* [CB-11997](https://issues.apache.org/jira/browse/CB-11997) Code review comments +* [CB-11997](https://issues.apache.org/jira/browse/CB-11997) Add crash recovery for iOS 8 +* [CB-11917](https://issues.apache.org/jira/browse/CB-11917) - Remove pull request template checklist item: "iCLA has been submitted…" +* [CB-11818](https://issues.apache.org/jira/browse/CB-11818) - Avoid retain cycle: WKUserContentController retains its message handler, to break it we cannot pass directly CDVWKWebViewEngine's instance +* [CB-11832](https://issues.apache.org/jira/browse/CB-11832) Incremented plugin version. + +### 1.1.0 (Sep 08, 2016) +* [CB-11824](https://issues.apache.org/jira/browse/CB-11824) - Update tests to include objective-c tests +* [CB-11554](https://issues.apache.org/jira/browse/CB-11554) - fixed unit tests +* [CB-11815](https://issues.apache.org/jira/browse/CB-11815) (**iOS**) Fix hard-coded bridge name "cordova" +* [CB-11554](https://issues.apache.org/jira/browse/CB-11554) - too 'brutal' app reload when title is empty +* [CB-11074](https://issues.apache.org/jira/browse/CB-11074) - Ensure settings from `config.xml` are taken into consideration +* Add ability to set the deceleration rate for the scrollview to 'fast' +* [CB-11496](https://issues.apache.org/jira/browse/CB-11496) - Add obj-c unit tests for `WKWebViewConfiguration`, `WKPreference` +* [CB-11496](https://issues.apache.org/jira/browse/CB-11496) - Create Obj-C unit-tests for `wkwebview-engine` (fix linker error) +* [CB-11452](https://issues.apache.org/jira/browse/CB-11452) - Update README.md with latest news about `AllowInlineMediaPlayback` fix +* [CB-9888](https://issues.apache.org/jira/browse/CB-9888) (**iOS**) check & reload `WKWebView` +* [CB-11375](https://issues.apache.org/jira/browse/CB-11375) - `onReset` method of `CDVPlugin` is never called +* Add pull request template. +* [CB-10818](https://issues.apache.org/jira/browse/CB-10818) - Support the scroll deceleration speed preference. +* [CB-10817](https://issues.apache.org/jira/browse/CB-10817) - Will now reload the `webView` if a crash occurs + ### 1.0.3 (Apr 15, 2016) -* CB-10636 Add `JSHint` for plugins +* [CB-10636](https://issues.apache.org/jira/browse/CB-10636) Add `JSHint` for plugins ### 1.0.2 (Feb 09, 2016) * [CB-10269](https://issues.apache.org/jira/browse/CB-10269) - Replace cordova exec only when present in wkwebview @@ -31,22 +57,22 @@ ### 1.0.1 (Dec 11, 2015) -* CB-10190 - WKWebView engine is not releasing the user-agent lock +* [CB-10190](https://issues.apache.org/jira/browse/CB-10190) - WKWebView engine is not releasing the user-agent lock ### 1.0.0 (Dec 04, 2015) -* CB-10146 - Add to README WKWebViewEngine quirks that will affect migration from UIWebView -* CB-10133 - DataClone DOM Exception 25 thrown for postMessage -* CB-10106 - added bridge proxy -* CB-10107 - nativeEvalAndFetch called for all bridges -* CB-10106 - iOS bridges need to take into account bridge changes -* CB-10073 - WKWebViewEngine should post CDVPluginResetNotification -* CB-10035 Updated RELEASENOTES to be newest to oldest -* CB-10002 - WKWebView should propagate shouldOverrideLoadWithRequest to plugins -* CB-9979 CB-9972 Change ATS link to new link -* CB-9636 - Plugin should detect at runtime iOS 8 and use of file:// url and present an error -* CB-8839 - WKWebView ignores DisallowOverscroll preference -* CB-8556 - fix handleOpenURL for WKWebViewEngine plugin -* CB-8666 - Update CDVWKWebViewEngine plugin to use 4.0.x branch code +* [CB-10146](https://issues.apache.org/jira/browse/CB-10146) - Add to README WKWebViewEngine quirks that will affect migration from UIWebView +* [CB-10133](https://issues.apache.org/jira/browse/CB-10133) - DataClone DOM Exception 25 thrown for postMessage +* [CB-10106](https://issues.apache.org/jira/browse/CB-10106) - added bridge proxy +* [CB-10107](https://issues.apache.org/jira/browse/CB-10107) - nativeEvalAndFetch called for all bridges +* [CB-10106](https://issues.apache.org/jira/browse/CB-10106) - iOS bridges need to take into account bridge changes +* [CB-10073](https://issues.apache.org/jira/browse/CB-10073) - WKWebViewEngine should post CDVPluginResetNotification +* [CB-10035](https://issues.apache.org/jira/browse/CB-10035) Updated RELEASENOTES to be newest to oldest +* [CB-10002](https://issues.apache.org/jira/browse/CB-10002) - WKWebView should propagate shouldOverrideLoadWithRequest to plugins +* [CB-9979](https://issues.apache.org/jira/browse/CB-9979) [CB-9972](https://issues.apache.org/jira/browse/CB-9972) Change ATS link to new link +* [CB-9636](https://issues.apache.org/jira/browse/CB-9636) - Plugin should detect at runtime iOS 8 and use of file:// url and present an error +* [CB-8839](https://issues.apache.org/jira/browse/CB-8839) - WKWebView ignores DisallowOverscroll preference +* [CB-8556](https://issues.apache.org/jira/browse/CB-8556) - fix handleOpenURL for WKWebViewEngine plugin +* [CB-8666](https://issues.apache.org/jira/browse/CB-8666) - Update CDVWKWebViewEngine plugin to use 4.0.x branch code diff --git a/package.json b/package.json index 1065738..c38e3c8 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,8 @@ { "name": "cordova-plugin-wkwebview-engine", - "version": "1.0.4-dev", + "version": "1.1.1", "description": "The official Apache Cordova WKWebView Engine Plugin", "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, "repository": { "type": "git", "url": "https://git-wip-us.apache.org/repos/asf/cordova-plugin-wkwebview-engine.git" @@ -15,8 +12,10 @@ "wkwebview" ], "scripts": { - "test": "npm run jshint", - "jshint": "node node_modules/jshint/bin/jshint src" + "test": "npm run jshint && npm run objc-tests", + "objc-tests": "cd tests/ios && npm test", + "preobjc-tests": "cd tests/ios && npm install", + "jshint": "node_modules/.bin/jshint src" }, "author": "Apache Cordova", "license": "Apache-2.0", diff --git a/plugin.xml b/plugin.xml index e95472e..c8c57c7 100644 --- a/plugin.xml +++ b/plugin.xml @@ -23,7 +23,7 @@ xmlns:rim="http://www.blackberry.com/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-wkwebview-engine" - version="1.0.4-dev"> + version="1.1.1"> Cordova WKWebView Engine Cordova WKWebView Engine Plugin Apache 2.0 diff --git a/src/ios/CDVWKWebViewEngine.m b/src/ios/CDVWKWebViewEngine.m index 9224e31..0985316 100644 --- a/src/ios/CDVWKWebViewEngine.m +++ b/src/ios/CDVWKWebViewEngine.m @@ -26,10 +26,20 @@ Licensed to the Apache Software Foundation (ASF) under one #define CDV_BRIDGE_NAME @"cordova" #define CDV_WKWEBVIEW_FILE_URL_LOAD_SELECTOR @"loadFileURL:allowingReadAccessToURL:" +@interface CDVWKWeakScriptMessageHandler : NSObject + +@property (nonatomic, weak, readonly) idscriptMessageHandler; + +- (instancetype)initWithScriptMessageHandler:(id)scriptMessageHandler; + +@end + + @interface CDVWKWebViewEngine () @property (nonatomic, strong, readwrite) UIView* engineWebView; @property (nonatomic, strong, readwrite) id uiDelegate; +@property (nonatomic, weak) id weakScriptMessageHandler; @end @@ -47,31 +57,51 @@ - (instancetype)initWithFrame:(CGRect)frame if (NSClassFromString(@"WKWebView") == nil) { return nil; } - self.uiDelegate = [[CDVWKWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]]; - - WKUserContentController* userContentController = [[WKUserContentController alloc] init]; - [userContentController addScriptMessageHandler:self name:CDV_BRIDGE_NAME]; - - WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init]; - configuration.userContentController = userContentController; - WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:frame configuration:configuration]; - - wkWebView.UIDelegate = self.uiDelegate; + self.engineWebView = [[WKWebView alloc] initWithFrame:frame]; + } - self.engineWebView = wkWebView; + return self; +} - NSLog(@"Using WKWebView"); +- (WKWebViewConfiguration*) createConfigurationFromSettings:(NSDictionary*)settings +{ + WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init]; + if (settings == nil) { + return configuration; } - return self; + 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; - WKWebView* wkWebView = (WKWebView*)_engineWebView; + 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 )self.viewController; @@ -84,10 +114,10 @@ - (void)pluginInitialize } if ([self.viewController conformsToProtocol:@protocol(WKScriptMessageHandler)]) { - [wkWebView.configuration.userContentController addScriptMessageHandler:(id < WKScriptMessageHandler >)self.viewController name:@"cordova"]; + [wkWebView.configuration.userContentController addScriptMessageHandler:(id < WKScriptMessageHandler >)self.viewController name:CDV_BRIDGE_NAME]; } - [self updateSettings:self.commandDelegate.settings]; + [self updateSettings:settings]; // check if content thread has died on resume NSLog(@"%@", @"CDVWKWebViewEngine will reload WKWebView if required on resume"); @@ -95,31 +125,67 @@ - (void)pluginInitialize 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 *)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 { - [self reloadIfRequired]; + if ([self shouldReloadWebView]) { + NSLog(@"%@", @"CDVWKWebViewEngine reloading!"); + [(WKWebView*)_engineWebView reload]; + } } -- (BOOL)reloadIfRequired +- (BOOL)shouldReloadWebView { WKWebView* wkWebView = (WKWebView*)_engineWebView; - NSString* title = wkWebView.title; - BOOL reload = ((title == nil) || [title isEqualToString:@""]); + 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 reloadIfRequired"); - NSLog(@"CDVWKWebViewEngine reloadIfRequired WKWebView.title: %@", title); - NSLog(@"CDVWKWebViewEngine reloadIfRequired reload: %u", reload); + NSLog(@"%@", @"CDVWKWebViewEngine shouldReloadWebView::"); + NSLog(@"CDVWKWebViewEngine shouldReloadWebView title: %@", title); + NSLog(@"CDVWKWebViewEngine shouldReloadWebView location: %@", [location absoluteString]); + NSLog(@"CDVWKWebViewEngine shouldReloadWebView reload: %u", reload); #endif - - if (reload) { - NSLog(@"%@", @"CDVWKWebViewEngine reloading!"); - [wkWebView reload]; - } + return reload; } + - (id)loadRequest:(NSURLRequest*)request { if ([self canLoadRequest:request]) { // can load, differentiate between file urls and other schemes @@ -174,10 +240,6 @@ - (void)updateSettings:(NSDictionary*)settings WKWebView* wkWebView = (WKWebView*)_engineWebView; wkWebView.configuration.preferences.minimumFontSize = [settings cordovaFloatSettingForKey:@"MinimumFontSize" defaultValue:0.0]; - wkWebView.configuration.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO]; - wkWebView.configuration.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES]; - wkWebView.configuration.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO]; - wkWebView.configuration.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES]; /* wkWebView.configuration.preferences.javaScriptEnabled = [settings cordovaBoolSettingForKey:@"JavaScriptEnabled" default:YES]; @@ -208,6 +270,8 @@ - (void)updateSettings:(NSDictionary*)settings if (![@"fast" isEqualToString:decelerationSetting]) { [wkWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal]; + } else { + [wkWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateFast]; } } @@ -379,4 +443,25 @@ - (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (WKNavi return decisionHandler(NO); } + +@end + +#pragma mark - CDVWKWeakScriptMessageHandler + +@implementation CDVWKWeakScriptMessageHandler + +- (instancetype)initWithScriptMessageHandler:(id)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/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineLibTests/CDVWKWebViewEngineTest.m b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineLibTests/CDVWKWebViewEngineTest.m index 73b5b0a..0c359c2 100644 --- a/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineLibTests/CDVWKWebViewEngineTest.m +++ b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineLibTests/CDVWKWebViewEngineTest.m @@ -20,16 +20,28 @@ Licensed to the Apache Software Foundation (ASF) under one #import #import #import "CDVWKWebViewEngine.h" +#import +#import @interface CDVWKWebViewEngineTest : XCTestCase @property (nonatomic, strong) CDVWKWebViewEngine* plugin; +@property (nonatomic, strong) CDVViewController* viewController; @end @interface CDVWKWebViewEngine () // TODO: expose private interface, if needed +- (BOOL)shouldReloadWebView; +- (BOOL)shouldReloadWebView:(NSURL*)location title:(NSString*)title; + +@end + +@interface CDVViewController () + +// expose property as readwrite, for test purposes +@property (nonatomic, readwrite, strong) NSMutableDictionary* settings; @end @@ -39,7 +51,12 @@ - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. - self.plugin = [[CDVWKWebViewEngine alloc] init]; + // NOTE: no app settings are set, so it will rely on default WKWebViewConfiguration settings + self.plugin = [[CDVWKWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + self.viewController = [[CDVViewController alloc] init]; + [self.viewController registerPlugin:self.plugin withClassName:NSStringFromClass([self.plugin class])]; + + XCTAssert([self.plugin conformsToProtocol:@protocol(CDVWebViewEngineProtocol)], @"Plugin does not conform to CDVWebViewEngineProtocol"); } - (void)tearDown { @@ -47,11 +64,171 @@ - (void)tearDown { [super tearDown]; } -- (void) testCDVWKWebViewEngine { +- (void) testCanLoadRequest { + NSURLRequest* fileUrlRequest = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:@"path/to/file.html"]]; + NSURLRequest* httpUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://apache.org"]]; + NSURLRequest* miscUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"foo://bar"]]; + id webViewEngineProtocol = self.plugin; + + SEL wk_sel = NSSelectorFromString(@"loadFileURL:allowingReadAccessToURL:"); + if ([self.plugin.engineWebView respondsToSelector:wk_sel]) { + XCTAssertTrue([webViewEngineProtocol canLoadRequest:fileUrlRequest]); + } else { + XCTAssertFalse([webViewEngineProtocol canLoadRequest:fileUrlRequest]); + } + + XCTAssertTrue([webViewEngineProtocol canLoadRequest:httpUrlRequest]); + XCTAssertTrue([webViewEngineProtocol canLoadRequest:miscUrlRequest]); +} + +- (void) testUpdateInfo { + // Add -ObjC to Other Linker Flags to test project, to load Categories + // Update objc test template generator as well + + id webViewEngineProtocol = self.plugin; + WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView; + + // iOS >=10 defaults to NO, < 10 defaults to YES. + BOOL mediaPlaybackRequiresUserActionDefault = IsAtLeastiOSVersion(@"10.0")? NO : YES; + + NSDictionary* preferences = @{ + [@"MinimumFontSize" lowercaseString] : @1.1, // default is 0.0 + [@"AllowInlineMediaPlayback" lowercaseString] : @YES, // default is NO + [@"MediaPlaybackRequiresUserAction" lowercaseString] : @(!mediaPlaybackRequiresUserActionDefault), // default is NO on iOS >= 10, YES for < 10 + [@"SuppressesIncrementalRendering" lowercaseString] : @YES, // default is NO + [@"MediaPlaybackAllowsAirPlay" lowercaseString] : @NO, // default is YES + [@"DisallowOverscroll" lowercaseString] : @YES, // so bounces is to be NO. defaults to NO + [@"WKWebViewDecelerationSpeed" lowercaseString] : @"fast" // default is 'normal' + }; + NSDictionary* info = @{ + kCDVWebViewEngineWebViewPreferences : preferences + }; + [webViewEngineProtocol updateWithInfo:info]; + + // the only preference we can set, we **can** change this during runtime + XCTAssertEqualWithAccuracy(wkWebView.configuration.preferences.minimumFontSize, 1.1, 0.0001); + + // the WKWebViewConfiguration properties, we **cannot** change outside of initialization + if (IsAtLeastiOSVersion(@"10.0")) { + XCTAssertFalse(wkWebView.configuration.mediaPlaybackRequiresUserAction); + } else { + XCTAssertTrue(wkWebView.configuration.mediaPlaybackRequiresUserAction); + } + XCTAssertFalse(wkWebView.configuration.allowsInlineMediaPlayback); + XCTAssertFalse(wkWebView.configuration.suppressesIncrementalRendering); + XCTAssertTrue(wkWebView.configuration.mediaPlaybackAllowsAirPlay); + + // in the test above, DisallowOverscroll is YES, so no bounce + if ([wkWebView respondsToSelector:@selector(scrollView)]) { + XCTAssertFalse(((UIScrollView*)[wkWebView scrollView]).bounces); + } else { + for (id subview in wkWebView.subviews) { + if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { + XCTAssertFalse(((UIScrollView*)subview).bounces = NO); + } + } + } + + XCTAssertTrue(wkWebView.scrollView.decelerationRate == UIScrollViewDecelerationRateFast); +} + +- (void) testConfigurationFromSettings { + // we need to re-set the plugin from the "setup" to take in the app settings we need + self.plugin = [[CDVWKWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + self.viewController = [[CDVViewController alloc] init]; + + // generate the app settings + // iOS >=10 defaults to NO, < 10 defaults to YES. + BOOL mediaPlaybackRequiresUserActionDefault = IsAtLeastiOSVersion(@"10.0")? NO : YES; + + NSDictionary* settings = @{ + [@"MinimumFontSize" lowercaseString] : @1.1, // default is 0.0 + [@"AllowInlineMediaPlayback" lowercaseString] : @YES, // default is NO + [@"MediaPlaybackRequiresUserAction" lowercaseString] : @(!mediaPlaybackRequiresUserActionDefault), // default is NO on iOS >= 10, YES for < 10 + [@"SuppressesIncrementalRendering" lowercaseString] : @YES, // default is NO + [@"MediaPlaybackAllowsAirPlay" lowercaseString] : @NO, // default is YES + [@"DisallowOverscroll" lowercaseString] : @YES, // so bounces is to be NO. defaults to NO + [@"WKWebViewDecelerationSpeed" lowercaseString] : @"fast" // default is 'normal' + }; + // this can be set because of the Category at the top of the file + self.viewController.settings = [settings mutableCopy]; + + // app settings are read after you register the plugin + [self.viewController registerPlugin:self.plugin withClassName:NSStringFromClass([self.plugin class])]; + XCTAssert([self.plugin conformsToProtocol:@protocol(CDVWebViewEngineProtocol)], @"Plugin does not conform to CDVWebViewEngineProtocol"); + + // after registering (thus plugin initialization), we can grab the webview configuration + WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView; + + // the only preference we can set, we **can** change this during runtime + XCTAssertEqualWithAccuracy(wkWebView.configuration.preferences.minimumFontSize, 1.1, 0.0001); + + // the WKWebViewConfiguration properties, we **cannot** change outside of initialization + if (IsAtLeastiOSVersion(@"10.0")) { + XCTAssertTrue(wkWebView.configuration.mediaPlaybackRequiresUserAction); + } else { + XCTAssertFalse(wkWebView.configuration.mediaPlaybackRequiresUserAction); + } + XCTAssertTrue(wkWebView.configuration.allowsInlineMediaPlayback); + XCTAssertTrue(wkWebView.configuration.suppressesIncrementalRendering); + // The test case below is in a separate test "testConfigurationWithMediaPlaybackAllowsAirPlay" (Apple bug) + // XCTAssertFalse(wkWebView.configuration.mediaPlaybackAllowsAirPlay); + + // in the test above, DisallowOverscroll is YES, so no bounce + if ([wkWebView respondsToSelector:@selector(scrollView)]) { + XCTAssertFalse(((UIScrollView*)[wkWebView scrollView]).bounces); + } else { + for (id subview in wkWebView.subviews) { + if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { + XCTAssertFalse(((UIScrollView*)subview).bounces = NO); + } + } + } + + XCTAssertTrue(wkWebView.scrollView.decelerationRate == UIScrollViewDecelerationRateFast); +} + +- (void) testShouldReloadWebView { + WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView; + + NSURL* about_blank = [NSURL URLWithString:@"about:blank"]; + NSURL* real_site = [NSURL URLWithString:@"https://cordova.apache.org"]; + NSString* empty_title_document = @""; + + // about:blank should reload + [wkWebView loadRequest:[NSURLRequest requestWithURL:about_blank]]; + XCTAssertTrue([self.plugin shouldReloadWebView]); + + // a network location should *not* reload + [wkWebView loadRequest:[NSURLRequest requestWithURL:real_site]]; + XCTAssertFalse([self.plugin shouldReloadWebView]); + + // document with empty title should *not* reload + // baseURL:nil results in about:blank, so we use a dummy here + [wkWebView loadHTMLString:empty_title_document baseURL:[NSURL URLWithString:@"about:"]]; + XCTAssertFalse([self.plugin shouldReloadWebView]); + + // Anecdotal assertion that when the WKWebView process has died, + // the title is nil, should always reload + XCTAssertTrue([self.plugin shouldReloadWebView:about_blank title:nil]); + XCTAssertTrue([self.plugin shouldReloadWebView:real_site title:nil]); + + // about:blank should always reload + XCTAssertTrue([self.plugin shouldReloadWebView:about_blank title:@"some title"]); + + // non about:blank with a non-nil title should **not** reload + XCTAssertFalse([self.plugin shouldReloadWebView:real_site title:@""]); +} + +- (void) testConfigurationWithMediaPlaybackAllowsAirPlay { + WKWebViewConfiguration* configuration = [WKWebViewConfiguration new]; + configuration.allowsAirPlayForMediaPlayback = NO; + + WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration]; - // Failing tests - XCTAssertTrue(NO); - XCTAssertFalse(YES); + XCTAssertFalse(configuration.allowsAirPlayForMediaPlayback); + // Uh-oh, bug in WKWebView below. Tested on iOS 9, iOS 10 beta 3 + XCTAssertFalse(wkWebView.configuration.allowsAirPlayForMediaPlayback); } @end diff --git a/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/project.pbxproj b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/project.pbxproj index caa1c1e..14a8d3b 100644 --- a/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/project.pbxproj +++ b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/project.pbxproj @@ -285,12 +285,14 @@ 7E9F517619DA09CE00DA31AC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + OTHER_LDFLAGS = "-ObjC"; }; name = Debug; }; 7E9F517719DA09CE00DA31AC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + OTHER_LDFLAGS = "-ObjC"; }; name = Release; }; @@ -327,12 +329,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"", - "\"$(OBJROOT)/UninstalledProducts/include\"", - "\"$(BUILT_PRODUCTS_DIR)\"", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -370,11 +367,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"", - "\n\"$(OBJROOT)/UninstalledProducts/include\"\n\"$(BUILT_PRODUCTS_DIR)\"", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; diff --git a/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/xcshareddata/xcschemes/CDVWKWebViewEngineLibTests.xcscheme b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/xcshareddata/xcschemes/CDVWKWebViewEngineLibTests.xcscheme index c002a4e..6fc153f 100644 --- a/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/xcshareddata/xcschemes/CDVWKWebViewEngineLibTests.xcscheme +++ b/tests/ios/CDVWKWebViewEngineTest/CDVWKWebViewEngineTest.xcodeproj/xcshareddata/xcschemes/CDVWKWebViewEngineLibTests.xcscheme @@ -23,10 +23,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -37,6 +37,11 @@ BlueprintName = "CDVWKWebViewEngineLibTests" ReferencedContainer = "container:CDVWKWebViewEngineTest.xcodeproj"> + + + + @@ -48,15 +53,18 @@ ReferencedContainer = "container:CDVWKWebViewEngineTest.xcodeproj"> + + + version="1.1.1"> cordova-plugin-wkwebview-engine Tests Apache 2.0