Repository: cordova-ios Updated Branches: refs/heads/4.0.x c0085a8c8 -> ef66b33cb
WKWebView - squashed commit. commit da7a3546f809c331cf230af180b3e6f1fb99cb2b Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jul 10 17:48:15 2014 -0700 Support alert/confirm/prompt in WKWebView commit 63552fd3f2548f407aec1bbfda997809d1f2a89d Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jul 10 14:52:44 2014 -0700 Support config.xml preferences for WKWebView, and style fixups commit e67e6bf2577c776c887453801af05f973fb90094 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jul 9 18:44:03 2014 -0700 Use weakSelf in block commit fc83f068388f3402935819f7891906ffa9029cc1 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jul 9 18:38:30 2014 -0700 Support config.xml preferences for WKWebView commit 4eeaf0c8730a30b8709d0d98aba4b2996e34d9f4 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jul 9 18:27:51 2014 -0700 Break out config.xml preferences for UIWebView (related to WKWebView prefs support) commit 9ba496297116f20a4ea0d7b83a9f142ceec2bc84 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jul 9 17:51:11 2014 -0700 Re-add pragma message for iOS 8 commit 2e17db94a87da80a7d50f202eef40178c0a688c0 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jul 9 17:46:00 2014 -0700 Removed unused WKWebView+Private header commit 601eea1c8784e1acf00b0a39ca4a3ea5085b2098 Author: Shazron Abdullah <shaz...@apache.org> Date: Mon Jul 7 15:59:30 2014 -0700 Removed WKWebView+Private category since the functions it covers are already now in iOS 8 beta 3 commit 69c86d641c8a14e23843566ff2024ce77238fd79 Author: Shazron Abdullah <shaz...@apache.org> Date: Mon Jun 23 11:59:51 2014 -0700 Changed @import WebKit back to the old #import (for supporting older IPHONE_OS_DEPLOYMENT_TARGET reasons, bug in Xcode), add #pragma message to add WebKit.framework for iOS 8 commit c133640d264eba5456b3ffd2d3be83e3fd90bf42 Author: Shazron Abdullah <shaz...@gmail.com> Date: Sat Jun 21 22:14:26 2014 -0700 Removed WebKit.framework from templates. commit b4832d132e6628a7ae0ef681eab54554ed913b77 Author: Shazron Abdullah <shaz...@gmail.com> Date: Sat Jun 21 21:45:10 2014 -0700 Using @import instead of #import for WebKit, which doesn't require us to list the framework in the project explicitly. This gives us a true Xcode 5 / 6 compile solution. HOWEVER there is a bug in Xcode (was there since 5) where if you do an @import for a framework, it won't link if your Deployment Target OS version does not also include the framework itself, when compiling for the Simulator. For example, if you @import WebKit, and build for the Simulator, your Deployment Target MUST be iOS 8. The workaround is, this bug does not appear if you build for a device. To make it work for the Simulator, you will have to explicitly add the framework in Build Phases -> Link Binary with Libraries. commit df3d8391546b2bb6da659ca2102609beb7038f7d Author: Shazron Abdullah <shaz...@gmail.com> Date: Sat Jun 21 00:20:36 2014 -0700 Unified the implementations to switch to WKWebView when available and fall back to UIWebView. The implementation even compiles under Xcode 5.1 -- however, the linker will complain under Xcode 5.1 that WebKit.framework is not available. Just remove the framework in "Link Binary With Libraries" Build Phase and it should run. commit 52e27adcd4227621d329fea4743be73bfcb7f4bf Author: Shazron Abdullah <shaz...@apache.org> Date: Fri Jun 20 16:59:48 2014 -0700 Re-add deprecated CDVPlugin functions commit e16e914c3ba2f30324f25da27fbbc0efa9cde727 Merge: f3af6f2 2e1b00c Author: Shazron Abdullah <shaz...@apache.org> Date: Fri Jun 20 16:51:54 2014 -0700 Merge branch 'wkwebview-only' of github.com:shazron/cordova-ios into wkwebview-only Conflicts: CordovaLib/Classes/CDVPlugin.h commit f3af6f2636dad50412da329ce7c21dfaf3717254 Author: Shazron Abdullah <shaz...@apache.org> Date: Fri Jun 20 16:22:08 2014 -0700 Changed webView property of CDVPlugin to UIView. Plugins need to coerce this into a UIWebView or WKWebView. commit c33497742cfe9c7f0e2c7c8902b56cf6fba09ad9 Author: Shazron Abdullah <shaz...@gmail.com> Date: Thu Jun 19 21:39:07 2014 -0700 Fixed native commands not being called when called in a exec callback commit b155b5d9e120a1b7ec2d4a8c3950073792281df5 Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 16:22:04 2014 -0700 Added new cordova.js to support WKWebView Cordova bridge commit 6a96341da8d0f455ed9f977e6329af6d98c357fe Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 16:08:30 2014 -0700 Implemented the WKWebView Cordova bridge. commit 6eb29c716b8308a7f4824a313a232c7c16f421b8 Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 13:42:49 2014 -0700 Moved WKScriptMessageHandler to CDVCommandDelegateImpl commit 374763daf13f73df872a64caa83a7371a0c58542 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:51:51 2014 -0700 Updated templates for WebKit.framework use commit be7fd66f708587bee48b9dbbc7c0b57b03002eb2 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:50:28 2014 -0700 Updated AppDelegate.m to use WKWebView evaluateJavascript (private) commit 05b5c5912e339d29623de75127c2f162e0c875ed Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:49:54 2014 -0700 Added WKWebView support (not unified, stripped out UIWebView use) commit a6ebfb01a7dbad504928b871783f75bbc95e0d85 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:49:00 2014 -0700 Added WKWebView private functions. commit 2e1b00cbb92164114db2f30df10b7f0ec918c9bc Author: Shazron Abdullah <shaz...@apache.org> Date: Fri Jun 20 16:22:08 2014 -0700 Changed webView property of CDVPlugin to UIView. Plugins need to coerce this into a UIWebView or WKWebView. commit 867647075c837c3782333eb6b4c865cb70451aa3 Author: Shazron Abdullah <shaz...@gmail.com> Date: Thu Jun 19 21:39:07 2014 -0700 Fixed native commands not being called when called in a exec callback commit ad3ec2937633995309b77bc663ee22e0b07ac667 Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 16:22:04 2014 -0700 Added new cordova.js to support WKWebView Cordova bridge commit ede3ad5cef804c67e777c0f2c750712df50883f5 Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 16:08:30 2014 -0700 Implemented the WKWebView Cordova bridge. commit c1c39086ab220fcdc5a796b27d38a5d32f7f5f37 Author: Shazron Abdullah <shaz...@apache.org> Date: Thu Jun 19 13:42:49 2014 -0700 Moved WKScriptMessageHandler to CDVCommandDelegateImpl commit 5d2b137645e5fffb460c8e84d16dc8f5d104d085 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:51:51 2014 -0700 Updated templates for WebKit.framework use commit 63bf9a7ca03f92f263a3a3d7226512aee784a171 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:50:28 2014 -0700 Updated AppDelegate.m to use WKWebView evaluateJavascript (private) commit 23c05db85e57f82a4c6fe03fc5faf49abaf947b8 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:49:54 2014 -0700 Added WKWebView support (not unified, stripped out UIWebView use) commit 74a0f4e678e4349849596f23f7f0714aaa574532 Author: Shazron Abdullah <shaz...@apache.org> Date: Wed Jun 18 17:49:00 2014 -0700 Added WKWebView private functions. Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/aa5d0e93 Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/aa5d0e93 Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/aa5d0e93 Branch: refs/heads/4.0.x Commit: aa5d0e937ac68b10aa846d439bb1baba4da12049 Parents: 40b9ddf Author: Shazron Abdullah <shaz...@apache.org> Authored: Mon Jul 14 12:03:19 2014 -0700 Committer: Shazron Abdullah <shaz...@apache.org> Committed: Mon Jul 14 12:03:19 2014 -0700 ---------------------------------------------------------------------- CordovaLib/CDVWebViewUIDelegate.h | 35 +++ CordovaLib/CDVWebViewUIDelegate.m | 126 +++++++++ CordovaLib/Classes/CDV.h | 2 + CordovaLib/Classes/CDVCommandDelegateImpl.h | 6 +- CordovaLib/Classes/CDVCommandDelegateImpl.m | 39 +-- CordovaLib/Classes/CDVCommandQueue.m | 17 +- CordovaLib/Classes/CDVPlugin.h | 9 +- CordovaLib/Classes/CDVPlugin.m | 9 +- CordovaLib/Classes/CDVViewController.h | 18 +- CordovaLib/Classes/CDVViewController.m | 255 ++++++------------ .../Classes/CDVWebViewOperationsDelegate.h | 39 +++ .../Classes/CDVWebViewOperationsDelegate.m | 83 ++++++ CordovaLib/Classes/CDVWebViewPreferences.h | 32 +++ CordovaLib/Classes/CDVWebViewPreferences.m | 261 +++++++++++++++++++ CordovaLib/CordovaLib.xcodeproj/project.pbxproj | 26 ++ CordovaLib/cordova.js | 51 ++-- CordovaLibTests/CordovaLibApp/config.xml | 1 + .../project/__CLI__.xcodeproj/project.pbxproj | 6 + .../__NON-CLI__.xcodeproj/project.pbxproj | 8 +- .../__PROJECT_NAME__/Classes/AppDelegate.m | 16 +- .../project/__PROJECT_NAME__/config.xml | 1 + 21 files changed, 812 insertions(+), 228 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/CDVWebViewUIDelegate.h ---------------------------------------------------------------------- diff --git a/CordovaLib/CDVWebViewUIDelegate.h b/CordovaLib/CDVWebViewUIDelegate.h new file mode 100644 index 0000000..9ff2ac1 --- /dev/null +++ b/CordovaLib/CDVWebViewUIDelegate.h @@ -0,0 +1,35 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#import <Foundation/Foundation.h> + +#ifdef __IPHONE_8_0 + #import <WebKit/WebKit.h> +#endif + +@interface CDVWebViewUIDelegate : NSObject +#ifdef __IPHONE_8_0 + <WKUIDelegate> +#endif + +@property (nonatomic, copy) NSString* title; + +- (instancetype)initWithTitle:(NSString*)title; + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/CDVWebViewUIDelegate.m ---------------------------------------------------------------------- diff --git a/CordovaLib/CDVWebViewUIDelegate.m b/CordovaLib/CDVWebViewUIDelegate.m new file mode 100644 index 0000000..6f98327 --- /dev/null +++ b/CordovaLib/CDVWebViewUIDelegate.m @@ -0,0 +1,126 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#ifdef __IPHONE_8_0 + +#import "CDVWebViewUIDelegate.h" + + @implementation CDVWebViewUIDelegate + + - (instancetype)initWithTitle:(NSString*)title + { + self = [super init]; + if (self) { + self.title = title; + } + + return self; + } + + - (void) webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message + initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)())completionHandler + { + UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) + { + completionHandler(); + [alert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [alert addAction:ok]; + + UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController; + + [rootController presentViewController:alert animated:YES completion:nil]; + } + + - (void) webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message + initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler + { + UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) + { + completionHandler(YES); + [alert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [alert addAction:ok]; + + UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) + { + completionHandler(NO); + [alert dismissViewControllerAnimated:YES completion:nil]; + }]; + [alert addAction:cancel]; + + UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController; + + [rootController presentViewController:alert animated:YES completion:nil]; + } + + - (void) webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt + defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame + completionHandler:(void (^)(NSString* result))completionHandler + { + UIAlertController* alert = [UIAlertController alertControllerWithTitle:self.title + message:prompt + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction* ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) + { + completionHandler(((UITextField*)alert.textFields[0]).text); + [alert dismissViewControllerAnimated:YES completion:nil]; + }]; + + [alert addAction:ok]; + + UIAlertAction* cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) + { + completionHandler(nil); + [alert dismissViewControllerAnimated:YES completion:nil]; + }]; + [alert addAction:cancel]; + + [alert addTextFieldWithConfigurationHandler:^(UITextField* textField) { + textField.text = defaultText; + }]; + + UIViewController* rootController = [UIApplication sharedApplication].delegate.window.rootViewController; + + [rootController presentViewController:alert animated:YES completion:nil]; + } + + @end +#endif /* ifdef __IPHONE_8_0 */ http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDV.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDV.h b/CordovaLib/Classes/CDV.h index 6cf592a..d368961 100644 --- a/CordovaLib/Classes/CDV.h +++ b/CordovaLib/Classes/CDV.h @@ -31,6 +31,8 @@ #import "CDVLocalStorage.h" #import "CDVScreenOrientationDelegate.h" #import "CDVTimer.h" +#import "CDVWebViewPreferences.h" +#import "CDVWebViewOperationsDelegate.h" #import "NSArray+Comparisons.h" #import "NSData+Base64.h" http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVCommandDelegateImpl.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVCommandDelegateImpl.h b/CordovaLib/Classes/CDVCommandDelegateImpl.h index 0531134..4a74d55 100644 --- a/CordovaLib/Classes/CDVCommandDelegateImpl.h +++ b/CordovaLib/Classes/CDVCommandDelegateImpl.h @@ -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 @@ -24,7 +24,7 @@ @class CDVCommandQueue; @interface CDVCommandDelegateImpl : NSObject <CDVCommandDelegate>{ - @private +@private __weak CDVViewController* _viewController; NSRegularExpression* _callbackIdPattern; @protected http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVCommandDelegateImpl.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVCommandDelegateImpl.m b/CordovaLib/Classes/CDVCommandDelegateImpl.m index 07100a2..59d19ba 100644 --- a/CordovaLib/Classes/CDVCommandDelegateImpl.m +++ b/CordovaLib/Classes/CDVCommandDelegateImpl.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 @@ -41,16 +41,16 @@ NSBundle* mainBundle = [NSBundle mainBundle]; NSMutableArray* directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]]; NSString* filename = [directoryParts lastObject]; - + [directoryParts removeLastObject]; - + NSString* directoryPartsJoined = [directoryParts componentsJoinedByString:@"/"]; NSString* directoryStr = _viewController.wwwFolderName; - + if ([directoryPartsJoined length] > 0) { directoryStr = [NSString stringWithFormat:@"%@/%@", _viewController.wwwFolderName, [directoryParts componentsJoinedByString:@"/"]]; } - + return [mainBundle pathForResource:filename ofType:@"" inDirectory:directoryStr]; } @@ -64,13 +64,18 @@ - (void)evalJsHelper2:(NSString*)js { CDV_EXEC_LOG(@"Exec: evalling: %@", [js substringToIndex:MIN([js length], 160)]); - NSString* commandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:js]; - if ([commandsJSON length] > 0) { - CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining."); - } - - [_commandQueue enqueueCommandBatch:commandsJSON]; - [_commandQueue executePending]; + [_viewController.webViewOperationsDelegate evaluateJavaScript:js completionHandler:^(id obj, NSError* error) { + // TODO: obj can be something other than string + if ([obj isKindOfClass:[NSString class]]) { + NSString* commandsJSON = (NSString*)obj; + if ([commandsJSON length] > 0) { + CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining."); + } + + [_commandQueue enqueueCommandBatch:commandsJSON]; + [_commandQueue executePending]; + } + }]; } - (void)evalJsHelper:(NSString*)js @@ -98,7 +103,7 @@ - (BOOL)isValidCallbackId:(NSString*)callbackId { NSError* err = nil; - + // Initialize on first use if (_callbackIdPattern == nil) { // Catch any invalid characters in the callback id. @@ -130,9 +135,9 @@ int status = [result.status intValue]; BOOL keepCallback = [result.keepCallback boolValue]; NSString* argumentsAsJSON = [result argumentsAsJSON]; - + NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)", callbackId, status, argumentsAsJSON, keepCallback]; - + [self evalJsHelper:js]; } @@ -169,7 +174,7 @@ - (BOOL)URLIsWhitelisted:(NSURL*)url { return ![_viewController.whitelist schemeIsAllowed:[url scheme]] || - [_viewController.whitelist URLIsAllowed:url logFailure:NO]; + [_viewController.whitelist URLIsAllowed:url logFailure:NO]; } - (NSDictionary*)settings http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVCommandQueue.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVCommandQueue.m b/CordovaLib/Classes/CDVCommandQueue.m index 1eddfe3..b4f1fa6 100644 --- a/CordovaLib/Classes/CDVCommandQueue.m +++ b/CordovaLib/Classes/CDVCommandQueue.m @@ -109,9 +109,22 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame. - (void)fetchCommandsFromJs { + NSString* js = @"cordova.require('cordova/exec').nativeFetchMessages()"; + SEL ui_selector = NSSelectorFromString(@"stringByEvaluatingJavaScriptFromString:"); + // Grab all the queued commands from the JS side. - NSString* queuedCommandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString: - @"cordova.require('cordova/exec').nativeFetchMessages()"]; + NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: + [[_viewController.webView class] instanceMethodSignatureForSelector:ui_selector]]; + + [invocation setSelector:ui_selector]; + [invocation setTarget:_viewController.webView]; + // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation + [invocation setArgument:&(js) atIndex:2]; + + [invocation invoke]; + + NSString* queuedCommandsJSON; + [invocation getReturnValue:&(queuedCommandsJSON)]; CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0); [self enqueueCommandBatch:queuedCommandsJSON]; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVPlugin.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVPlugin.h b/CordovaLib/Classes/CDVPlugin.h index 20c209b..89fed08 100644 --- a/CordovaLib/Classes/CDVPlugin.h +++ b/CordovaLib/Classes/CDVPlugin.h @@ -22,6 +22,9 @@ #import "CDVPluginResult.h" #import "NSMutableArray+QueueAdditions.h" #import "CDVCommandDelegate.h" +#ifdef __IPHONE_8_0 + #import <WebKit/WebKit.h> +#endif extern NSString* const CDVPageDidLoadNotification; extern NSString* const CDVPluginHandleOpenURLNotification; @@ -32,13 +35,13 @@ extern NSString* const CDVRemoteNotificationError; @interface CDVPlugin : NSObject {} -@property (nonatomic, weak) UIWebView* webView; +@property (nonatomic, weak) UIView* webView; @property (nonatomic, weak) UIViewController* viewController; @property (nonatomic, weak) id <CDVCommandDelegate> commandDelegate; @property (readonly, assign) BOOL hasPendingOperation; -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView; +- (instancetype)initWithWebView:(UIView*)theWebView; - (void)pluginInitialize; - (void)handleOpenURL:(NSNotification*)notification; @@ -58,7 +61,7 @@ extern NSString* const CDVRemoteNotificationError; - (id)appDelegate; -// TODO(agrieve): Deprecate these in favour of using CDVCommandDelegate directly. +// TODO(agrieve)x: Deprecate these in favour of using CDVCommandDelegate directly. - (NSString*)writeJavascript:(NSString*)javascript CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of evalJs:"); - (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of sendPluginResult:callbackId"); http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVPlugin.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVPlugin.m b/CordovaLib/Classes/CDVPlugin.m index ea81ddd..5f90311 100644 --- a/CordovaLib/Classes/CDVPlugin.m +++ b/CordovaLib/Classes/CDVPlugin.m @@ -18,6 +18,7 @@ */ #import "CDVPlugin.h" +#import "CDVViewController.h" NSString* const CDVPageDidLoadNotification = @"CDVPageDidLoadNotification"; NSString* const CDVPluginHandleOpenURLNotification = @"CDVPluginHandleOpenURLNotification"; @@ -36,12 +37,12 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; @synthesize webView, viewController, commandDelegate, hasPendingOperation; // Do not override these methods. Use pluginInitialize instead. -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings +- (instancetype)initWithWebView:(UIView*)theWebView settings:(NSDictionary*)classSettings { return [self initWithWebView:theWebView]; } -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView +- (instancetype)initWithWebView:(UIView*)theWebView { self = [super init]; if (self) { @@ -130,7 +131,9 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; - (NSString*)writeJavascript:(NSString*)javascript { - return [self.webView stringByEvaluatingJavaScriptFromString:javascript]; + // TODO: although deprecated, should have some solution here instead of removing it + [((CDVViewController*)self.viewController).webViewOperationsDelegate evaluateJavaScript : javascript completionHandler : nil]; // bad cast, but ok for now + return @""; } - (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVViewController.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVViewController.h b/CordovaLib/Classes/CDVViewController.h index 1015c50..d38d9d3 100644 --- a/CordovaLib/Classes/CDVViewController.h +++ b/CordovaLib/Classes/CDVViewController.h @@ -26,8 +26,19 @@ #import "CDVWhitelist.h" #import "CDVScreenOrientationDelegate.h" #import "CDVPlugin.h" +#import "CDVWebViewOperationsDelegate.h" +#ifdef __IPHONE_8_0 + #import <WebKit/WebKit.h> +#else + @protocol WKScriptMessageHandler + @end +#endif -@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{ +@protocol WKScriptMessageHandler; + +@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate, WKScriptMessageHandler>{ + @protected + CDVWebViewOperationsDelegate* _webViewOperationsDelegate; @protected id <CDVCommandDelegate> _commandDelegate; @protected @@ -35,7 +46,7 @@ NSString* _userAgent; } -@property (nonatomic, strong) IBOutlet UIWebView* webView; +@property (nonatomic, strong) IBOutlet UIView* webView; @property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects; @property (nonatomic, readonly, strong) NSDictionary* pluginsMap; @@ -47,6 +58,7 @@ @property (nonatomic, readwrite, copy) NSString* wwwFolderName; @property (nonatomic, readwrite, copy) NSString* startPage; @property (nonatomic, readonly, strong) CDVCommandQueue* commandQueue; +@property (nonatomic, readonly, strong) CDVWebViewOperationsDelegate* webViewOperationsDelegate; @property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate; @property (nonatomic, readonly) NSString* userAgent; @@ -55,7 +67,7 @@ - (void)printMultitaskingInfo; - (void)createGapView; -- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds; +- (UIView*)newCordovaViewWithFrame:(CGRect)bounds; - (void)javascriptAlert:(NSString*)text; - (NSString*)appURLScheme; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVViewController.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m index 66c1850..d5aeb89 100644 --- a/CordovaLib/Classes/CDVViewController.m +++ b/CordovaLib/Classes/CDVViewController.m @@ -23,6 +23,7 @@ #import "CDVConfigParser.h" #import "CDVUserAgentUtil.h" #import "CDVWebViewDelegate.h" +#import "CDVWebViewUIDelegate.h" #import <AVFoundation/AVFoundation.h> #define degreesToRadian(x) (M_PI * (x) / 180.0) @@ -30,6 +31,7 @@ @interface CDVViewController () { NSInteger _userAgentLockToken; CDVWebViewDelegate* _webViewDelegate; + CDVWebViewUIDelegate* _webViewUIDelegate; } @property (nonatomic, readwrite, strong) NSXMLParser* configParser; @@ -55,6 +57,7 @@ @synthesize wwwFolderName, startPage, initialized, openURL; @synthesize commandDelegate = _commandDelegate; @synthesize commandQueue = _commandQueue; +@synthesize webViewOperationsDelegate = _webViewOperationsDelegate; - (void)__init { @@ -254,22 +257,15 @@ // Configure WebView _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self]; - self.webView.delegate = _webViewDelegate; + if ([webView respondsToSelector:@selector(setDelegate:)]) { + [webView setValue:_webViewDelegate forKey:@"delegate"]; + } // register this viewcontroller with the NSURLProtocol, only after the User-Agent is set [CDVURLProtocol registerViewController:self]; // ///////////////// - NSString* enableViewportScale = [self settingForKey:@"EnableViewportScale"]; - NSNumber* allowInlineMediaPlayback = [self settingForKey:@"AllowInlineMediaPlayback"]; - BOOL mediaPlaybackRequiresUserAction = YES; // default value - if ([self settingForKey:@"MediaPlaybackRequiresUserAction"]) { - mediaPlaybackRequiresUserAction = [(NSNumber*)[self settingForKey:@"MediaPlaybackRequiresUserAction"] boolValue]; - } - - self.webView.scalesPageToFit = [enableViewportScale boolValue]; - /* * Fire up CDVLocalStorage to work-around WebKit storage limitations: on all iOS 5.1+ versions for local-only backups, but only needed on iOS 5.1 for cloud backup. */ @@ -278,150 +274,8 @@ [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage class])]; } - /* - * This is for iOS 4.x, where you can allow inline <video> and <audio>, and also autoplay them - */ - if ([allowInlineMediaPlayback boolValue] && [self.webView respondsToSelector:@selector(allowsInlineMediaPlayback)]) { - self.webView.allowsInlineMediaPlayback = YES; - } - if ((mediaPlaybackRequiresUserAction == NO) && [self.webView respondsToSelector:@selector(mediaPlaybackRequiresUserAction)]) { - self.webView.mediaPlaybackRequiresUserAction = NO; - } - - // By default, overscroll bouncing is allowed. - // UIWebViewBounce has been renamed to DisallowOverscroll, but both are checked. - BOOL bounceAllowed = YES; - NSNumber* disallowOverscroll = [self settingForKey:@"DisallowOverscroll"]; - if (disallowOverscroll == nil) { - NSNumber* bouncePreference = [self settingForKey:@"UIWebViewBounce"]; - bounceAllowed = (bouncePreference == nil || [bouncePreference boolValue]); - } else { - bounceAllowed = ![disallowOverscroll boolValue]; - } - - // prevent webView from bouncing - // based on the DisallowOverscroll/UIWebViewBounce key in config.xml - if (!bounceAllowed) { - if ([self.webView respondsToSelector:@selector(scrollView)]) { - ((UIScrollView*)[self.webView scrollView]).bounces = NO; - } else { - for (id subview in self.webView.subviews) { - if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { - ((UIScrollView*)subview).bounces = NO; - } - } - } - } - - NSString* decelerationSetting = [self settingForKey:@"UIWebViewDecelerationSpeed"]; - if (![@"fast" isEqualToString : decelerationSetting]) { - [self.webView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal]; - } - - /* - * iOS 6.0 UIWebView properties - */ - if (IsAtLeastiOSVersion(@"6.0")) { - BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES - if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"] != nil) { - if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"]) { - keyboardDisplayRequiresUserAction = [(NSNumber*)[self settingForKey:@"KeyboardDisplayRequiresUserAction"] boolValue]; - } - } - - // property check for compiling under iOS < 6 - if ([self.webView respondsToSelector:@selector(setKeyboardDisplayRequiresUserAction:)]) { - [self.webView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:@"keyboardDisplayRequiresUserAction"]; - } - - BOOL suppressesIncrementalRendering = NO; // SuppressesIncrementalRendering - defaults to NO - if ([self settingForKey:@"SuppressesIncrementalRendering"] != nil) { - if ([self settingForKey:@"SuppressesIncrementalRendering"]) { - suppressesIncrementalRendering = [(NSNumber*)[self settingForKey:@"SuppressesIncrementalRendering"] boolValue]; - } - } - - // property check for compiling under iOS < 6 - if ([self.webView respondsToSelector:@selector(setSuppressesIncrementalRendering:)]) { - [self.webView setValue:[NSNumber numberWithBool:suppressesIncrementalRendering] forKey:@"suppressesIncrementalRendering"]; - } - } - - /* - * iOS 7.0 UIWebView properties - */ - if (IsAtLeastiOSVersion(@"7.0")) { - SEL ios7sel = nil; - id prefObj = nil; - - CGFloat gapBetweenPages = 0.0; // default - prefObj = [self settingForKey:@"GapBetweenPages"]; - if (prefObj != nil) { - gapBetweenPages = [prefObj floatValue]; - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setGapBetweenPages:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithFloat:gapBetweenPages] forKey:@"gapBetweenPages"]; - } - - CGFloat pageLength = 0.0; // default - prefObj = [self settingForKey:@"PageLength"]; - if (prefObj != nil) { - pageLength = [[self settingForKey:@"PageLength"] floatValue]; - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPageLength:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithBool:pageLength] forKey:@"pageLength"]; - } - - NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage - prefObj = [self settingForKey:@"PaginationBreakingMode"]; - if (prefObj != nil) { - NSArray* validValues = @[@"page", @"column"]; - NSString* prefValue = [validValues objectAtIndex:0]; - - if ([prefObj isKindOfClass:[NSString class]]) { - prefValue = prefObj; - } - - paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]]; - if (paginationBreakingMode == NSNotFound) { - paginationBreakingMode = 0; - } - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPaginationBreakingMode:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithInteger:paginationBreakingMode] forKey:@"paginationBreakingMode"]; - } - - NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated - prefObj = [self settingForKey:@"PaginationMode"]; - if (prefObj != nil) { - NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"]; - NSString* prefValue = [validValues objectAtIndex:0]; - - if ([prefObj isKindOfClass:[NSString class]]) { - prefValue = prefObj; - } - - paginationMode = [validValues indexOfObject:[prefValue lowercaseString]]; - if (paginationMode == NSNotFound) { - paginationMode = 0; - } - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPaginationMode:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithInteger:paginationMode] forKey:@"paginationMode"]; - } - } + CDVWebViewPreferences* prefs = [[CDVWebViewPreferences alloc] initWithWebView:webView]; + [prefs updateSettings:self.settings]; if ([self.startupPluginNames count] > 0) { [CDVTimer start:@"TotalPluginStartup"]; @@ -441,10 +295,10 @@ [CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken]; if (!loadErr) { NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]; - [self.webView loadRequest:appReq]; + [_webViewOperationsDelegate loadRequest:appReq]; } else { NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr]; - [self.webView loadHTMLString:html baseURL:nil]; + [_webViewOperationsDelegate loadHTMLString:html baseURL:nil]; } }]; } @@ -508,20 +362,22 @@ } } -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +- (void)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation completionHandler:(void (^)(BOOL))completionHandler { // First, ask the webview via JS if it supports the new orientation NSString* jsCall = [NSString stringWithFormat: @"window.shouldRotateToOrientation && window.shouldRotateToOrientation(%ld);" , (long)[self mapIosOrientationToJsOrientation:interfaceOrientation]]; - NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCall]; + __weak CDVViewController* weakSelf = self; - if ([res length] > 0) { - return [res boolValue]; - } - - // if js did not handle the new orientation (no return value), use values from the plist (via supportedOrientations) - return [self supportsOrientation:interfaceOrientation]; + [_webViewOperationsDelegate evaluateJavaScript:jsCall completionHandler:^(NSString* obj, NSError* error) { + if ([obj length] > 0) { + completionHandler([obj boolValue]); + } else { + // if js did not handle the new orientation (no return value), use values from the plist (via supportedOrientations) + completionHandler([weakSelf supportsOrientation:interfaceOrientation]); + } + }]; } - (BOOL)shouldAutorotate @@ -554,9 +410,37 @@ return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]]; } -- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds +- (UIView*)newCordovaViewWithFrame:(CGRect)bounds { - return [[UIWebView alloc] initWithFrame:bounds]; + UIView* cordovaView = nil; + BOOL useWKWebView = NO; // default value + + if ([self settingForKey:@"UseWKWebView"]) { + useWKWebView = [(NSNumber*)[self settingForKey:@"UseWKWebView"] boolValue]; + } + + if (NSClassFromString(@"WKWebView") && useWKWebView) { +#ifdef __IPHONE_8_0 + WKUserContentController* userContentController = [[WKUserContentController alloc] init]; + + // scriptMessageHandler is the object that conforms to the WKScriptMessageHandler protocol + // see https://developer.apple.com/library/prerelease/ios/documentation/WebKit/Reference/WKScriptMessageHandler_Ref/index.html#//apple_ref/swift/intf/WKScriptMessageHandler + if ([_commandDelegate conformsToProtocol:@protocol(WKScriptMessageHandler)]) { + [userContentController addScriptMessageHandler:self name:@"cordova"]; + } + + WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init]; + configuration.userContentController = userContentController; + + cordovaView = [[WKWebView alloc] initWithFrame:bounds configuration:configuration]; + _webViewUIDelegate = [[CDVWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]]; + ((WKWebView*)cordovaView).UIDelegate = _webViewUIDelegate; +#endif + } else { + cordovaView = [[UIWebView alloc] initWithFrame:bounds]; + } + + return cordovaView; } - (NSString*)userAgent @@ -577,6 +461,7 @@ self.webView = [self newCordovaViewWithFrame:webViewBounds]; self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + _webViewOperationsDelegate = [[CDVWebViewOperationsDelegate alloc] initWithWebView:self.webView]; [self.view addSubview:self.webView]; [self.view sendSubviewToBack:self.webView]; @@ -612,7 +497,9 @@ // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; - self.webView.delegate = nil; + if ([webView respondsToSelector:@selector(setDelegate:)]) { + [webView setValue:nil forKey:@"delegate"]; + } self.webView = nil; [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; } @@ -975,11 +862,38 @@ if (self.openURL) { // calls into javascript global function 'handleOpenURL' NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", [self.openURL description]]; - [self.webView stringByEvaluatingJavaScriptFromString:jsString]; + [_webViewOperationsDelegate evaluateJavaScript:jsString completionHandler:nil]; self.openURL = nil; } } +#pragma mark WKScriptMessageHandler implementation + +#ifdef __IPHONE_8_0 + - (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message + { + if (![message.name isEqualToString:@"cordova"]) { + return; + } + + NSArray* jsonEntry = message.body; // NSString:callbackId, NSString:service, NSString:action, NSArray:args + CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry]; + CDV_EXEC_LOG(@"Exec(%@): Calling %@.%@", command.callbackId, command.className, command.methodName); + + if (![_commandQueue execute:command]) { + #ifdef DEBUG + NSString* commandJson = [jsonEntry JSONString]; + static NSUInteger maxLogLength = 1024; + NSString* commandString = ([commandJson length] > maxLogLength) ? + [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] : + commandJson; + + DLog(@"FAILED pluginJSON = %@", commandString); + #endif + } + } +#endif /* ifdef __IPHONE_8_0 */ + // /////////////////////// - (void)dealloc @@ -987,7 +901,10 @@ [CDVURLProtocol unregisterViewController:self]; [[NSNotificationCenter defaultCenter] removeObserver:self]; - self.webView.delegate = nil; + if ([webView respondsToSelector:@selector(setDelegate:)]) { + [webView setValue:nil forKey:@"delegate"]; + } + self.webView = nil; [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; [_commandQueue dispose]; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVWebViewOperationsDelegate.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewOperationsDelegate.h b/CordovaLib/Classes/CDVWebViewOperationsDelegate.h new file mode 100644 index 0000000..34330a1 --- /dev/null +++ b/CordovaLib/Classes/CDVWebViewOperationsDelegate.h @@ -0,0 +1,39 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +#ifdef __IPHONE_8_0 +#pragma message("For iOS 8 - Please add WebKit.framework into your 'Link Binary with Libraries' Build Phase Project Setting. This will be baked in once Xcode 6 is required.") +#endif /* ifdef __IPHONE_8_0 */ + + +@interface CDVWebViewOperationsDelegate : NSObject { + @private + __weak UIView* _webView; +} + +- (instancetype) initWithWebView:(UIView*)webView; + +- (void)loadRequest:(NSURLRequest*)request; +- (void)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL; +- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler; + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVWebViewOperationsDelegate.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewOperationsDelegate.m b/CordovaLib/Classes/CDVWebViewOperationsDelegate.m new file mode 100644 index 0000000..d243aba --- /dev/null +++ b/CordovaLib/Classes/CDVWebViewOperationsDelegate.m @@ -0,0 +1,83 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#import <objc/message.h> +#import "CDVWebViewOperationsDelegate.h" + +@implementation CDVWebViewOperationsDelegate + +- (instancetype) initWithWebView:(UIView*)webView +{ + self = [super init]; + if (self) { + Class wk_class = NSClassFromString(@"WKWebView"); + if ( !([webView isKindOfClass:wk_class] || [webView isKindOfClass:[UIWebView class]] )) { + return nil; + } + _webView = webView; + } + + return self; +} + +- (void)loadRequest:(NSURLRequest*)request +{ + SEL selector = NSSelectorFromString(@"loadRequest:"); + if ([_webView respondsToSelector:selector]) { + // UIKit operations have to be on the main thread. and this method is synchronous + [_webView performSelectorOnMainThread:selector withObject:request waitUntilDone:YES]; + } +} + +- (void)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL +{ + SEL selector = NSSelectorFromString(@"loadHTMLString:baseURL:"); + + dispatch_block_t invoke = ^(void) { + ((void (*)(id, SEL, id, id))objc_msgSend)(_webView, selector, string, baseURL); + }; + + if ([_webView respondsToSelector:selector]) { + // UIKit operations have to be on the main thread. + // perform a synchronous invoke on the main thread without deadlocking + if ([NSThread isMainThread]) { + invoke(); + } else { + dispatch_sync(dispatch_get_main_queue(), invoke); + } + } +} + +- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler +{ + SEL ui_sel = NSSelectorFromString(@"stringByEvaluatingJavaScriptFromString:"); + SEL wk_sel = NSSelectorFromString(@"evaluateJavaScript:completionHandler:"); + + // UIKit operations have to be on the main thread. This method does not need to be synchronous + dispatch_async(dispatch_get_main_queue(), ^{ + if ([_webView respondsToSelector:ui_sel]) { + NSString* ret = ((NSString* (*)(id, SEL, id))objc_msgSend)(_webView, ui_sel, javaScriptString); + completionHandler(ret, nil); + } else if ([_webView respondsToSelector:wk_sel]) { + ((void (*)(id, SEL, id, id))objc_msgSend)(_webView, wk_sel, javaScriptString, completionHandler); + } + }); +} + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVWebViewPreferences.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewPreferences.h b/CordovaLib/Classes/CDVWebViewPreferences.h new file mode 100644 index 0000000..5058eef --- /dev/null +++ b/CordovaLib/Classes/CDVWebViewPreferences.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 <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +@interface CDVWebViewPreferences: NSObject { + @private + __weak UIView* _webView; +} + +- (instancetype) initWithWebView:(UIView*)webView; +- (void) updateSettings:(NSDictionary*)settings; + + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/Classes/CDVWebViewPreferences.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewPreferences.m b/CordovaLib/Classes/CDVWebViewPreferences.m new file mode 100644 index 0000000..a42b3aa --- /dev/null +++ b/CordovaLib/Classes/CDVWebViewPreferences.m @@ -0,0 +1,261 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +#import "CDVWebViewPreferences.h" +#import "CDVAvailability.h" +#import <objc/message.h> + +#ifdef __IPHONE_8_0 + #import <WebKit/WebKit.h> +#endif /* ifdef __IPHONE_8_0 */ + +@implementation CDVWebViewPreferences + +- (instancetype)initWithWebView:(UIView*)webView +{ + self = [super init]; + if (self) { + Class wk_class = NSClassFromString(@"WKWebView"); + if (!([webView isKindOfClass:wk_class] || [webView isKindOfClass:[UIWebView class]])) { + return nil; + } + _webView = webView; + } + + return self; +} + +- (void)updateSettings:(NSDictionary*)settings +{ + Class wk_class = NSClassFromString(@"WKWebView"); + SEL ui_sel = NSSelectorFromString(@"updateUIWebView:settings:"); + SEL wk_sel = NSSelectorFromString(@"updateWKWebView:settings:"); + + __weak id weakSelf = self; + + dispatch_block_t invoke = ^(void) { + if ([_webView isKindOfClass:[UIWebView class]] && [weakSelf respondsToSelector:ui_sel]) { + ((void (*)(id, SEL, id, id))objc_msgSend)(weakSelf, ui_sel, _webView, settings); + } else if ([_webView isKindOfClass:wk_class] && [weakSelf respondsToSelector:wk_sel]) { + ((void (*)(id, SEL, id, id))objc_msgSend)(weakSelf, wk_sel, _webView, settings); + } + }; + + // UIKit operations have to be on the main thread. + // perform a synchronous invoke on the main thread without deadlocking + if ([NSThread isMainThread]) { + invoke(); + } else { + dispatch_sync(dispatch_get_main_queue(), invoke); + } +} + +- (id)cordovaSettings:(NSDictionary*)settings forKey:(NSString*)key +{ + return [settings objectForKey:[key lowercaseString]]; +} + +- (void)updateUIWebView:(UIWebView*)theWebView settings:(NSDictionary*)settings +{ + NSString* enableViewportScale = [self cordovaSettings:settings forKey:@"EnableViewportScale"]; + NSNumber* allowInlineMediaPlayback = [self cordovaSettings:settings forKey:@"AllowInlineMediaPlayback"]; + BOOL mediaPlaybackRequiresUserAction = YES; // default value + + if ([self cordovaSettings:settings forKey:@"MediaPlaybackRequiresUserAction"]) { + mediaPlaybackRequiresUserAction = [(NSNumber*)[self cordovaSettings:settings forKey:@"MediaPlaybackRequiresUserAction"] boolValue]; + } + + theWebView.scalesPageToFit = [enableViewportScale boolValue]; + + /* + * This is for iOS 4.x, where you can allow inline <video> and <audio>, and also autoplay them + */ + if ([allowInlineMediaPlayback boolValue] && [theWebView respondsToSelector:@selector(allowsInlineMediaPlayback)]) { + theWebView.allowsInlineMediaPlayback = YES; + } + if ((mediaPlaybackRequiresUserAction == NO) && [theWebView respondsToSelector:@selector(mediaPlaybackRequiresUserAction)]) { + theWebView.mediaPlaybackRequiresUserAction = NO; + } + + // By default, overscroll bouncing is allowed. + // UIWebViewBounce has been renamed to DisallowOverscroll, but both are checked. + BOOL bounceAllowed = YES; + NSNumber* disallowOverscroll = [self cordovaSettings:settings forKey:@"DisallowOverscroll"]; + if (disallowOverscroll == nil) { + NSNumber* bouncePreference = [self cordovaSettings:settings forKey:@"UIWebViewBounce"]; + bounceAllowed = (bouncePreference == nil || [bouncePreference boolValue]); + } else { + bounceAllowed = ![disallowOverscroll boolValue]; + } + + // prevent webView from bouncing + // based on the DisallowOverscroll/UIWebViewBounce key in config.xml + if (!bounceAllowed) { + if ([theWebView respondsToSelector:@selector(scrollView)]) { + ((UIScrollView*)[theWebView scrollView]).bounces = NO; + } else { + for (id subview in theWebView.subviews) { + if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { + ((UIScrollView*)subview).bounces = NO; + } + } + } + } + + NSString* decelerationSetting = [self cordovaSettings:settings forKey:@"UIWebViewDecelerationSpeed"]; + if (![@"fast" isEqualToString : decelerationSetting]) { + [theWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal]; + } + + /* + * iOS 6.0 UIWebView properties + */ + if (IsAtLeastiOSVersion(@"6.0")) { + BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES + if ([self cordovaSettings:settings forKey:@"KeyboardDisplayRequiresUserAction"] != nil) { + if ([self cordovaSettings:settings forKey:@"KeyboardDisplayRequiresUserAction"]) { + keyboardDisplayRequiresUserAction = [(NSNumber*)[self cordovaSettings:settings forKey:@"KeyboardDisplayRequiresUserAction"] boolValue]; + } + } + + // property check for compiling under iOS < 6 + if ([theWebView respondsToSelector:@selector(setKeyboardDisplayRequiresUserAction:)]) { + [theWebView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:@"keyboardDisplayRequiresUserAction"]; + } + + BOOL suppressesIncrementalRendering = NO; // SuppressesIncrementalRendering - defaults to NO + if ([self cordovaSettings:settings forKey:@"SuppressesIncrementalRendering"] != nil) { + if ([self cordovaSettings:settings forKey:@"SuppressesIncrementalRendering"]) { + suppressesIncrementalRendering = [(NSNumber*)[self cordovaSettings:settings forKey:@"SuppressesIncrementalRendering"] boolValue]; + } + } + + // property check for compiling under iOS < 6 + if ([theWebView respondsToSelector:@selector(setSuppressesIncrementalRendering:)]) { + [theWebView setValue:[NSNumber numberWithBool:suppressesIncrementalRendering] forKey:@"suppressesIncrementalRendering"]; + } + } + + /* + * iOS 7.0 UIWebView properties + */ + if (IsAtLeastiOSVersion(@"7.0")) { + SEL ios7sel = nil; + id prefObj = nil; + + CGFloat gapBetweenPages = 0.0; // default + prefObj = [self cordovaSettings:settings forKey:@"GapBetweenPages"]; + if (prefObj != nil) { + gapBetweenPages = [prefObj floatValue]; + } + + // property check for compiling under iOS < 7 + ios7sel = NSSelectorFromString(@"setGapBetweenPages:"); + if ([theWebView respondsToSelector:ios7sel]) { + [theWebView setValue:[NSNumber numberWithFloat:gapBetweenPages] forKey:@"gapBetweenPages"]; + } + + CGFloat pageLength = 0.0; // default + prefObj = [self cordovaSettings:settings forKey:@"PageLength"]; + if (prefObj != nil) { + pageLength = [[self cordovaSettings:settings forKey:@"PageLength"] floatValue]; + } + + // property check for compiling under iOS < 7 + ios7sel = NSSelectorFromString(@"setPageLength:"); + if ([theWebView respondsToSelector:ios7sel]) { + [theWebView setValue:[NSNumber numberWithBool:pageLength] forKey:@"pageLength"]; + } + + NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage + prefObj = [self cordovaSettings:settings forKey:@"PaginationBreakingMode"]; + if (prefObj != nil) { + NSArray* validValues = @[@"page", @"column"]; + NSString* prefValue = [validValues objectAtIndex:0]; + + if ([prefObj isKindOfClass:[NSString class]]) { + prefValue = prefObj; + } + + paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]]; + if (paginationBreakingMode == NSNotFound) { + paginationBreakingMode = 0; + } + } + + // property check for compiling under iOS < 7 + ios7sel = NSSelectorFromString(@"setPaginationBreakingMode:"); + if ([theWebView respondsToSelector:ios7sel]) { + [theWebView setValue:[NSNumber numberWithInteger:paginationBreakingMode] forKey:@"paginationBreakingMode"]; + } + + NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated + prefObj = [self cordovaSettings:settings forKey:@"PaginationMode"]; + if (prefObj != nil) { + NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"]; + NSString* prefValue = [validValues objectAtIndex:0]; + + if ([prefObj isKindOfClass:[NSString class]]) { + prefValue = prefObj; + } + + paginationMode = [validValues indexOfObject:[prefValue lowercaseString]]; + if (paginationMode == NSNotFound) { + paginationMode = 0; + } + } + + // property check for compiling under iOS < 7 + ios7sel = NSSelectorFromString(@"setPaginationMode:"); + if ([theWebView respondsToSelector:ios7sel]) { + [theWebView setValue:[NSNumber numberWithInteger:paginationMode] forKey:@"paginationMode"]; + } + } +} + +#ifdef __IPHONE_8_0 + + - (void)updateWKWebView:(WKWebView*)theWebView settings:(NSDictionary*)settings + { + id prefObj = nil; + + CGFloat minimumFontSize = 0.0; // default + + prefObj = [self cordovaSettings:settings forKey:@"MinimumFontSize"]; + if (prefObj != nil) { + minimumFontSize = [[self cordovaSettings:settings forKey:@"MinimumFontSize"] floatValue]; + } + theWebView.configuration.preferences.minimumFontSize = minimumFontSize; + + /* + BOOL javaScriptEnabled = YES; // default value + if ([self cordovaSettings:settings forKey:@"JavaScriptEnabled"]) { + javaScriptEnabled = [(NSNumber*)[self cordovaSettings:settings forKey:@"JavaScriptEnabled"] boolValue]; + } + theWebView.configuration.preferences.javaScriptEnabled = javaScriptEnabled; + + BOOL javaScriptCanOpenWindowsAutomatically = NO; // default value + if ([self cordovaSettings:settings forKey:@"JavaScriptEnabled"]) { + javaScriptCanOpenWindowsAutomatically = [(NSNumber*)[self cordovaSettings:settings forKey:@"JavaScriptEnabled"] boolValue]; + } + theWebView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = javaScriptCanOpenWindowsAutomatically; + */ + } +#endif /* ifdef __IPHONE_8_0 */ + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/CordovaLib.xcodeproj/project.pbxproj ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj index a084d16..a2d5cc4 100644 --- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj +++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj @@ -13,8 +13,10 @@ 1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F92F49F1314023E0046367C /* CDVPluginResult.m */; }; 301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 301F2F2914F3C9CA003FE9FC /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; }; 302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 302965BB13A94E9D007046C5 /* CDVDebug.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 302D72FC19554BFC0028C99F /* CDVWebViewOperationsDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D72FA19554BFC0028C99F /* CDVWebViewOperationsDelegate.m */; }; 3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; }; + 303820731955603600C91592 /* CDVWebViewOperationsDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 302D72F919554BFC0028C99F /* CDVWebViewOperationsDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */; }; @@ -32,6 +34,10 @@ 30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7E14B5A81705050A0032169E /* CDVTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E14B5A61705050A0032169E /* CDVTimer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7E14B5A91705050A0032169E /* CDVTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E14B5A71705050A0032169E /* CDVTimer.m */; }; + 7E785B9A196F508900ABBDC8 /* CDVWebViewUIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E785B9B196F508900ABBDC8 /* CDVWebViewUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */; }; + 7EE9ECF819525D24004CA6B9 /* CDVWebViewPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7EE9ECF919525D24004CA6B9 /* CDVWebViewPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */; }; 8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* CDVViewController.m */; }; 8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -61,6 +67,8 @@ 1F92F49F1314023E0046367C /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPluginResult.m; path = Classes/CDVPluginResult.m; sourceTree = "<group>"; }; 301F2F2914F3C9CA003FE9FC /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDV.h; path = Classes/CDV.h; sourceTree = "<group>"; }; 302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree = "<group>"; }; + 302D72F919554BFC0028C99F /* CDVWebViewOperationsDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewOperationsDelegate.h; path = Classes/CDVWebViewOperationsDelegate.h; sourceTree = "<group>"; }; + 302D72FA19554BFC0028C99F /* CDVWebViewOperationsDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewOperationsDelegate.m; path = Classes/CDVWebViewOperationsDelegate.m; sourceTree = "<group>"; }; 30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; }; 3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h; sourceTree = "<group>"; }; 3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m; sourceTree = "<group>"; }; @@ -93,6 +101,10 @@ 68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; 7E14B5A61705050A0032169E /* CDVTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVTimer.h; path = Classes/CDVTimer.h; sourceTree = "<group>"; }; 7E14B5A71705050A0032169E /* CDVTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVTimer.m; path = Classes/CDVTimer.m; sourceTree = "<group>"; }; + 7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVWebViewUIDelegate.h; sourceTree = "<group>"; }; + 7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVWebViewUIDelegate.m; sourceTree = "<group>"; }; + 7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWebViewPreferences.h; path = Classes/CDVWebViewPreferences.h; sourceTree = "<group>"; }; + 7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWebViewPreferences.m; path = Classes/CDVWebViewPreferences.m; sourceTree = "<group>"; }; 8220B5C316D5427E00EC3921 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 8852C43614B65FD800F0E735 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVViewController.h; path = Classes/CDVViewController.h; sourceTree = "<group>"; }; 8852C43714B65FD800F0E735 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVViewController.m; path = Classes/CDVViewController.m; sourceTree = "<group>"; }; @@ -176,6 +188,12 @@ 8852C43714B65FD800F0E735 /* CDVViewController.m */, EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */, EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */, + 7EE9ECF619525D24004CA6B9 /* CDVWebViewPreferences.h */, + 7EE9ECF719525D24004CA6B9 /* CDVWebViewPreferences.m */, + 302D72F919554BFC0028C99F /* CDVWebViewOperationsDelegate.h */, + 302D72FA19554BFC0028C99F /* CDVWebViewOperationsDelegate.m */, + 7E785B98196F508900ABBDC8 /* CDVWebViewUIDelegate.h */, + 7E785B99196F508900ABBDC8 /* CDVWebViewUIDelegate.m */, ); name = Cleaver; sourceTree = "<group>"; @@ -281,8 +299,11 @@ F858FBC6166009A8007DA594 /* CDVConfigParser.h in Headers */, 30F3930B169F839700B22307 /* CDVJSON.h in Headers */, EBFF4DBD16D3FE2E008F452B /* CDVWebViewDelegate.h in Headers */, + 7EE9ECF819525D24004CA6B9 /* CDVWebViewPreferences.h in Headers */, EB96673B16A8970A00D86CDF /* CDVUserAgentUtil.h in Headers */, 7E14B5A81705050A0032169E /* CDVTimer.h in Headers */, + 7E785B9A196F508900ABBDC8 /* CDVWebViewUIDelegate.h in Headers */, + 303820731955603600C91592 /* CDVWebViewOperationsDelegate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -344,6 +365,7 @@ 8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */, 8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */, 1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */, + 7EE9ECF919525D24004CA6B9 /* CDVWebViewPreferences.m in Sources */, 30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */, 30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */, 30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */, @@ -356,10 +378,12 @@ EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */, F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */, 30F3930C169F839700B22307 /* CDVJSON.m in Sources */, + 7E785B9B196F508900ABBDC8 /* CDVWebViewUIDelegate.m in Sources */, EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */, EBFF4DBC16D3FE2E008F452B /* CDVWebViewDelegate.m in Sources */, 7E14B5A91705050A0032169E /* CDVTimer.m in Sources */, 1B701029177A61CF00AE11F4 /* CDVShared.m in Sources */, + 302D72FC19554BFC0028C99F /* CDVWebViewOperationsDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -370,6 +394,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; DSTROOT = "/tmp/$(PROJECT_NAME).dst"; @@ -393,6 +418,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; DSTROOT = "/tmp/$(PROJECT_NAME).dst"; GCC_MODEL_TUNING = G5; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLib/cordova.js ---------------------------------------------------------------------- diff --git a/CordovaLib/cordova.js b/CordovaLib/cordova.js index 4f64444..2470044 100644 --- a/CordovaLib/cordova.js +++ b/CordovaLib/cordova.js @@ -1,5 +1,5 @@ // Platform: ios -// 3.6.0-dev-7e845f3 +// 3.6.0-dev-f27458f /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -19,7 +19,7 @@ under the License. */ ;(function() { -var CORDOVA_JS_BUILD_LABEL = '3.6.0-dev-7e845f3'; +var CORDOVA_JS_BUILD_LABEL = '3.6.0-dev-f27458f'; // file: src/scripts/require.js /*jshint -W079 */ @@ -826,7 +826,8 @@ var cordova = require('cordova'), XHR_OPTIONAL_PAYLOAD: 3, IFRAME_HASH_NO_PAYLOAD: 4, // Bundling the payload turns out to be slower. Probably since it has to be URI encoded / decoded. - IFRAME_HASH_WITH_PAYLOAD: 5 + IFRAME_HASH_WITH_PAYLOAD: 5, + WK_WEBVIEW_BINDING: 6 }, bridgeMode, execIframe, @@ -921,9 +922,17 @@ function iOSExec() { // Use IFRAME_NAV elsewhere since it's faster and XHR bridge // seems to have bugs in newer OS's (CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134) if (bridgeMode === undefined) { - bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD; + if (navigator.userAgent) { + bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD; + } else { + bridgeMode = jsToNativeModes.IFRAME_NAV; + } } - + + if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.cordova && window.webkit.messageHandlers.cordova.postMessage) { + bridgeMode = jsToNativeModes.WK_WEBVIEW_BINDING; + } + var successCallback, failCallback, service, action, actionArgs, splitCommand; var callbackId = null; if (typeof arguments[0] !== "string") { @@ -973,20 +982,24 @@ function iOSExec() { // effectively clone the command arguments in case they are mutated before // the command is executed. commandQueue.push(JSON.stringify(command)); - - // If we're in the context of a stringByEvaluatingJavaScriptFromString call, - // then the queue will be flushed when it returns; no need for a poke. - // Also, if there is already a command in the queue, then we've already - // poked the native side, so there is no reason to do so again. - if (!isInContextOfEvalJs && commandQueue.length == 1) { - switch (bridgeMode) { - case jsToNativeModes.XHR_NO_PAYLOAD: - case jsToNativeModes.XHR_WITH_PAYLOAD: - case jsToNativeModes.XHR_OPTIONAL_PAYLOAD: - pokeNativeViaXhr(); - break; - default: // iframe-based. - pokeNativeViaIframe(); + + if (bridgeMode === jsToNativeModes.WK_WEBVIEW_BINDING) { + window.webkit.messageHandlers.cordova.postMessage(command); + } else { + // If we're in the context of a stringByEvaluatingJavaScriptFromString call, + // then the queue will be flushed when it returns; no need for a poke. + // Also, if there is already a command in the queue, then we've already + // poked the native side, so there is no reason to do so again. + if (!isInContextOfEvalJs && commandQueue.length == 1) { + switch (bridgeMode) { + case jsToNativeModes.XHR_NO_PAYLOAD: + case jsToNativeModes.XHR_WITH_PAYLOAD: + case jsToNativeModes.XHR_OPTIONAL_PAYLOAD: + pokeNativeViaXhr(); + break; + default: // iframe-based. + pokeNativeViaIframe(); + } } } } http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/CordovaLibTests/CordovaLibApp/config.xml ---------------------------------------------------------------------- diff --git a/CordovaLibTests/CordovaLibApp/config.xml b/CordovaLibTests/CordovaLibApp/config.xml index 1fcc8d7..da6c067 100644 --- a/CordovaLibTests/CordovaLibApp/config.xml +++ b/CordovaLibTests/CordovaLibApp/config.xml @@ -36,6 +36,7 @@ <content src="index.html" /> <!-- Preferences for iOS --> + <preference name="UseWKWebView" value="false" /> <preference name="AllowInlineMediaPlayback" value="false" /> <preference name="BackupWebStorage" value="cloud" /> <preference name="DisallowOverscroll" value="false" /> http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/bin/templates/project/__CLI__.xcodeproj/project.pbxproj ---------------------------------------------------------------------- diff --git a/bin/templates/project/__CLI__.xcodeproj/project.pbxproj b/bin/templates/project/__CLI__.xcodeproj/project.pbxproj index 4fc1058..6248e1d 100755 --- a/bin/templates/project/__CLI__.xcodeproj/project.pbxproj +++ b/bin/templates/project/__CLI__.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ 7E7966DB1810823500FA85AD /* icon...@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon...@2x.png"; sourceTree = "<group>"; }; 7E7966DC1810823500FA85AD /* icon-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-small.png"; sourceTree = "<group>"; }; 7E7966DD1810823500FA85AD /* icon-sm...@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-sm...@2x.png"; sourceTree = "<group>"; }; + 7ED68E4519526A5A00B0A8AF /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 8D1107310486CEB800E47090 /* __PROJECT_NAME__-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "__PROJECT_NAME__-Info.plist"; path = "../__PROJECT_NAME__-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; D4A0D8751607E02300AEF8BB /* Default-568h@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x~iphone.png"; sourceTree = "<group>"; }; EB87FDF21871DA7A0020F90C /* merges */ = {isa = PBXFileReference; lastKnownFileType = folder; name = merges; path = ../../merges; sourceTree = "<group>"; }; @@ -204,6 +205,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 7ED68E4519526A5A00B0A8AF /* WebKit.framework */, 5AEE5B34173C68D80009041E /* CoreLocation.framework */, 5B1594DC16A7569C00FEF299 /* AssetsLibrary.framework */, 288765FC0DF74451002DB57D /* CoreGraphics.framework */, @@ -470,6 +472,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; @@ -503,6 +506,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -533,6 +537,7 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -579,6 +584,7 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/bin/templates/project/__NON-CLI__.xcodeproj/project.pbxproj ---------------------------------------------------------------------- diff --git a/bin/templates/project/__NON-CLI__.xcodeproj/project.pbxproj b/bin/templates/project/__NON-CLI__.xcodeproj/project.pbxproj index a59b3bd..c2d5ca4 100755 --- a/bin/templates/project/__NON-CLI__.xcodeproj/project.pbxproj +++ b/bin/templates/project/__NON-CLI__.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ 7E7966DB1810823500FA85AD /* icon...@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon...@2x.png"; sourceTree = "<group>"; }; 7E7966DC1810823500FA85AD /* icon-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-small.png"; sourceTree = "<group>"; }; 7E7966DD1810823500FA85AD /* icon-sm...@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-sm...@2x.png"; sourceTree = "<group>"; }; + 7EFADAF51952687D00F28308 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 8D1107310486CEB800E47090 /* __PROJECT_NAME__-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "__PROJECT_NAME__-Info.plist"; path = "../__PROJECT_NAME__-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; D4A0D8751607E02300AEF8BB /* Default-568h@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x~iphone.png"; sourceTree = "<group>"; }; F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = "__PROJECT_NAME__/config.xml"; sourceTree = "<group>"; }; @@ -199,6 +200,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 7EFADAF51952687D00F28308 /* WebKit.framework */, 5AEE5B34173C68D80009041E /* CoreLocation.framework */, 5B1594DC16A7569C00FEF299 /* AssetsLibrary.framework */, 288765FC0DF74451002DB57D /* CoreGraphics.framework */, @@ -391,7 +393,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cordova/lib/copy-www-build-step.sh"; - showEnvVarsInLog = 0; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -456,6 +458,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; @@ -489,6 +492,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -519,6 +523,7 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -565,6 +570,7 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/bin/templates/project/__PROJECT_NAME__/Classes/AppDelegate.m ---------------------------------------------------------------------- diff --git a/bin/templates/project/__PROJECT_NAME__/Classes/AppDelegate.m b/bin/templates/project/__PROJECT_NAME__/Classes/AppDelegate.m index cc82260..ea2fb7c 100644 --- a/bin/templates/project/__PROJECT_NAME__/Classes/AppDelegate.m +++ b/bin/templates/project/__PROJECT_NAME__/Classes/AppDelegate.m @@ -101,7 +101,7 @@ // calls into javascript global function 'handleOpenURL' NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", url]; - [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString]; + [self.viewController.webViewOperationsDelegate evaluateJavaScript:jsString completionHandler:nil]; // all plugins will get the notification, and their handlers will be called [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; @@ -117,20 +117,20 @@ [[NSNotificationCenter defaultCenter] postNotificationName:CDVLocalNotification object:notification]; } -- (void) application:(UIApplication *)application - didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +- (void) application:(UIApplication*)application + didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { // re-post ( broadcast ) NSString* token = [[[[deviceToken description] - stringByReplacingOccurrencesOfString: @"<" withString: @""] - stringByReplacingOccurrencesOfString: @">" withString: @""] - stringByReplacingOccurrencesOfString: @" " withString: @""]; + stringByReplacingOccurrencesOfString:@"<" withString:@""] + stringByReplacingOccurrencesOfString:@">" withString:@""] + stringByReplacingOccurrencesOfString:@" " withString:@""]; [[NSNotificationCenter defaultCenter] postNotificationName:CDVRemoteNotification object:token]; } -- (void) application:(UIApplication *)application - didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +- (void) application:(UIApplication*)application + didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { // re-post ( broadcast ) [[NSNotificationCenter defaultCenter] postNotificationName:CDVRemoteNotificationError object:error]; http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/aa5d0e93/bin/templates/project/__PROJECT_NAME__/config.xml ---------------------------------------------------------------------- diff --git a/bin/templates/project/__PROJECT_NAME__/config.xml b/bin/templates/project/__PROJECT_NAME__/config.xml index 1fcc8d7..da6c067 100644 --- a/bin/templates/project/__PROJECT_NAME__/config.xml +++ b/bin/templates/project/__PROJECT_NAME__/config.xml @@ -36,6 +36,7 @@ <content src="index.html" /> <!-- Preferences for iOS --> + <preference name="UseWKWebView" value="false" /> <preference name="AllowInlineMediaPlayback" value="false" /> <preference name="BackupWebStorage" value="cloud" /> <preference name="DisallowOverscroll" value="false" /> --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org For additional commands, e-mail: commits-h...@cordova.apache.org