From c2cafb4b45fcbb307a113828dfc9f723f8a6433b Mon Sep 17 00:00:00 2001 From: Andrey Kurdyumov Date: Sun, 20 Jul 2014 00:28:44 +0600 Subject: [PATCH 1/9] CB-7172 Force window to have focus after resume Workaround for some devices (Samsung Galaxy Note 3 at least) github: close #108 --- framework/src/org/apache/cordova/CordovaActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index 4a46c808..2fdb9a7b 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -604,6 +604,9 @@ public class CordovaActivity extends Activity implements CordovaInterface { if (this.appView == null) { return; } + // Force window to have focus, so application always + // receive user input. Workaround for some devices (Samsung Galaxy Note 3 at least) + this.getWindow().getDecorView().requestFocus(); this.appView.handleResume(this.keepRunning, this.activityResultKeepRunning); From 955133f1737cb9352de8c20fd22b30967fc4e1f9 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Thu, 26 Jun 2014 15:48:50 -0400 Subject: [PATCH 2/9] Extend whitelist to handle URLs without // chars --- framework/src/org/apache/cordova/Whitelist.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/org/apache/cordova/Whitelist.java b/framework/src/org/apache/cordova/Whitelist.java index ecbb7f61..5101ec35 100644 --- a/framework/src/org/apache/cordova/Whitelist.java +++ b/framework/src/org/apache/cordova/Whitelist.java @@ -124,15 +124,15 @@ public class Whitelist { whiteList = null; } else { // specific access - Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+)://)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?"); + Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?"); Matcher m = parts.matcher(origin); if (m.matches()) { String scheme = m.group(2); - String host = m.group(3); + String host = m.group(4); // Special case for two urls which are allowed to have empty hosts if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*"; - String port = m.group(7); - String path = m.group(8); + String port = m.group(8); + 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)); From 3d191d5884ef66d97cbf89bd1347cf2da1d4dacf Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Thu, 31 Jul 2014 08:17:31 -0700 Subject: [PATCH 3/9] CB-7238: Minor band-aid to get tests running again, this has to go away before 3.6.0 is released, since this is an API change. --- .../org/apache/cordova/test/CordovaWebViewTestActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java index 06070cc5..f9382d93 100644 --- a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java +++ b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java @@ -47,6 +47,9 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter setContentView(R.layout.main); + //CB-7238: This has to be added now, because it got removed from somewhere else + Config.init(this); + cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView); Config.init(this); cordovaWebView.init(this, new CordovaWebViewClient(this, cordovaWebView), new CordovaChromeClient(this, cordovaWebView), From 48b51c451a6b761d0e4e0415252642fc96e62960 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Thu, 31 Jul 2014 09:23:14 -0700 Subject: [PATCH 4/9] CB-7238: I should have collapsed this, but Config.init() must go before the creation of CordovaWebView --- test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java index f9382d93..1c1789ef 100644 --- a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java +++ b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java @@ -51,7 +51,6 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter Config.init(this); cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView); - Config.init(this); cordovaWebView.init(this, new CordovaWebViewClient(this, cordovaWebView), new CordovaChromeClient(this, cordovaWebView), Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences()); From 993d73762caaf02e2d5045fb9e60345e2a8bf6ac Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Mon, 21 Jul 2014 09:20:49 -0400 Subject: [PATCH 5/9] Handle unsupported protocol errors in webview better --- .../org/apache/cordova/CordovaWebViewClient.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index a2cf0bed..f65a9760 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -231,7 +231,19 @@ public class CordovaWebViewClient extends WebViewClient { // Clear timeout flag this.appView.loadUrlTimeout++; - // Handle error + // If this is a "Protocol Not Supported" error, then revert to the previous + // page. If there was no previous page, then punt. The application's config + // is likely incorrect (start page set to sms: or something like that) + if (errorCode == WebViewClient.ERROR_UNSUPPORTED_SCHEME) { + if (view.canGoBack()) { + view.goBack(); + return; + } else { + super.onReceivedError(view, errorCode, description, failingUrl); + } + } + + // Handle other errors by passing them to the webview in JS JSONObject data = new JSONObject(); try { data.put("errorCode", errorCode); From d6eb723b7fdefc1dd2c3d8b0cdae24783ac8968f Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Tue, 22 Jul 2014 13:53:33 -0400 Subject: [PATCH 6/9] Filter out non-launchable intents --- framework/src/org/apache/cordova/CordovaUriHelper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/org/apache/cordova/CordovaUriHelper.java b/framework/src/org/apache/cordova/CordovaUriHelper.java index f189f1ce..dcbaeb5e 100644 --- a/framework/src/org/apache/cordova/CordovaUriHelper.java +++ b/framework/src/org/apache/cordova/CordovaUriHelper.java @@ -69,6 +69,9 @@ class CordovaUriHelper { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + intent.setComponent(null); + intent.setSelector(null); this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error loading url " + url, e); From 73219bf2d22a7057f19b6dd9cd8fd24632316d90 Mon Sep 17 00:00:00 2001 From: Martin Bektchiev Date: Wed, 6 Aug 2014 15:24:51 +0300 Subject: [PATCH 7/9] CB-7265 Fix crash when navigating to custom protocol (introduced in 3.5.1) Conflicts: framework/src/org/apache/cordova/CordovaUriHelper.java Github: close #111 --- framework/src/org/apache/cordova/CordovaUriHelper.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/CordovaUriHelper.java b/framework/src/org/apache/cordova/CordovaUriHelper.java index dcbaeb5e..bb785920 100644 --- a/framework/src/org/apache/cordova/CordovaUriHelper.java +++ b/framework/src/org/apache/cordova/CordovaUriHelper.java @@ -19,8 +19,10 @@ package org.apache.cordova; +import android.annotation.TargetApi; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.webkit.WebView; class CordovaUriHelper { @@ -44,6 +46,7 @@ class CordovaUriHelper { * @param url The url to be loaded. * @return true to override, false for default behavior */ + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) boolean shouldOverrideUrlLoading(WebView view, String url) { // The WebView should support http and https when going on the Internet if(url.startsWith("http:") || url.startsWith("https:")) @@ -71,7 +74,9 @@ class CordovaUriHelper { intent.setData(Uri.parse(url)); intent.addCategory(Intent.CATEGORY_BROWSABLE); intent.setComponent(null); - intent.setSelector(null); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + intent.setSelector(null); + } this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error loading url " + url, e); From 41125ea1e2ce9bff3191f57d88c10c277cbb3e94 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Thu, 7 Aug 2014 16:18:56 -0400 Subject: [PATCH 8/9] CB-7261 Fix setNativeToJsBridgeMode sometimes crashing when switching to ONLINE_EVENT --- .../org/apache/cordova/NativeToJsMessageQueue.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java index d05eed82..497366f2 100755 --- a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java +++ b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java @@ -321,11 +321,16 @@ public class NativeToJsMessageQueue { } } }; + final Runnable resetNetworkRunnable = new Runnable() { + public void run() { + online = false; + // If the following call triggers a notifyOfFlush, then ignore it. + ignoreNextFlush = true; + webView.setNetworkAvailable(true); + } + }; @Override void reset() { - online = false; - // If the following call triggers a notifyOfFlush, then ignore it. - ignoreNextFlush = true; - webView.setNetworkAvailable(true); + cordova.getActivity().runOnUiThread(resetNetworkRunnable); } @Override void onNativeToJsMessageAvailable() { cordova.getActivity().runOnUiThread(toggleNetworkRunnable); From 320e31bb105cf6401e646f45810ef3c136bf5ab9 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Tue, 12 Aug 2014 11:09:53 -0700 Subject: [PATCH 9/9] Adding tests related to 3.5.1 --- .../cordova/test/SabotagedActivity.java | 73 +++++++++++++++++++ .../test/junit/IntentUriOverrideTest.java | 73 +++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 test/src/org/apache/cordova/test/SabotagedActivity.java create mode 100644 test/src/org/apache/cordova/test/junit/IntentUriOverrideTest.java diff --git a/test/src/org/apache/cordova/test/SabotagedActivity.java b/test/src/org/apache/cordova/test/SabotagedActivity.java new file mode 100644 index 00000000..e1170ba3 --- /dev/null +++ b/test/src/org/apache/cordova/test/SabotagedActivity.java @@ -0,0 +1,73 @@ +package org.apache.cordova.test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; + +import org.apache.cordova.Config; +import org.apache.cordova.CordovaActivity; + +import android.content.res.AssetManager; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; + +public class SabotagedActivity extends CordovaActivity { + + private String BAD_ASSET = "www/error.html"; + private String LOG_TAG = "SabotagedActivity"; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + +// copyErrorAsset(); + super.init(); + super.loadUrl(Config.getStartUrl()); + } + + /* + * Sometimes we need to move code around before we can do anything. This will + * copy the bad code out of the assets before we initalize Cordova so that when Cordova actually + * initializes, we have something for it to navigate to. + */ + + private void copyErrorAsset () { + AssetManager assetManager = getAssets(); + String[] files = null; + try { + files = assetManager.list(BAD_ASSET); + } catch (IOException e) { + Log.e(LOG_TAG, e.getMessage()); + } + + for(String filename : files) { + InputStream in = null; + OutputStream out = null; + try { + in = assetManager.open(BAD_ASSET); + out = new FileOutputStream(Environment.getExternalStorageDirectory().toString() +"/" + filename); + copy(in, out); + in.close(); + in = null; + out.flush(); + out.close(); + out = null; + } catch(Exception e) { + Log.e("tag", e.getMessage()); + } + } + } + + + //Quick and Dirty Copy! + private void copy(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int read; + while((read = in.read(buffer)) != -1){ + out.write(buffer, 0, read); + } + } +} diff --git a/test/src/org/apache/cordova/test/junit/IntentUriOverrideTest.java b/test/src/org/apache/cordova/test/junit/IntentUriOverrideTest.java new file mode 100644 index 00000000..aea06afe --- /dev/null +++ b/test/src/org/apache/cordova/test/junit/IntentUriOverrideTest.java @@ -0,0 +1,73 @@ +package org.apache.cordova.test.junit; + +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.test.SabotagedActivity; +import org.apache.cordova.test.splashscreen; + +import android.app.Instrumentation; +import android.content.Context; +import android.content.Intent; +import android.content.res.AssetManager; +import android.test.ActivityInstrumentationTestCase2; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + + +public class IntentUriOverrideTest extends ActivityInstrumentationTestCase2 { + + private int TIMEOUT = 1000; + + private SabotagedActivity testActivity; + private FrameLayout containerView; + private LinearLayout innerContainer; + private CordovaWebView testView; + private Instrumentation mInstr; + private String BAD_URL = "file:///sdcard/download/wl-exploit.htm"; + + + public IntentUriOverrideTest() + { + super("org.apache.cordova.test",SabotagedActivity.class); + } + + + protected void setUp() throws Exception { + super.setUp(); + mInstr = this.getInstrumentation(); + Intent badIntent = new Intent(); + badIntent.setClassName("org.apache.cordova.test", "org.apache.cordova.test.SabotagedActivity"); + badIntent.putExtra("url", BAD_URL); + setActivityIntent(badIntent); + testActivity = getActivity(); + containerView = (FrameLayout) testActivity.findViewById(android.R.id.content); + innerContainer = (LinearLayout) containerView.getChildAt(0); + testView = (CordovaWebView) innerContainer.getChildAt(0); + } + + + public void testPreconditions(){ + assertNotNull(innerContainer); + assertNotNull(testView); + } + + public void testChangeStartUrl() throws Throwable + { + runTestOnUiThread(new Runnable() { + public void run() + { + boolean isBadUrl = testView.getUrl().equals(BAD_URL); + assertFalse(isBadUrl); + } + }); + } + + private void sleep() { + try { + Thread.sleep(TIMEOUT); + } catch (InterruptedException e) { + fail("Unexpected Timeout"); + } + } + + +}