mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-26 12:03:28 +08:00
Merging latest master, including new tests
This commit is contained in:
commit
a7ccb9243d
@ -197,7 +197,19 @@ public class AndroidWebViewClient extends WebViewClient {
|
|||||||
// Clear timeout flag
|
// Clear timeout flag
|
||||||
appView.loadUrlTimeout++;
|
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();
|
JSONObject data = new JSONObject();
|
||||||
try {
|
try {
|
||||||
data.put("errorCode", errorCode);
|
data.put("errorCode", errorCode);
|
||||||
|
@ -394,6 +394,9 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
|||||||
if (this.appView == null) {
|
if (this.appView == null) {
|
||||||
return;
|
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);
|
this.appView.handleResume(this.keepRunning, this.activityResultKeepRunning);
|
||||||
|
|
||||||
|
@ -19,8 +19,11 @@
|
|||||||
|
|
||||||
package org.apache.cordova;
|
package org.apache.cordova;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
|
||||||
public class CordovaUriHelper {
|
public class CordovaUriHelper {
|
||||||
|
|
||||||
@ -43,6 +46,7 @@ public class CordovaUriHelper {
|
|||||||
* @param url The url to be loaded.
|
* @param url The url to be loaded.
|
||||||
* @return true to override, false for default behavior
|
* @return true to override, false for default behavior
|
||||||
*/
|
*/
|
||||||
|
@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
|
// The WebView should support http and https when going on the Internet
|
||||||
if(url.startsWith("http:") || url.startsWith("https:"))
|
if(url.startsWith("http:") || url.startsWith("https:"))
|
||||||
@ -68,6 +72,11 @@ public class CordovaUriHelper {
|
|||||||
try {
|
try {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(url));
|
intent.setData(Uri.parse(url));
|
||||||
|
intent.addCategory(Intent.CATEGORY_BROWSABLE);
|
||||||
|
intent.setComponent(null);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||||
|
intent.setSelector(null);
|
||||||
|
}
|
||||||
this.cordova.getActivity().startActivity(intent);
|
this.cordova.getActivity().startActivity(intent);
|
||||||
} 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);
|
||||||
|
@ -321,12 +321,17 @@ public class NativeToJsMessageQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@Override void reset() {
|
final Runnable resetNetworkRunnable = new Runnable() {
|
||||||
|
public void run() {
|
||||||
online = false;
|
online = false;
|
||||||
// If the following call triggers a notifyOfFlush, then ignore it.
|
// If the following call triggers a notifyOfFlush, then ignore it.
|
||||||
ignoreNextFlush = true;
|
ignoreNextFlush = true;
|
||||||
webView.setNetworkAvailable(true);
|
webView.setNetworkAvailable(true);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
@Override void reset() {
|
||||||
|
cordova.getActivity().runOnUiThread(resetNetworkRunnable);
|
||||||
|
}
|
||||||
@Override void onNativeToJsMessageAvailable() {
|
@Override void onNativeToJsMessageAvailable() {
|
||||||
cordova.getActivity().runOnUiThread(toggleNetworkRunnable);
|
cordova.getActivity().runOnUiThread(toggleNetworkRunnable);
|
||||||
}
|
}
|
||||||
|
@ -124,15 +124,15 @@ public class Whitelist {
|
|||||||
whiteList = null;
|
whiteList = null;
|
||||||
}
|
}
|
||||||
else { // specific access
|
else { // specific access
|
||||||
Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+)://)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
|
Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
|
||||||
Matcher m = parts.matcher(origin);
|
Matcher m = parts.matcher(origin);
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
String scheme = m.group(2);
|
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
|
// Special case for two urls which are allowed to have empty hosts
|
||||||
if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
|
if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
|
||||||
String port = m.group(7);
|
String port = m.group(8);
|
||||||
String path = m.group(8);
|
String path = m.group(9);
|
||||||
if (scheme == null) {
|
if (scheme == null) {
|
||||||
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
// 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("http", host, port, path));
|
||||||
|
8
test/assets/www/error.html
Normal file
8
test/assets/www/error.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OH NOES!</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Things went terribly wrong!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -22,6 +22,8 @@ package org.apache.cordova.test;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import org.apache.cordova.AndroidChromeClient;
|
||||||
|
import org.apache.cordova.AndroidWebViewClient;
|
||||||
import org.apache.cordova.Config;
|
import org.apache.cordova.Config;
|
||||||
import org.apache.cordova.CordovaWebView;
|
import org.apache.cordova.CordovaWebView;
|
||||||
import org.apache.cordova.CordovaInterface;
|
import org.apache.cordova.CordovaInterface;
|
||||||
@ -45,10 +47,11 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
|
|||||||
|
|
||||||
setContentView(R.layout.main);
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
|
//CB-7238: This has to be added now, because it got removed from somewhere else
|
||||||
Config.init(this);
|
Config.init(this);
|
||||||
cordovaWebView.init(this,
|
|
||||||
Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
|
cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
|
||||||
|
cordovaWebView.init(this, Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
|
||||||
|
|
||||||
cordovaWebView.loadUrl("file:///android_asset/www/index.html");
|
cordovaWebView.loadUrl("file:///android_asset/www/index.html");
|
||||||
|
|
||||||
|
73
test/src/org/apache/cordova/test/SabotagedActivity.java
Normal file
73
test/src/org/apache/cordova/test/SabotagedActivity.java
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<SabotagedActivity> {
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user