You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by dp...@apache.org on 2021/10/01 07:38:16 UTC
[cordova-ios] branch master updated: feat: add
CDVWebViewEngineConfigurationDelegate (#1050)
This is an automated email from the ASF dual-hosted git repository.
dpogue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-ios.git
The following commit(s) were added to refs/heads/master by this push:
new 4c81363 feat: add CDVWebViewEngineConfigurationDelegate (#1050)
4c81363 is described below
commit 4c8136345ae9622646ee7e4eb60ba2b37ad44fbe
Author: Michael Tamburro <61...@users.noreply.github.com>
AuthorDate: Fri Oct 1 03:38:10 2021 -0400
feat: add CDVWebViewEngineConfigurationDelegate (#1050)
* feat: add CDVWebViewEngineConfigurationDelegate to fully expose WKWebView configuration (#900)
* fix: update the existing tests of the default behavior
* chore: bring back initWithFrame, as existing CDVWebViewEngineProtocol conforming plugins use it
* chore: clean up newCordovaViewWithFrame in order to extract initialization with configuration
* chore: find existing methods that can return nil, and mark them as such for clarity
---
.../Plugins/CDVWebViewEngine/CDVWebViewEngine.m | 23 ++++++--
CordovaLib/Classes/Public/CDVViewController.h | 35 +++++++++--
CordovaLib/Classes/Public/CDVViewController.m | 69 +++++++++++++++-------
.../Classes/Public/CDVWebViewEngineProtocol.h | 16 ++++-
tests/CordovaLibTests/CDVWebViewEngineTest.m | 2 +-
5 files changed, 108 insertions(+), 37 deletions(-)
diff --git a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
index a07bf29..5be8a41 100644
--- a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
+++ b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
@@ -45,6 +45,7 @@
@property (nonatomic, strong) CDVURLSchemeHandler * schemeHandler;
@property (nonatomic, readwrite) NSString *CDV_ASSETS_URL;
@property (nonatomic, readwrite) Boolean cdvIsFileScheme;
+@property (nullable, nonatomic, strong, readwrite) WKWebViewConfiguration *configuration;
@end
@@ -55,24 +56,36 @@
@synthesize engineWebView = _engineWebView;
-- (instancetype)initWithFrame:(CGRect)frame
+- (nullable instancetype)initWithFrame:(CGRect)frame configuration:(nullable WKWebViewConfiguration *)configuration
{
self = [super init];
if (self) {
if (NSClassFromString(@"WKWebView") == nil) {
return nil;
}
-
- self.engineWebView = [[WKWebView alloc] initWithFrame:frame];
+
+ self.configuration = configuration;
+ self.engineWebView = configuration ? [[WKWebView alloc] initWithFrame:frame configuration:configuration] : [[WKWebView alloc] initWithFrame:frame];
}
return self;
}
+- (nullable instancetype)initWithFrame:(CGRect)frame
+{
+ return [self initWithFrame:frame configuration:nil];
+}
+
- (WKWebViewConfiguration*) createConfigurationFromSettings:(NSDictionary*)settings
{
- WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
- configuration.processPool = [[CDVWebViewProcessPoolFactory sharedFactory] sharedProcessPool];
+ WKWebViewConfiguration* configuration;
+ if (_configuration) {
+ configuration = _configuration;
+ } else {
+ configuration = [[WKWebViewConfiguration alloc] init];
+ configuration.processPool = [[CDVWebViewProcessPoolFactory sharedFactory] sharedProcessPool];
+ }
+
if (settings == nil) {
return configuration;
}
diff --git a/CordovaLib/Classes/Public/CDVViewController.h b/CordovaLib/Classes/Public/CDVViewController.h
index 81c7128..8e595e3 100644
--- a/CordovaLib/Classes/Public/CDVViewController.h
+++ b/CordovaLib/Classes/Public/CDVViewController.h
@@ -26,6 +26,25 @@
#import "CDVScreenOrientationDelegate.h"
#import "CDVPlugin.h"
#import "CDVWebViewEngineProtocol.h"
+@import WebKit;
+
+@protocol CDVWebViewEngineConfigurationDelegate <NSObject>
+
+@optional
+/// Provides a fully configured WKWebViewConfiguration which will be overriden with
+/// any related settings you add to config.xml (e.g., `PreferredContentMode`).
+/// Useful for more complex configuration, including websiteDataStore.
+///
+/// Example usage:
+///
+/// extension CDVViewController: CDVWebViewEngineConfigurationDelegate {
+/// public func configuration() -> WKWebViewConfiguration {
+/// // return your config here
+/// }
+/// }
+- (nonnull WKWebViewConfiguration*)configuration;
+
+@end
@interface CDVViewController : UIViewController <CDVScreenOrientationDelegate>{
@protected
@@ -36,10 +55,12 @@
CDVCommandQueue* _commandQueue;
}
+NS_ASSUME_NONNULL_BEGIN
+
@property (nonatomic, readonly, weak) IBOutlet UIView* webView;
@property (nonatomic, readonly, strong) UIView* launchView;
-@property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects;
+@property (nullable, nonatomic, readonly, strong) NSMutableDictionary* pluginObjects;
@property (nonatomic, readonly, strong) NSDictionary* pluginsMap;
@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
@property (nonatomic, readonly, strong) NSXMLParser* configParser;
@@ -53,21 +74,21 @@
@property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate;
/**
- Takes/Gives an array of UIInterfaceOrientation (int) objects
- ex. UIInterfaceOrientationPortrait
+ Takes/Gives an array of UIInterfaceOrientation (int) objects
+ ex. UIInterfaceOrientationPortrait
*/
@property (nonatomic, readwrite, strong) NSArray* supportedOrientations;
- (UIView*)newCordovaViewWithFrame:(CGRect)bounds;
-- (NSString*)appURLScheme;
-- (NSURL*)errorURL;
+- (nullable NSString*)appURLScheme;
+- (nullable NSURL*)errorURL;
- (UIColor*)colorFromColorString:(NSString*)colorString CDV_DEPRECATED(7.0.0, "Use BackgroundColor in xcassets");
- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations;
- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation;
-- (id)getCommandInstance:(NSString*)pluginName;
+- (nullable id)getCommandInstance:(NSString*)pluginName;
- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className;
- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName;
@@ -75,4 +96,6 @@
- (void)showLaunchScreen:(BOOL)visible;
+NS_ASSUME_NONNULL_END
+
@end
diff --git a/CordovaLib/Classes/Public/CDVViewController.m b/CordovaLib/Classes/Public/CDVViewController.m
index 50dcf5e..1ebfd1e 100644
--- a/CordovaLib/Classes/Public/CDVViewController.m
+++ b/CordovaLib/Classes/Public/CDVViewController.m
@@ -27,7 +27,7 @@
#import "CDVCommandDelegateImpl.h"
#import <Foundation/NSCharacterSet.h>
-@interface CDVViewController () { }
+@interface CDVViewController () <CDVWebViewEngineConfigurationDelegate> { }
@property (nonatomic, readwrite, strong) NSXMLParser* configParser;
@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
@@ -238,7 +238,7 @@
return appURL;
}
-- (NSURL*)errorURL
+- (nullable NSURL*)errorURL
{
NSURL* errorUrl = nil;
@@ -485,36 +485,61 @@
return [self.supportedOrientations containsObject:@(orientation)];
}
-- (UIView*)newCordovaViewWithFrame:(CGRect)bounds
+/// Retrieves the view from a newwly initialized webViewEngine
+/// @param bounds The bounds with which the webViewEngine will be initialized
+- (nonnull UIView*)newCordovaViewWithFrame:(CGRect)bounds
{
- NSString* defaultWebViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaDefaultWebViewEngine"];
- NSString* webViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaWebViewEngine"];
+ NSString* defaultWebViewEngineClassName = [self.settings cordovaSettingForKey:@"CordovaDefaultWebViewEngine"];
+ NSString* webViewEngineClassName = [self.settings cordovaSettingForKey:@"CordovaWebViewEngine"];
- if (!defaultWebViewEngineClass) {
- defaultWebViewEngineClass = @"CDVWebViewEngine";
+ if (!defaultWebViewEngineClassName) {
+ defaultWebViewEngineClassName = @"CDVWebViewEngine";
}
- if (!webViewEngineClass) {
- webViewEngineClass = defaultWebViewEngineClass;
+ if (!webViewEngineClassName) {
+ webViewEngineClassName = defaultWebViewEngineClassName;
}
- // Find webViewEngine
- if (NSClassFromString(webViewEngineClass)) {
- self.webViewEngine = [[NSClassFromString(webViewEngineClass) alloc] initWithFrame:bounds];
- // if a webView engine returns nil (not supported by the current iOS version) or doesn't conform to the protocol, or can't load the request, we use WKWebView
- if (!self.webViewEngine || ![self.webViewEngine conformsToProtocol:@protocol(CDVWebViewEngineProtocol)] || ![self.webViewEngine canLoadRequest:[NSURLRequest requestWithURL:self.appUrl]]) {
- self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds];
+ // Determine if a provided custom web view engine is sufficient
+ id <CDVWebViewEngineProtocol> engine;
+ Class customWebViewEngineClass = NSClassFromString(webViewEngineClassName);
+ if (customWebViewEngineClass) {
+ id customWebViewEngine = [self initWebViewEngine:customWebViewEngineClass bounds:bounds];
+ BOOL customConformsToProtocol = [customWebViewEngine conformsToProtocol:@protocol(CDVWebViewEngineProtocol)];
+ BOOL customCanLoad = [customWebViewEngine canLoadRequest:[NSURLRequest requestWithURL:self.appUrl]];
+ if (customConformsToProtocol && customCanLoad) {
+ engine = customWebViewEngine;
}
- } else {
- self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds];
}
-
- if ([self.webViewEngine isKindOfClass:[CDVPlugin class]]) {
- [self registerPlugin:(CDVPlugin*)self.webViewEngine withClassName:webViewEngineClass];
+
+ // Otherwise use the default web view engine
+ if (!engine) {
+ Class defaultWebViewEngineClass = NSClassFromString(defaultWebViewEngineClassName);
+ id defaultWebViewEngine = [self initWebViewEngine:defaultWebViewEngineClass bounds:bounds];
+ NSAssert([defaultWebViewEngine conformsToProtocol:@protocol(CDVWebViewEngineProtocol)],
+ @"we expected the default web view engine to conform to the CDVWebViewEngineProtocol");
+ engine = defaultWebViewEngine;
+ }
+
+ if ([engine isKindOfClass:[CDVPlugin class]]) {
+ [self registerPlugin:(CDVPlugin*)engine withClassName:webViewEngineClassName];
}
+ self.webViewEngine = engine;
return self.webViewEngine.engineWebView;
}
+/// Initialiizes the webViewEngine, with config, if supported and provided
+/// @param engineClass A class that must conform to the `CDVWebViewEngineProtocol`
+/// @param bounds with which the webview will be initialized
+- (id _Nullable) initWebViewEngine:(nonnull Class)engineClass bounds:(CGRect)bounds {
+ WKWebViewConfiguration *config = [self respondsToSelector:@selector(configuration)] ? [self configuration] : nil;
+ if (config && [engineClass respondsToSelector:@selector(initWithFrame:configuration:)]) {
+ return [[engineClass alloc] initWithFrame:bounds configuration:config];
+ } else {
+ return [[engineClass alloc] initWithFrame:bounds];
+ }
+}
+
- (void)createLaunchView
{
CGRect webViewBounds = self.view.bounds;
@@ -608,7 +633,7 @@
/**
Returns an instance of a CordovaCommand object, based on its name. If one exists already, it is returned.
*/
-- (id)getCommandInstance:(NSString*)pluginName
+- (nullable id)getCommandInstance:(NSString*)pluginName
{
// first, we try to find the pluginName in the pluginsMap
// (acts as a allowList as well) if it does not exist, we return nil
@@ -642,7 +667,7 @@
#pragma mark -
-- (NSString*)appURLScheme
+- (nullable NSString*)appURLScheme
{
NSString* URLScheme = nil;
diff --git a/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h b/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h
index e6126a4..8a562a7 100644
--- a/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h
+++ b/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h
@@ -18,6 +18,7 @@
*/
#import <UIKit/UIKit.h>
+@import WebKit;
#define kCDVWebViewEngineScriptMessageHandlers @"kCDVWebViewEngineScriptMessageHandlers"
#define kCDVWebViewEngineWKNavigationDelegate @"kCDVWebViewEngineWKNavigationDelegate"
@@ -26,16 +27,25 @@
@protocol CDVWebViewEngineProtocol <NSObject>
+NS_ASSUME_NONNULL_BEGIN
+
@property (nonatomic, strong, readonly) UIView* engineWebView;
- (id)loadRequest:(NSURLRequest*)request;
-- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL;
-- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
+- (id)loadHTMLString:(NSString*)string baseURL:(nullable NSURL*)baseURL;
+- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^_Nullable)(id, NSError*))completionHandler;
- (NSURL*)URL;
- (BOOL)canLoadRequest:(NSURLRequest*)request;
+- (nullable instancetype)initWithFrame:(CGRect)frame;
+
+/// Convenience Initializer
+/// @param frame The frame for the new web view.
+/// @param configuration The configuration for the new web view.
+- (nullable instancetype)initWithFrame:(CGRect)frame configuration:(nullable WKWebViewConfiguration *)configuration;
-- (instancetype)initWithFrame:(CGRect)frame;
- (void)updateWithInfo:(NSDictionary*)info;
+NS_ASSUME_NONNULL_END
+
@end
diff --git a/tests/CordovaLibTests/CDVWebViewEngineTest.m b/tests/CordovaLibTests/CDVWebViewEngineTest.m
index 0facc70..962d943 100644
--- a/tests/CordovaLibTests/CDVWebViewEngineTest.m
+++ b/tests/CordovaLibTests/CDVWebViewEngineTest.m
@@ -126,7 +126,7 @@
- (void) testConfigurationFromSettings {
// we need to re-set the plugin from the "setup" to take in the app settings we need
- self.plugin = [[CDVWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+ self.plugin = [[CDVWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:nil];
self.viewController = [[CDVViewController alloc] init];
// generate the app settings
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org