diff --git a/README.md b/README.md
index c3d5ac54..23c2d018 100644
--- a/README.md
+++ b/README.md
@@ -19,11 +19,14 @@
-# Ionic Web View
+# Ionic Web View for Cordova
-The Web View plugin for Cordova that is specialized for Ionic apps.
+A Web View plugin for Cordova, focused on providing the highest performance experience for Ionic apps (but can be used with any Cordova app).
-This is for `cordova-plugin-ionic-webview` @ `2.x`, which uses the latest and greatest features and may not work with all apps. See [Requirements](#requirements) and [Migrating to 2.x](#migrating-to-2x).
+This plugin defaults to using WKWebView on iOS and the latest evergreen webview on Android. Additionally, this plugin makes it easy to use HTML5 style routing
+that web developers expect for building single-page apps.
+
+Note: This repo and its documentation are for `cordova-plugin-ionic-webview` @ `2.x`, which uses the new features that may not work with all apps. See [Requirements](#requirements) and [Migrating to 2.x](#migrating-to-2x).
:book: **Documentation**: [https://beta.ionicframework.com/docs/building/webview][ionic-webview-docs]
@@ -31,12 +34,58 @@ This is for `cordova-plugin-ionic-webview` @ `2.x`, which uses the latest and gr
:sparkling_heart: **Want to contribute?** Please see [CONTRIBUTING.md](https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/CONTRIBUTING.md).
-### Requirements
+## Configuration
+
+This plugin has several configuration options that can be set in `config.xml`. Important: some configuration options should be adjusted for production apps, especially `WKPort`:
+
+### iOS and Android Preferences
+
+Preferences available for both iOS and Android platforms
+
+#### WKPort
+
+```xml
+
+```
+
+The default port the server will listen on. _You should change this to a random port number!_
+
+### iOS Preferences
+
+Preferences only available for iOS platform
+
+#### WKSuspendInBackground
+
+```xml
+
+```
+
+Whether to try to keep the server running when the app is backgrounded. Note: the server will likely be suspended by the OS after a few minutes. In particular, long-lived background tasks are not allowed on iOS outside of select audio and geolocation tasks.
+
+#### WKBind
+
+```xml
+
+```
+
+The hostname the server will bind to. There aren't a lot of other valid options, but some prefer binding to "127.0.0.1"
+
+#### WKInternalConnectionsOnly (New in 2.2.0)
+
+```xml
+
+```
+
+Whether to restrict access to this server to the app itself. Previous versions of this plugin did not restrict access to the app itself. In 2.2.0 and above,
+the plugin now restricts access to only the app itself.
+
+
+## Plugin Requirements
* **iOS**: iOS 10+ and `cordova-ios` 4+
-* **Android**: Android 5.0+ and `cordova-android` 6.4+
+* **Android**: Android 4.4+ and `cordova-android` 6.4+
-### Migrating to 2.x
+## Migrating to 2.x
1. Remove and re-add the Web View plugin:
diff --git a/package.json b/package.json
index 748fd7bb..95d7ebd7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-ionic-webview",
- "version": "2.1.4",
+ "version": "2.2.0",
"description": "The official Ionic's WKWebView Engine Plugin",
"main": "index.js",
"scripts": {
diff --git a/plugin.xml b/plugin.xml
index ea8cdc4f..0302b3f8 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -19,7 +19,7 @@
under the License.
-->
-
+
cordova-plugin-ionic-webview
The official Ionic's WKWebView Engine Plugin
Apache-2.0
diff --git a/src/ios/CDVWKWebViewEngine.m b/src/ios/CDVWKWebViewEngine.m
index c8ce47f1..d81e695d 100644
--- a/src/ios/CDVWKWebViewEngine.m
+++ b/src/ios/CDVWKWebViewEngine.m
@@ -105,6 +105,8 @@ @interface CDVWKWebViewEngine ()
@property (nonatomic, weak) id weakScriptMessageHandler;
@property (nonatomic, strong) GCDWebServer *webServer;
@property (nonatomic, readwrite) CGRect frame;
+@property (nonatomic, strong) NSString *userAgentCreds;
+@property (nonatomic, assign) BOOL internalConnectionsOnly;
@property (nonatomic, readwrite) NSString *CDV_LOCAL_SERVER;
@end
@@ -259,6 +261,8 @@ - (void)pluginInitialize
{
// viewController would be available now. we attempt to set all possible delegates to it, by default
NSDictionary* settings = self.commandDelegate.settings;
+ self.internalConnectionsOnly = [settings cordovaBoolSettingForKey:@"WKInternalConnectionsOnly" defaultValue:YES];
+
[self initWebServer];
self.uiDelegate = [[CDVWKWebViewUIDelegate alloc] initWithTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
@@ -319,6 +323,9 @@ - (void)pluginInitialize
if (IsAtLeastiOSVersion(@"9.0") && [self.viewController isKindOfClass:[CDVViewController class]]) {
wkWebView.customUserAgent = ((CDVViewController*) self.viewController).userAgent;
}
+ if (self.internalConnectionsOnly) {
+ wkWebView.customUserAgent = [NSString stringWithFormat:@"%@/%@",wkWebView.customUserAgent, [self getUserAgentCredentials]];
+ }
if ([self.viewController conformsToProtocol:@protocol(WKUIDelegate)]) {
wkWebView.UIDelegate = (id )self.viewController;
@@ -376,6 +383,21 @@ - (void) keyboardDisplayDoesNotRequireUserAction {
}
}
+- (NSString*)getUserAgentCredentials {
+ if (self.userAgentCreds == nil) {
+ self.userAgentCreds = [self generateRandomString:32];
+ }
+ return self.userAgentCreds;
+}
+
+- (NSString*)generateRandomString:(int)num {
+ NSMutableString* string = [NSMutableString stringWithCapacity:num];
+ for (int i = 0; i < num; i++) {
+ [string appendFormat:@"%C", (unichar)('a' + arc4random_uniform(26))];
+ }
+ return string;
+}
+
- (void)onReset
{
[self addURLObserver];
@@ -799,7 +821,11 @@ -(void)setServerPath:(NSString *) path
}
__block NSString* serverUrl = self.CDV_LOCAL_SERVER;
- [self.webServer addGETHandlerForBasePath:@"/" directoryPath:path indexFilename:((CDVViewController *)self.viewController).startPage cacheAge:0 allowRangeRequests:YES];
+ if (self.internalConnectionsOnly) {
+ [self internalConnectionsGetHandlerForPath:path];
+ } else {
+ [self.webServer addGETHandlerForBasePath:@"/" directoryPath:path indexFilename:((CDVViewController *)self.viewController).startPage cacheAge:0 allowRangeRequests:YES];
+ }
[self.webServer addHandlerForMethod:@"GET" pathRegex:@"_file_/" requestClass:GCDWebServerFileRequest.class asyncProcessBlock:^(__kindof GCDWebServerRequest * _Nonnull request, GCDWebServerCompletionBlock _Nonnull completionBlock) {
NSString *urlToRemove = [serverUrl stringByAppendingString:@"/_file_"];
NSString *absUrl = [[[request URL] absoluteString] stringByReplacingOccurrencesOfString:urlToRemove withString:@""];
@@ -810,7 +836,7 @@ -(void)setServerPath:(NSString *) path
}
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:absUrl]) {
- GCDWebServerResponse* response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];;
+ GCDWebServerResponse* response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];
completionBlock(response);
} else {
GCDWebServerFileResponse *response = [GCDWebServerFileResponse responseWithFile:absUrl byteRange:request.byteRange];
@@ -823,6 +849,45 @@ -(void)setServerPath:(NSString *) path
}
}
+-(void) internalConnectionsGetHandlerForPath:(NSString*)directoryPath {
+ __weak CDVWKWebViewEngine * weakSelf = self;
+ [self.webServer addHandlerWithMatchBlock:^GCDWebServerRequest*(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
+ if (![requestMethod isEqualToString:@"GET"]) {
+ return nil;
+ }
+ return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
+ }
+ processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) {
+ GCDWebServerResponse* response = nil;
+ NSString* userAgent = [request.headers objectForKey:@"User-Agent"];
+ if ([userAgent containsString:[weakSelf getUserAgentCredentials]]) {
+ NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:1]];
+ NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType];
+ if (fileType) {
+ if ([fileType isEqualToString:NSFileTypeDirectory]) {
+ NSString* indexPath = [filePath stringByAppendingPathComponent:((CDVViewController *)weakSelf.viewController).startPage];
+ NSString* indexType = [[[NSFileManager defaultManager] attributesOfItemAtPath:indexPath error:NULL] fileType];
+ if ([indexType isEqualToString:NSFileTypeRegular]) {
+ response = [GCDWebServerFileResponse responseWithFile:indexPath];
+ }
+ } else if ([fileType isEqualToString:NSFileTypeRegular]) {
+ response = [GCDWebServerFileResponse responseWithFile:filePath byteRange:request.byteRange];
+ [response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];
+ }
+ }
+ if (response) {
+ response.cacheControlMaxAge = 0;
+ } else {
+ response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];
+ }
+ [response setValue:@"*" forAdditionalHeader:@"Access-Control-Allow-Origin"];
+ } else {
+ response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_Unauthorized];
+ }
+ return response;
+ }];
+}
+
-(void)persistServerBasePath:(CDVInvokedUrlCommand*)command
{
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];