mirror of
https://github.com/apache/cordova-android.git
synced 2025-03-04 00:13:20 +08:00
Merge branch 'master' into 4.0.x (External whitelist changes)
This commit is contained in:
commit
31b1a821ca
@ -30,7 +30,20 @@
|
|||||||
Apache Cordova Team
|
Apache Cordova Team
|
||||||
</author>
|
</author>
|
||||||
|
|
||||||
<access origin="*"/>
|
<!-- Allow access to arbitrary URLs in the Cordova WebView. This is a
|
||||||
|
development mode setting, and should be changed for production. -->
|
||||||
|
<access origin="http://*/*"/>
|
||||||
|
<access origin="https://*/*"/>
|
||||||
|
|
||||||
|
<!-- Grant certain URLs the ability to launch external applications. This
|
||||||
|
behaviour is set to match that of Cordova versions before 3.6.0, and
|
||||||
|
should be reviewed before launching an application in production. It
|
||||||
|
may be changed in the future. -->
|
||||||
|
<access origin="tel:*" launch-external="yes"/>
|
||||||
|
<access origin="geo:*" launch-external="yes"/>
|
||||||
|
<access origin="mailto:*" launch-external="yes"/>
|
||||||
|
<access origin="sms:*" launch-external="yes"/>
|
||||||
|
<access origin="market:*" launch-external="yes"/>
|
||||||
|
|
||||||
<!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
|
<!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
|
||||||
<content src="index.html" />
|
<content src="index.html" />
|
||||||
|
@ -86,7 +86,8 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
|||||||
private WebChromeClient.CustomViewCallback mCustomViewCallback;
|
private WebChromeClient.CustomViewCallback mCustomViewCallback;
|
||||||
|
|
||||||
private CordovaResourceApi resourceApi;
|
private CordovaResourceApi resourceApi;
|
||||||
private Whitelist whitelist;
|
private Whitelist internalWhitelist;
|
||||||
|
private Whitelist externalWhitelist;
|
||||||
private CordovaPreferences preferences;
|
private CordovaPreferences preferences;
|
||||||
// The URL passed to loadUrl(), not necessarily the URL of the current page.
|
// The URL passed to loadUrl(), not necessarily the URL of the current page.
|
||||||
String loadedUrl;
|
String loadedUrl;
|
||||||
@ -110,12 +111,14 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
|||||||
// Use two-phase init so that the control will work with XML layouts.
|
// Use two-phase init so that the control will work with XML layouts.
|
||||||
@Override
|
@Override
|
||||||
public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
||||||
Whitelist whitelist, CordovaPreferences preferences) {
|
Whitelist internalWhitelist, Whitelist externalWhitelist,
|
||||||
|
CordovaPreferences preferences) {
|
||||||
if (this.cordova != null) {
|
if (this.cordova != null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
this.cordova = cordova;
|
this.cordova = cordova;
|
||||||
this.whitelist = whitelist;
|
this.internalWhitelist = internalWhitelist;
|
||||||
|
this.externalWhitelist = externalWhitelist;
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
|
|
||||||
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
|
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
|
||||||
@ -351,7 +354,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
|||||||
if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
|
if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
|
||||||
LOG.d(TAG, ">>> loadUrlNow()");
|
LOG.d(TAG, ">>> loadUrlNow()");
|
||||||
}
|
}
|
||||||
if (url.startsWith("file://") || url.startsWith("javascript:") || whitelist.isUrlWhiteListed(url)) {
|
if (url.startsWith("file://") || url.startsWith("javascript:") || internalWhitelist.isUrlWhiteListed(url)) {
|
||||||
super.loadUrl(url);
|
super.loadUrl(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +429,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
|||||||
if (!openExternal) {
|
if (!openExternal) {
|
||||||
|
|
||||||
// Make sure url is in whitelist
|
// Make sure url is in whitelist
|
||||||
if (url.startsWith("file://") || whitelist.isUrlWhiteListed(url)) {
|
if (url.startsWith("file://") || internalWhitelist.isUrlWhiteListed(url)) {
|
||||||
// TODO: What about params?
|
// TODO: What about params?
|
||||||
// Load new URL
|
// Load new URL
|
||||||
loadUrlIntoView(url, true);
|
loadUrlIntoView(url, true);
|
||||||
@ -744,7 +747,12 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Whitelist getWhitelist() {
|
public Whitelist getWhitelist() {
|
||||||
return this.whitelist;
|
return this.internalWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Whitelist getExternalWhitelist() {
|
||||||
|
return this.externalWhitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,7 +58,7 @@ public class Config {
|
|||||||
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parser.getWhitelist().addWhiteListEntry(origin, subdomains);
|
parser.getInternalWhitelist().addWhiteListEntry(origin, subdomains);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,7 +72,21 @@ public class Config {
|
|||||||
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return parser.getWhitelist().isUrlWhiteListed(url);
|
return parser.getInternalWhitelist().isUrlWhiteListed(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if URL is in approved list of URLs to launch external applications.
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return true if whitelisted
|
||||||
|
*/
|
||||||
|
public static boolean isUrlExternallyWhiteListed(String url) {
|
||||||
|
if (parser == null) {
|
||||||
|
Log.e(TAG, "Config was not initialised. Did you forget to Config.init(this)?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return parser.getExternalWhitelist().isUrlWhiteListed(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getStartUrl() {
|
public static String getStartUrl() {
|
||||||
@ -87,7 +101,11 @@ public class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Whitelist getWhitelist() {
|
public static Whitelist getWhitelist() {
|
||||||
return parser.getWhitelist();
|
return parser.getInternalWhitelist();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Whitelist getExternalWhitelist() {
|
||||||
|
return parser.getExternalWhitelist();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PluginEntry> getPluginEntries() {
|
public static List<PluginEntry> getPluginEntries() {
|
||||||
|
@ -36,11 +36,16 @@ public class ConfigXmlParser {
|
|||||||
|
|
||||||
private String launchUrl = "file:///android_asset/www/index.html";
|
private String launchUrl = "file:///android_asset/www/index.html";
|
||||||
private CordovaPreferences prefs = new CordovaPreferences();
|
private CordovaPreferences prefs = new CordovaPreferences();
|
||||||
private Whitelist whitelist = new Whitelist();
|
private Whitelist internalWhitelist = new Whitelist();
|
||||||
|
private Whitelist externalWhitelist = new Whitelist();
|
||||||
private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
|
private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
|
||||||
|
|
||||||
public Whitelist getWhitelist() {
|
public Whitelist getInternalWhitelist() {
|
||||||
return whitelist;
|
return internalWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Whitelist getExternalWhitelist() {
|
||||||
|
return externalWhitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CordovaPreferences getPreferences() {
|
public CordovaPreferences getPreferences() {
|
||||||
@ -75,6 +80,11 @@ public class ConfigXmlParser {
|
|||||||
boolean onload = false;
|
boolean onload = false;
|
||||||
boolean insideFeature = false;
|
boolean insideFeature = false;
|
||||||
|
|
||||||
|
// Add implicitly allowed URLs
|
||||||
|
internalWhitelist.addWhiteListEntry("file:///*", false);
|
||||||
|
internalWhitelist.addWhiteListEntry("content:///*", false);
|
||||||
|
internalWhitelist.addWhiteListEntry("data:*", false);
|
||||||
|
|
||||||
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
||||||
if (eventType == XmlResourceParser.START_TAG) {
|
if (eventType == XmlResourceParser.START_TAG) {
|
||||||
String strNode = xml.getName();
|
String strNode = xml.getName();
|
||||||
@ -96,8 +106,21 @@ public class ConfigXmlParser {
|
|||||||
else if (strNode.equals("access")) {
|
else if (strNode.equals("access")) {
|
||||||
String origin = xml.getAttributeValue(null, "origin");
|
String origin = xml.getAttributeValue(null, "origin");
|
||||||
String subdomains = xml.getAttributeValue(null, "subdomains");
|
String subdomains = xml.getAttributeValue(null, "subdomains");
|
||||||
|
boolean external = (xml.getAttributeValue(null, "launch-external") != null);
|
||||||
if (origin != null) {
|
if (origin != null) {
|
||||||
whitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
if (external) {
|
||||||
|
externalWhitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||||
|
} else {
|
||||||
|
if ("*".equals(origin)) {
|
||||||
|
// Special-case * origin to mean http and https when used for internal
|
||||||
|
// whitelist. This prevents external urls like sms: and geo: from being
|
||||||
|
// handled internally.
|
||||||
|
internalWhitelist.addWhiteListEntry("http://*/*", false);
|
||||||
|
internalWhitelist.addWhiteListEntry("https://*/*", false);
|
||||||
|
} else {
|
||||||
|
internalWhitelist.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strNode.equals("preference")) {
|
else if (strNode.equals("preference")) {
|
||||||
|
@ -121,7 +121,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
|||||||
|
|
||||||
// Read from config.xml:
|
// Read from config.xml:
|
||||||
protected CordovaPreferences preferences;
|
protected CordovaPreferences preferences;
|
||||||
protected Whitelist whitelist;
|
protected Whitelist internalWhitelist;
|
||||||
|
protected Whitelist externalWhitelist;
|
||||||
protected String launchUrl;
|
protected String launchUrl;
|
||||||
protected ArrayList<PluginEntry> pluginEntries;
|
protected ArrayList<PluginEntry> pluginEntries;
|
||||||
|
|
||||||
@ -181,7 +182,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
|||||||
preferences = parser.getPreferences();
|
preferences = parser.getPreferences();
|
||||||
preferences.setPreferencesBundle(getIntent().getExtras());
|
preferences.setPreferencesBundle(getIntent().getExtras());
|
||||||
preferences.copyIntoIntentExtras(this);
|
preferences.copyIntoIntentExtras(this);
|
||||||
whitelist = parser.getWhitelist();
|
internalWhitelist = parser.getInternalWhitelist();
|
||||||
|
externalWhitelist = parser.getExternalWhitelist();
|
||||||
launchUrl = parser.getLaunchUrl();
|
launchUrl = parser.getLaunchUrl();
|
||||||
pluginEntries = parser.getPluginEntries();
|
pluginEntries = parser.getPluginEntries();
|
||||||
Config.parser = parser;
|
Config.parser = parser;
|
||||||
@ -256,7 +258,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
|||||||
// If all else fails, return a default WebView
|
// If all else fails, return a default WebView
|
||||||
ret = new AndroidWebView(this);
|
ret = new AndroidWebView(this);
|
||||||
}
|
}
|
||||||
ret.init(this, pluginEntries, whitelist, preferences);
|
ret.init(this, pluginEntries, internalWhitelist, externalWhitelist, preferences);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +546,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
|||||||
|
|
||||||
// If errorUrl specified, then load it
|
// If errorUrl specified, then load it
|
||||||
final String errorUrl = preferences.getString("errorUrl", null);
|
final String errorUrl = preferences.getString("errorUrl", null);
|
||||||
if ((errorUrl != null) && (errorUrl.startsWith("file://") || whitelist.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
|
if ((errorUrl != null) && (errorUrl.startsWith("file://") || internalWhitelist.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
|
||||||
// Load URL on UI thread
|
// Load URL on UI thread
|
||||||
me.runOnUiThread(new Runnable() {
|
me.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -48,18 +48,11 @@ public class CordovaUriHelper {
|
|||||||
*/
|
*/
|
||||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
||||||
public boolean shouldOverrideUrlLoading(String url) {
|
public boolean shouldOverrideUrlLoading(String url) {
|
||||||
// The WebView should support http and https when going on the Internet
|
|
||||||
if(url.startsWith("http:") || url.startsWith("https:"))
|
|
||||||
{
|
|
||||||
// We only need to whitelist sites on the Internet!
|
|
||||||
if(appView.getWhitelist().isUrlWhiteListed(url))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Give plugins the chance to handle the url
|
// Give plugins the chance to handle the url
|
||||||
else if (this.appView.getPluginManager().onOverrideUrlLoading(url)) {
|
if (this.appView.getPluginManager().onOverrideUrlLoading(url)) {
|
||||||
|
// Do nothing other than what the plugins wanted.
|
||||||
|
// If any returned true, then the request was handled.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if(url.startsWith("file://") | url.startsWith("data:"))
|
else if(url.startsWith("file://") | url.startsWith("data:"))
|
||||||
{
|
{
|
||||||
@ -67,7 +60,11 @@ public class CordovaUriHelper {
|
|||||||
//DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!
|
//DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!
|
||||||
return url.contains("app_webview");
|
return url.contains("app_webview");
|
||||||
}
|
}
|
||||||
else
|
else if (appView.getWhitelist().isUrlWhiteListed(url)) {
|
||||||
|
// Allow internal navigation
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (appView.getExternalWhitelist().isUrlWhiteListed(url))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
@ -78,11 +75,12 @@ public class CordovaUriHelper {
|
|||||||
intent.setSelector(null);
|
intent.setSelector(null);
|
||||||
}
|
}
|
||||||
this.cordova.getActivity().startActivity(intent);
|
this.cordova.getActivity().startActivity(intent);
|
||||||
|
return true;
|
||||||
} catch (android.content.ActivityNotFoundException e) {
|
} catch (android.content.ActivityNotFoundException e) {
|
||||||
LOG.e(TAG, "Error loading url " + url, e);
|
LOG.e(TAG, "Error loading url " + url, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Default behaviour should be to load the default intent, let's see what happens!
|
// Intercept the request and do nothing with it -- block it
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ public interface CordovaWebView {
|
|||||||
public static final String CORDOVA_VERSION = "4.0.0-dev";
|
public static final String CORDOVA_VERSION = "4.0.0-dev";
|
||||||
|
|
||||||
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
||||||
Whitelist whitelist, CordovaPreferences preferences);
|
Whitelist internalWhitelist, Whitelist externalWhitelist,
|
||||||
|
CordovaPreferences preferences);
|
||||||
|
|
||||||
View getView();
|
View getView();
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ public interface CordovaWebView {
|
|||||||
PluginManager getPluginManager();
|
PluginManager getPluginManager();
|
||||||
|
|
||||||
Whitelist getWhitelist();
|
Whitelist getWhitelist();
|
||||||
|
Whitelist getExternalWhitelist();
|
||||||
CordovaPreferences getPreferences();
|
CordovaPreferences getPreferences();
|
||||||
|
|
||||||
void onFilePickerResult(Uri uri);
|
void onFilePickerResult(Uri uri);
|
||||||
|
@ -98,10 +98,6 @@ public class Whitelist {
|
|||||||
|
|
||||||
public Whitelist() {
|
public Whitelist() {
|
||||||
this.whiteList = new ArrayList<URLPattern>();
|
this.whiteList = new ArrayList<URLPattern>();
|
||||||
// Add implicitly allowed URLs
|
|
||||||
addWhiteListEntry("file:///*", false);
|
|
||||||
addWhiteListEntry("content:///*", false);
|
|
||||||
addWhiteListEntry("data:*", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
|
/* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
Apache Cordova Team
|
Apache Cordova Team
|
||||||
</author>
|
</author>
|
||||||
<access origin="*.apache.org" />
|
<access origin="*.apache.org" />
|
||||||
|
<access origin="http://*.google.com/*" />
|
||||||
|
<access origin="https://*.google.com/*" />
|
||||||
|
<access origin="https://*.googleapis.com/*" />
|
||||||
|
<access origin="https://*.gstatic.com/*" />
|
||||||
<content src="index.html" />
|
<content src="index.html" />
|
||||||
<preference name="loglevel" value="DEBUG" />
|
<preference name="loglevel" value="DEBUG" />
|
||||||
<preference name="useBrowserHistory" value="true" />
|
<preference name="useBrowserHistory" value="true" />
|
||||||
|
@ -51,7 +51,8 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
|
|||||||
Config.init(this);
|
Config.init(this);
|
||||||
|
|
||||||
cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
|
cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
|
||||||
cordovaWebView.init(this, Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
|
cordovaWebView.init(this, Config.getPluginEntries(), Config.getWhitelist(),
|
||||||
|
Config.getExternalWhitelist(), Config.getPreferences());
|
||||||
|
|
||||||
cordovaWebView.loadUrl("file:///android_asset/www/index.html");
|
cordovaWebView.loadUrl("file:///android_asset/www/index.html");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user