You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by er...@apache.org on 2021/07/02 02:52:14 UTC

[cordova-android] branch master updated: feat(allow-list)!: integrate and refactor core plugin (#1138)

This is an automated email from the ASF dual-hosted git repository.

erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-android.git


The following commit(s) were added to refs/heads/master by this push:
     new 015db81  feat(allow-list)!: integrate and refactor core plugin (#1138)
015db81 is described below

commit 015db819aed3f35892d2b6035781ea4bd752149d
Author: エリス <er...@users.noreply.github.com>
AuthorDate: Fri Jul 2 11:52:05 2021 +0900

    feat(allow-list)!: integrate and refactor core plugin (#1138)
    
    * refactor!: naming to allow list
    * feat(allow-list): integrate core plugin
    * refactor(allow-list): cleanup
    * refactor: drop deprecated launch-external case for CustomConfigParser::handleStartTag
    * fix: apply review comments
---
 bin/templates/project/assets/www/index.html        |   2 +-
 bin/templates/project/res/xml/config.xml           |   2 +-
 .../cordova/{Whitelist.java => AllowList.java}     |  34 ++---
 .../src/org/apache/cordova/AllowListPlugin.java    | 157 +++++++++++++++++++++
 framework/src/org/apache/cordova/Config.java       |   2 +-
 .../src/org/apache/cordova/ConfigXmlParser.java    |   9 ++
 .../src/org/apache/cordova/CordovaWebView.java     |   2 +-
 .../src/org/apache/cordova/CordovaWebViewImpl.java |   6 +-
 .../src/org/apache/cordova/allowlist}/index.html   |   2 +-
 .../src/org/apache/cordova/allowlist}/index2.html  |   2 +-
 .../apache/cordova/engine/SystemWebViewClient.java |   4 +-
 .../assets/www/{whitelist => allowlist}/index.html |   2 +-
 .../www/{whitelist => allowlist}/index2.html       |   2 +-
 test/androidx/app/src/main/assets/www/index.html   |   2 +-
 14 files changed, 197 insertions(+), 31 deletions(-)

diff --git a/bin/templates/project/assets/www/index.html b/bin/templates/project/assets/www/index.html
index 646f9cb..590563b 100644
--- a/bin/templates/project/assets/www/index.html
+++ b/bin/templates/project/assets/www/index.html
@@ -21,7 +21,7 @@
     <head>
         <!--
         Customize this policy to fit your own app's needs. For more guidance, see:
-            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
+            https://cordova.apache.org/docs/en/latest/
         Some notes:
             * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
             * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
diff --git a/bin/templates/project/res/xml/config.xml b/bin/templates/project/res/xml/config.xml
index ae06783..79e01a0 100644
--- a/bin/templates/project/res/xml/config.xml
+++ b/bin/templates/project/res/xml/config.xml
@@ -33,7 +33,7 @@
     <!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
     <content src="index.html" />
 
-    <!-- Whitelist docs: https://github.com/apache/cordova-plugin-whitelist -->
+    <!-- Allow List docs: https://cordova.apache.org/docs/en/latest/ -->
     <access origin="*" />
     <!-- Grant certain URLs the ability to launch external applications. This
          behaviour is set to match that of Cordova versions before 3.6.0, and
diff --git a/framework/src/org/apache/cordova/Whitelist.java b/framework/src/org/apache/cordova/AllowList.java
similarity index 87%
rename from framework/src/org/apache/cordova/Whitelist.java
rename to framework/src/org/apache/cordova/AllowList.java
index d0f823c..4b4bafc 100644
--- a/framework/src/org/apache/cordova/Whitelist.java
+++ b/framework/src/org/apache/cordova/AllowList.java
@@ -28,7 +28,7 @@ import org.apache.cordova.LOG;
 
 import android.net.Uri;
 
-public class Whitelist {
+public class AllowList {
     private static class URLPattern {
         public Pattern scheme;
         public Pattern host;
@@ -92,12 +92,12 @@ public class Whitelist {
         }
     }
 
-    private ArrayList<URLPattern> whiteList;
+    private ArrayList<URLPattern> allowList;
 
-    public static final String TAG = "Whitelist";
+    public static final String TAG = "CordovaAllowList";
 
-    public Whitelist() {
-        this.whiteList = new ArrayList<URLPattern>();
+    public AllowList() {
+        this.allowList = new ArrayList<URLPattern>();
     }
 
     /* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
@@ -111,13 +111,13 @@ public class Whitelist {
      * the scheme to be omitted for backwards compatibility. (Also host is not required
      * to begin with a "*" or "*.".)
      */
-    public void addWhiteListEntry(String origin, boolean subdomains) {
-        if (whiteList != null) {
+    public void addAllowListEntry(String origin, boolean subdomains) {
+        if (allowList != null) {
             try {
                 // Unlimited access to network resources
                 if (origin.compareTo("*") == 0) {
                     LOG.d(TAG, "Unlimited access to network resources");
-                    whiteList = null;
+                    allowList = null;
                 }
                 else { // specific access
                     Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
@@ -131,10 +131,10 @@ public class Whitelist {
                         String path = m.group(9);
                         if (scheme == null) {
                             // XXX making it stupid friendly for people who forget to include protocol/SSL
-                            whiteList.add(new URLPattern("http", host, port, path));
-                            whiteList.add(new URLPattern("https", host, port, path));
+                            allowList.add(new URLPattern("http", host, port, path));
+                            allowList.add(new URLPattern("https", host, port, path));
                         } else {
-                            whiteList.add(new URLPattern(scheme, host, port, path));
+                            allowList.add(new URLPattern(scheme, host, port, path));
                         }
                     }
                 }
@@ -149,15 +149,15 @@ public class Whitelist {
      * Determine if URL is in approved list of URLs to load.
      *
      * @param uri
-     * @return true if wide open or whitelisted
+     * @return true if wide open or allow listed
      */
-    public boolean isUrlWhiteListed(String uri) {
-        // If there is no whitelist, then it's wide open
-        if (whiteList == null) return true;
+    public boolean isUrlAllowListed(String uri) {
+        // If there is no allowList, then it's wide open
+        if (allowList == null) return true;
 
         Uri parsedUri = Uri.parse(uri);
-        // Look for match in white list
-        Iterator<URLPattern> pit = whiteList.iterator();
+        // Look for match in allow list
+        Iterator<URLPattern> pit = allowList.iterator();
         while (pit.hasNext()) {
             URLPattern p = pit.next();
             if (p.matches(parsedUri)) {
diff --git a/framework/src/org/apache/cordova/AllowListPlugin.java b/framework/src/org/apache/cordova/AllowListPlugin.java
new file mode 100644
index 0000000..7b2e787
--- /dev/null
+++ b/framework/src/org/apache/cordova/AllowListPlugin.java
@@ -0,0 +1,157 @@
+/*
+       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.
+*/
+
+package org.apache.cordova;
+
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.ConfigXmlParser;
+import org.apache.cordova.LOG;
+import org.apache.cordova.AllowList;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+
+public class AllowListPlugin extends CordovaPlugin {
+    public static final String PLUGIN_NAME = "CordovaAllowListPlugin";
+    protected static final String LOG_TAG = "CordovaAllowListPlugin";
+
+    private AllowList allowedNavigations;
+    private AllowList allowedIntents;
+    private AllowList allowedRequests;
+
+    // Used when instantiated via reflection by PluginManager
+    public AllowListPlugin() { }
+
+    // These can be used by embedders to allow Java-configuration of an allow list.
+    public AllowListPlugin(Context context) {
+        this(new AllowList(), new AllowList(), null);
+        new CustomConfigXmlParser().parse(context);
+    }
+
+    public AllowListPlugin(XmlPullParser xmlParser) {
+        this(new AllowList(), new AllowList(), null);
+        new CustomConfigXmlParser().parse(xmlParser);
+    }
+
+    public AllowListPlugin(AllowList allowedNavigations, AllowList allowedIntents, AllowList allowedRequests) {
+        if (allowedRequests == null) {
+            allowedRequests = new AllowList();
+            allowedRequests.addAllowListEntry("file:///*", false);
+            allowedRequests.addAllowListEntry("data:*", false);
+        }
+
+        this.allowedNavigations = allowedNavigations;
+        this.allowedIntents = allowedIntents;
+        this.allowedRequests = allowedRequests;
+    }
+
+    @Override
+    public void pluginInitialize() {
+        if (this.allowedNavigations == null) {
+            this.allowedNavigations = new AllowList();
+            this.allowedIntents = new AllowList();
+            this.allowedRequests = new AllowList();
+
+            new CustomConfigXmlParser().parse(webView.getContext());
+        }
+    }
+
+    private class CustomConfigXmlParser extends ConfigXmlParser {
+        @Override
+        public void handleStartTag(XmlPullParser xml) {
+            String strNode = xml.getName();
+            if (strNode.equals("content")) {
+                String startPage = xml.getAttributeValue(null, "src");
+                allowedNavigations.addAllowListEntry(startPage, false);
+            } else if (strNode.equals("allow-navigation")) {
+                String origin = xml.getAttributeValue(null, "href");
+                if ("*".equals(origin)) {
+                    allowedNavigations.addAllowListEntry("http://*/*", false);
+                    allowedNavigations.addAllowListEntry("https://*/*", false);
+                    allowedNavigations.addAllowListEntry("data:*", false);
+                } else {
+                    allowedNavigations.addAllowListEntry(origin, false);
+                }
+            } else if (strNode.equals("allow-intent")) {
+                String origin = xml.getAttributeValue(null, "href");
+                allowedIntents.addAllowListEntry(origin, false);
+            } else if (strNode.equals("access")) {
+                String origin = xml.getAttributeValue(null, "origin");
+
+                if (origin != null) {
+                    if ("*".equals(origin)) {
+                        allowedRequests.addAllowListEntry("http://*/*", false);
+                        allowedRequests.addAllowListEntry("https://*/*", false);
+                    } else {
+                        String subdomains = xml.getAttributeValue(null, "subdomains");
+                        allowedRequests.addAllowListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void handleEndTag(XmlPullParser xml) { }
+    }
+
+    @Override
+    public Boolean shouldAllowNavigation(String url) {
+        return this.allowedNavigations.isUrlAllowListed(url)
+            ? true
+            : null; // default policy
+    }
+
+    @Override
+    public Boolean shouldAllowRequest(String url) {
+        return (this.shouldAllowNavigation(url) || this.allowedRequests.isUrlAllowListed(url))
+            ? true
+            : null; // default policy
+    }
+
+    @Override
+    public Boolean shouldOpenExternalUrl(String url) {
+        return (this.allowedIntents.isUrlAllowListed(url))
+            ? true
+            : null; // default policy
+    }
+
+    public AllowList getAllowedNavigations() {
+        return this.allowedNavigations;
+    }
+
+    public void setAllowedNavigations(AllowList allowedNavigations) {
+        this.allowedNavigations = allowedNavigations;
+    }
+
+    public AllowList getAllowedIntents() {
+        return this.allowedIntents;
+    }
+
+    public void setAllowedIntents(AllowList allowedIntents) {
+        this.allowedIntents = allowedIntents;
+    }
+
+    public AllowList getAllowedRequests() {
+        return this.allowedRequests;
+    }
+
+    public void setAllowedRequests(AllowList allowedRequests) {
+        this.allowedRequests = allowedRequests;
+    }
+}
diff --git a/framework/src/org/apache/cordova/Config.java b/framework/src/org/apache/cordova/Config.java
index 0739795..238cd5e 100644
--- a/framework/src/org/apache/cordova/Config.java
+++ b/framework/src/org/apache/cordova/Config.java
@@ -23,7 +23,7 @@ import java.util.List;
 
 import android.app.Activity;
 
-@Deprecated // Use Whitelist, CordovaPrefences, etc. directly.
+@Deprecated // Use AllowList, CordovaPrefences, etc. directly.
 public class Config {
     private static final String TAG = "Config";
 
diff --git a/framework/src/org/apache/cordova/ConfigXmlParser.java b/framework/src/org/apache/cordova/ConfigXmlParser.java
index 17b47b0..9c14e55 100644
--- a/framework/src/org/apache/cordova/ConfigXmlParser.java
+++ b/framework/src/org/apache/cordova/ConfigXmlParser.java
@@ -68,6 +68,15 @@ public class ConfigXmlParser {
                 return;
             }
         }
+
+        pluginEntries.add(
+            new PluginEntry(
+                AllowListPlugin.PLUGIN_NAME,
+                "org.apache.cordova.AllowListPlugin",
+                true
+            )
+        );
+
         parse(action.getResources().getXml(id));
     }
 
diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java
index dec02fd..beff508 100644
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -94,7 +94,7 @@ public interface CordovaWebView {
     /**
      * Load the specified URL in the Cordova webview or a new browser instance.
      *
-     * NOTE: If openExternal is false, only whitelisted URLs can be loaded.
+     * NOTE: If openExternal is false, only allow listed URLs can be loaded.
      *
      * @param url           The url to load.
      * @param openExternal  Load url in browser instead of Cordova webview.
diff --git a/framework/src/org/apache/cordova/CordovaWebViewImpl.java b/framework/src/org/apache/cordova/CordovaWebViewImpl.java
index 55b8d3b..57b5232 100644
--- a/framework/src/org/apache/cordova/CordovaWebViewImpl.java
+++ b/framework/src/org/apache/cordova/CordovaWebViewImpl.java
@@ -218,19 +218,19 @@ public class CordovaWebViewImpl implements CordovaWebView {
 
         // If loading into our webview
         if (!openExternal) {
-            // Make sure url is in whitelist
+            // Make sure url is in allow list
             if (pluginManager.shouldAllowNavigation(url)) {
                 // TODO: What about params?
                 // Load new URL
                 loadUrlIntoView(url, true);
                 return;
             } else {
-                LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the <allow-navigation> whitelist. URL=" + url);
+                LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the <allow-navigation> allow list. URL=" + url);
                 return;
             }
         }
         if (!pluginManager.shouldOpenExternalUrl(url)) {
-            LOG.w(TAG, "showWebPage: Refusing to send intent for URL since it is not in the <allow-intent> whitelist. URL=" + url);
+            LOG.w(TAG, "showWebPage: Refusing to send intent for URL since it is not in the <allow-intent> allow list. URL=" + url);
             return;
         }
 
diff --git a/test/androidx/app/src/main/assets/www/whitelist/index.html b/framework/src/org/apache/cordova/allowlist/index.html
similarity index 98%
copy from test/androidx/app/src/main/assets/www/whitelist/index.html
copy to framework/src/org/apache/cordova/allowlist/index.html
index b9596c9..24cac6e 100755
--- a/test/androidx/app/src/main/assets/www/whitelist/index.html
+++ b/framework/src/org/apache/cordova/allowlist/index.html
@@ -27,7 +27,7 @@
       <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>
   <body onload="init();" id="stage" class="theme">
-    <h1>Whitelist Page 1</h1>
+    <h1>Allow List Page 1</h1>
     <div id="info">
         <h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
         <h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
diff --git a/test/androidx/app/src/main/assets/www/whitelist/index2.html b/framework/src/org/apache/cordova/allowlist/index2.html
similarity index 98%
copy from test/androidx/app/src/main/assets/www/whitelist/index2.html
copy to framework/src/org/apache/cordova/allowlist/index2.html
index 5d990ad..bb475a8 100755
--- a/test/androidx/app/src/main/assets/www/whitelist/index2.html
+++ b/framework/src/org/apache/cordova/allowlist/index2.html
@@ -27,7 +27,7 @@
       <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>
   <body onload="init();" id="stage" class="theme">
-    <h1>Whitelist Page 2</h1>
+    <h1>Allow List Page 2</h1>
     <div id="info">
         <h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
         <h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
diff --git a/framework/src/org/apache/cordova/engine/SystemWebViewClient.java b/framework/src/org/apache/cordova/engine/SystemWebViewClient.java
index 2af0668..2fea4fe 100755
--- a/framework/src/org/apache/cordova/engine/SystemWebViewClient.java
+++ b/framework/src/org/apache/cordova/engine/SystemWebViewClient.java
@@ -371,10 +371,10 @@ public class SystemWebViewClient extends WebViewClient {
     @SuppressWarnings("deprecation")
     public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
         try {
-            // Check the against the whitelist and lock out access to the WebView directory
+            // Check the against the allow list and lock out access to the WebView directory
             // Changing this will cause problems for your application
             if (!parentEngine.pluginManager.shouldAllowRequest(url)) {
-                LOG.w(TAG, "URL blocked by whitelist: " + url);
+                LOG.w(TAG, "URL blocked by allow list: " + url);
                 // Results in a 404.
                 return new WebResourceResponse("text/plain", "UTF-8", null);
             }
diff --git a/test/androidx/app/src/main/assets/www/whitelist/index.html b/test/androidx/app/src/main/assets/www/allowlist/index.html
similarity index 98%
rename from test/androidx/app/src/main/assets/www/whitelist/index.html
rename to test/androidx/app/src/main/assets/www/allowlist/index.html
index b9596c9..24cac6e 100755
--- a/test/androidx/app/src/main/assets/www/whitelist/index.html
+++ b/test/androidx/app/src/main/assets/www/allowlist/index.html
@@ -27,7 +27,7 @@
       <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>
   <body onload="init();" id="stage" class="theme">
-    <h1>Whitelist Page 1</h1>
+    <h1>Allow List Page 1</h1>
     <div id="info">
         <h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
         <h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
diff --git a/test/androidx/app/src/main/assets/www/whitelist/index2.html b/test/androidx/app/src/main/assets/www/allowlist/index2.html
similarity index 98%
rename from test/androidx/app/src/main/assets/www/whitelist/index2.html
rename to test/androidx/app/src/main/assets/www/allowlist/index2.html
index 5d990ad..bb475a8 100755
--- a/test/androidx/app/src/main/assets/www/whitelist/index2.html
+++ b/test/androidx/app/src/main/assets/www/allowlist/index2.html
@@ -27,7 +27,7 @@
       <script type="text/javascript" charset="utf-8" src="../main.js"></script>
   </head>
   <body onload="init();" id="stage" class="theme">
-    <h1>Whitelist Page 2</h1>
+    <h1>Allow List Page 2</h1>
     <div id="info">
         <h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
         <h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
diff --git a/test/androidx/app/src/main/assets/www/index.html b/test/androidx/app/src/main/assets/www/index.html
index 4614826..0252050 100755
--- a/test/androidx/app/src/main/assets/www/index.html
+++ b/test/androidx/app/src/main/assets/www/index.html
@@ -51,6 +51,6 @@
     <button class="btn large" onclick="startActivity('htmlnotfound/index.html');">HTML not found</button>
     <button class="btn large" onclick="startActivity('iframe/index.html');">IFrame</button>
     <button class="btn large" onclick="startActivity('lifecycle/index.html');">Lifecycle</button>
-    <button class="btn large" onclick="startActivity('whitelist/index.html');">Whitelist</button>
+    <button class="btn large" onclick="startActivity('allowlist/index.html');">Allow List</button>
   </body>
 </html>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org