diff --git a/bin/templates/project/gitignore b/bin/templates/project/gitignore index a1c8ff71..6e524459 100644 --- a/bin/templates/project/gitignore +++ b/bin/templates/project/gitignore @@ -5,7 +5,7 @@ local.properties /gradlew.bat /gradle # Ant builds -ant-built +ant-build ant-gen # Eclipse builds gen diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java index 98174763..49131d80 100755 --- a/framework/src/org/apache/cordova/AndroidWebView.java +++ b/framework/src/org/apache/cordova/AndroidWebView.java @@ -123,7 +123,7 @@ public class AndroidWebView extends WebView implements CordovaWebView { pluginManager = new PluginManager(this, this.cordova, pluginEntries); resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); - bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova)); + bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova), this.cordova.getActivity().getPackageName()); pluginManager.addService("App", "org.apache.cordova.CoreAndroid"); initWebViewSettings(); @@ -598,6 +598,9 @@ public class AndroidWebView extends WebView implements CordovaWebView { public void handleDestroy() { + // Cancel pending timeout timer. + loadUrlTimeout++; + // Send destroy event to JavaScript this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};"); diff --git a/framework/src/org/apache/cordova/CordovaBridge.java b/framework/src/org/apache/cordova/CordovaBridge.java index c3f10f3b..becbd529 100644 --- a/framework/src/org/apache/cordova/CordovaBridge.java +++ b/framework/src/org/apache/cordova/CordovaBridge.java @@ -37,12 +37,14 @@ public class CordovaBridge { private NativeToJsMessageQueue jsMessageQueue; private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread. private String loadedUrl; + private String appContentUrlPrefix; - public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) { + public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue, String packageName) { this.pluginManager = pluginManager; this.jsMessageQueue = jsMessageQueue; + this.appContentUrlPrefix = "content://" + packageName + "."; } - + public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException { if (!verifySecret("exec()", bridgeSecret)) { return null; @@ -97,6 +99,8 @@ public class CordovaBridge { } // Bridge secret wrong and bridge not due to it being from the previous page. if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) { + Log.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!"); + clearBridgeSecret(); throw new IllegalAccessException(); } return true; @@ -165,7 +169,9 @@ public class CordovaBridge { // Protect against random iframes being able to talk through the bridge. // Trust only file URLs and the start URL's domain. // The extra origin.startsWith("http") is to protect against iframes with data: having "" as origin. - if (origin.startsWith("file:") || (origin.startsWith("http") && loadedUrl.startsWith(origin))) { + if (origin.startsWith("file:") || + origin.startsWith(this.appContentUrlPrefix) || + (origin.startsWith("http") && loadedUrl.startsWith(origin))) { // Enable the bridge int bridgeMode = Integer.parseInt(defaultValue.substring(9)); jsMessageQueue.setBridgeMode(bridgeMode);