From a6cf26ab4dcc1b8dc58b05c5b06b8cf2ad77850e Mon Sep 17 00:00:00 2001 From: Niklas Merz Date: Mon, 9 Dec 2019 14:46:16 +0100 Subject: [PATCH 1/4] Prepare runtime hostname switching --- .../cordova/webview/IonicWebView.java | 9 +++++++++ .../cordova/webview/IonicWebViewEngine.java | 14 +++++++++++++- .../cordova/webview/WebViewLocalServer.java | 11 ++++++++++- src/www/util.js | 3 +++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebView.java b/src/android/com/ionicframework/cordova/webview/IonicWebView.java index ff771371..8989a516 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebView.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebView.java @@ -33,6 +33,15 @@ public void run() { editor.putString(CDV_SERVER_PATH, path); editor.apply(); return true; + } else if (action.equals("setOrigin")) { + final String hostname = args.getString(0); + final String scheme = args.getString(1); + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + ((IonicWebViewEngine) webView.getEngine()).setOrigin(hostname, scheme); + } + }); + return true; } return false; } diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java index 81d04978..c2321549 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java @@ -25,6 +25,7 @@ import org.apache.cordova.engine.SystemWebViewClient; import org.apache.cordova.engine.SystemWebViewEngine; import org.apache.cordova.engine.SystemWebView; +import java.util.ArrayList; public class IonicWebViewEngine extends SystemWebViewEngine { public static final String TAG = "IonicWebViewEngine"; @@ -64,7 +65,7 @@ public void init(CordovaWebView parentWebView, CordovaInterface cordova, final C scheme = preferences.getString("Scheme", "http"); CDV_LOCAL_SERVER = scheme + "://" + hostname; - localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme); + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, new ArrayList()); localServer.hostAssets("www"); webView.setWebViewClient(new ServerClient(this, parser)); @@ -163,4 +164,15 @@ public void setServerBasePath(String path) { public String getServerBasePath() { return this.localServer.getBasePath(); } + + public void setOrigin(String hostname, String scheme) { + + ConfigXmlParser parser = new ConfigXmlParser(); + parser.parse(cordova.getActivity()); + this.scheme = scheme; + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, new ArrayList()); + localServer.hostAssets("www"); + CDV_LOCAL_SERVER = scheme + "://" + hostname; + webView.loadUrl(CDV_LOCAL_SERVER); + } } diff --git a/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java b/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java index cf134932..8b1d28a2 100644 --- a/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java +++ b/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.ArrayList; /** * Helper class meant to be used with the android.webkit.WebView class to enable hosting assets, @@ -64,6 +65,7 @@ public class WebViewLocalServer { // Whether to route all requests to paths without extensions back to `index.html` private final boolean html5mode; private ConfigXmlParser parser; + private ArrayList ignorePaths; public String getAuthority() { return authority; } @@ -163,13 +165,14 @@ public Uri getHttpsPrefix() { } } - WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser, String customScheme) { + WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser, String customScheme, ArrayList ignorePaths) { uriMatcher = new UriMatcher(null); this.html5mode = html5mode; this.parser = parser; this.protocolHandler = new AndroidProtocolHandler(context.getApplicationContext()); this.authority = authority; this.customScheme = customScheme; + this.ignorePaths = ignorePaths; } private static Uri parseAndVerifyUrl(String url) { @@ -223,6 +226,12 @@ public WebResourceResponse shouldInterceptRequest(Uri uri, WebResourceRequest re return null; } + for(String path : ignorePaths) { + if (uri.getPath().contains(path)) { + return null; + } + } + if (isLocalFile(uri) || uri.getAuthority().equals(this.authority)) { Log.d("SERVER", "Handling local request: " + uri.toString()); return handleLocalRequest(uri, handler, request); diff --git a/src/www/util.js b/src/www/util.js index 4acf8851..436ecb4d 100644 --- a/src/www/util.js +++ b/src/www/util.js @@ -24,6 +24,9 @@ var WebView = { }, persistServerBasePath: function() { exec(null, null, 'IonicWebView', 'persistServerBasePath', []); + }, + setOrigin: function(hostname, scheme) { + exec(null, null, 'IonicWebView', 'setOrigin', [hostname, scheme]); } } From 2e5f56d8072022abe3b1d97d006691b604b05efb Mon Sep 17 00:00:00 2001 From: Niklas Merz Date: Mon, 9 Dec 2019 15:42:11 +0100 Subject: [PATCH 2/4] Allow to whitelist paths for same origin work around --- .../cordova/webview/IonicWebView.java | 3 ++- .../cordova/webview/IonicWebViewEngine.java | 7 ++++--- .../cordova/webview/WebViewLocalServer.java | 20 ++++++++++++++----- src/www/util.js | 4 ++-- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebView.java b/src/android/com/ionicframework/cordova/webview/IonicWebView.java index 8989a516..c1c27f7b 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebView.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebView.java @@ -36,9 +36,10 @@ public void run() { } else if (action.equals("setOrigin")) { final String hostname = args.getString(0); final String scheme = args.getString(1); + final JSONArray paths = args.getJSONArray(2); cordova.getActivity().runOnUiThread(new Runnable() { public void run() { - ((IonicWebViewEngine) webView.getEngine()).setOrigin(hostname, scheme); + ((IonicWebViewEngine) webView.getEngine()).setOrigin(hostname, scheme, paths); } }); return true; diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java index c2321549..dfdc7830 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java @@ -26,6 +26,7 @@ import org.apache.cordova.engine.SystemWebViewEngine; import org.apache.cordova.engine.SystemWebView; import java.util.ArrayList; +import org.json.JSONArray; public class IonicWebViewEngine extends SystemWebViewEngine { public static final String TAG = "IonicWebViewEngine"; @@ -65,7 +66,7 @@ public void init(CordovaWebView parentWebView, CordovaInterface cordova, final C scheme = preferences.getString("Scheme", "http"); CDV_LOCAL_SERVER = scheme + "://" + hostname; - localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, new ArrayList()); + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, null); localServer.hostAssets("www"); webView.setWebViewClient(new ServerClient(this, parser)); @@ -165,12 +166,12 @@ public String getServerBasePath() { return this.localServer.getBasePath(); } - public void setOrigin(String hostname, String scheme) { + public void setOrigin(String hostname, String scheme, JSONArray paths) { ConfigXmlParser parser = new ConfigXmlParser(); parser.parse(cordova.getActivity()); this.scheme = scheme; - localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, new ArrayList()); + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, paths); localServer.hostAssets("www"); CDV_LOCAL_SERVER = scheme + "://" + hostname; webView.loadUrl(CDV_LOCAL_SERVER); diff --git a/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java b/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java index 8b1d28a2..a7553104 100644 --- a/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java +++ b/src/android/com/ionicframework/cordova/webview/WebViewLocalServer.java @@ -35,6 +35,8 @@ import java.util.UUID; import java.util.ArrayList; +import org.json.JSONArray; + /** * Helper class meant to be used with the android.webkit.WebView class to enable hosting assets, * resources and other data on 'virtual' http(s):// URL. @@ -65,7 +67,7 @@ public class WebViewLocalServer { // Whether to route all requests to paths without extensions back to `index.html` private final boolean html5mode; private ConfigXmlParser parser; - private ArrayList ignorePaths; + private JSONArray ignorePaths; public String getAuthority() { return authority; } @@ -165,7 +167,7 @@ public Uri getHttpsPrefix() { } } - WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser, String customScheme, ArrayList ignorePaths) { + WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser, String customScheme, JSONArray ignorePaths) { uriMatcher = new UriMatcher(null); this.html5mode = html5mode; this.parser = parser; @@ -226,9 +228,17 @@ public WebResourceResponse shouldInterceptRequest(Uri uri, WebResourceRequest re return null; } - for(String path : ignorePaths) { - if (uri.getPath().contains(path)) { - return null; + if(this.ignorePaths != null) { + for (int i = 0; i < this.ignorePaths.length(); i++) { + try { + String path = this.ignorePaths.getString(i); + + if (uri.getPath().contains(path)) { + return null; + } + } catch(Exception e) { + // Ingore + } } } diff --git a/src/www/util.js b/src/www/util.js index 436ecb4d..1d9a33d1 100644 --- a/src/www/util.js +++ b/src/www/util.js @@ -25,8 +25,8 @@ var WebView = { persistServerBasePath: function() { exec(null, null, 'IonicWebView', 'persistServerBasePath', []); }, - setOrigin: function(hostname, scheme) { - exec(null, null, 'IonicWebView', 'setOrigin', [hostname, scheme]); + setOrigin: function(hostname, scheme, paths) { + exec(null, null, 'IonicWebView', 'setOrigin', [hostname, scheme, paths]); } } From d6dba52ae8571486c484e1fc89643caa90cd183a Mon Sep 17 00:00:00 2001 From: Niklas Merz Date: Tue, 10 Dec 2019 09:36:58 +0100 Subject: [PATCH 3/4] Switch hostname while preserving path --- .../ionicframework/cordova/webview/IonicWebViewEngine.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java index dfdc7830..8bb9d064 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java @@ -173,7 +173,10 @@ public void setOrigin(String hostname, String scheme, JSONArray paths) { this.scheme = scheme; localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, paths); localServer.hostAssets("www"); + String url = webView.getUrl(); + String oldHost = CDV_LOCAL_SERVER; CDV_LOCAL_SERVER = scheme + "://" + hostname; - webView.loadUrl(CDV_LOCAL_SERVER); + url = url.replace(oldHost, CDV_LOCAL_SERVER); + webView.loadUrl(url); } } From 3a00bb4eb98a4e05234287864fc6df048fb415c9 Mon Sep 17 00:00:00 2001 From: Niklas Merz Date: Fri, 13 Dec 2019 14:16:08 +0100 Subject: [PATCH 4/4] (android): Set origin save last used hostname etc. --- .../cordova/webview/IonicWebView.java | 10 ++++++++++ .../cordova/webview/IonicWebViewEngine.java | 20 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebView.java b/src/android/com/ionicframework/cordova/webview/IonicWebView.java index c1c27f7b..a9f32b4c 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebView.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebView.java @@ -12,6 +12,9 @@ public class IonicWebView extends CordovaPlugin { public static final String WEBVIEW_PREFS_NAME = "WebViewSettings"; public static final String CDV_SERVER_PATH = "serverBasePath"; + public static final String CDV_HOSTNAME = "hostname"; + public static final String CDV_SCHEME = "scheme"; + public static final String CDV_PATHS = "paths"; public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { @@ -37,6 +40,13 @@ public void run() { final String hostname = args.getString(0); final String scheme = args.getString(1); final JSONArray paths = args.getJSONArray(2); + SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(WEBVIEW_PREFS_NAME, + Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(CDV_HOSTNAME, hostname); + editor.putString(CDV_SCHEME, scheme); + editor.putString(CDV_PATHS, paths.toString()); + editor.apply(); cordova.getActivity().runOnUiThread(new Runnable() { public void run() { ((IonicWebViewEngine) webView.getEngine()).setOrigin(hostname, scheme, paths); diff --git a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java index 8bb9d064..31a702a7 100644 --- a/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java +++ b/src/android/com/ionicframework/cordova/webview/IonicWebViewEngine.java @@ -64,9 +64,26 @@ public void init(CordovaWebView parentWebView, CordovaInterface cordova, final C String hostname = preferences.getString("Hostname", "localhost"); scheme = preferences.getString("Scheme", "http"); + + SharedPreferences prefs = cordova.getActivity().getApplicationContext() + .getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); + String hostnamePref = prefs.getString(IonicWebView.CDV_HOSTNAME, null); + String schemePref = prefs.getString(IonicWebView.CDV_SCHEME, null); + JSONArray paths = null; + if (hostnamePref != null && schemePref != null) { + String pathsPref = prefs.getString(IonicWebView.CDV_PATHS, null); + try { + paths = new JSONArray(pathsPref); + } catch(Exception e) { + //invalid ignore + } + hostname = hostnamePref; + scheme = schemePref; + } + CDV_LOCAL_SERVER = scheme + "://" + hostname; - localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, null); + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme, paths); localServer.hostAssets("www"); webView.setWebViewClient(new ServerClient(this, parser)); @@ -77,7 +94,6 @@ public void init(CordovaWebView parentWebView, CordovaInterface cordova, final C int mode = preferences.getInteger("MixedContentMode", 0); settings.setMixedContentMode(mode); } - SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); String path = prefs.getString(IonicWebView.CDV_SERVER_PATH, null); if (!isDeployDisabled() && !isNewBinary() && path != null && !path.isEmpty()) { setServerBasePath(path);