You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by bo...@apache.org on 2014/08/14 23:21:18 UTC
[10/10] android commit: Merging latest master, including new tests
Merging latest master, including new tests
Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/a7ccb924
Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/a7ccb924
Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/a7ccb924
Branch: refs/heads/4.0.x
Commit: a7ccb9243daf3dfaa0f2538492dccaa4d140ba58
Parents: f9b8f9a 320e31b
Author: Joe Bowser <bo...@apache.org>
Authored: Thu Aug 14 14:20:49 2014 -0700
Committer: Joe Bowser <bo...@apache.org>
Committed: Thu Aug 14 14:20:49 2014 -0700
----------------------------------------------------------------------
.../apache/cordova/AndroidWebViewClient.java | 14 +++-
.../src/org/apache/cordova/CordovaActivity.java | 3 +
.../org/apache/cordova/CordovaUriHelper.java | 9 +++
.../apache/cordova/NativeToJsMessageQueue.java | 13 ++--
framework/src/org/apache/cordova/Whitelist.java | 8 +--
test/assets/www/error.html | 8 +++
.../test/CordovaWebViewTestActivity.java | 9 ++-
.../apache/cordova/test/SabotagedActivity.java | 73 ++++++++++++++++++++
.../test/junit/IntentUriOverrideTest.java | 73 ++++++++++++++++++++
9 files changed, 198 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/framework/src/org/apache/cordova/AndroidWebViewClient.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/AndroidWebViewClient.java
index 44862a6,0000000..c017177
mode 100755,000000..100755
--- a/framework/src/org/apache/cordova/AndroidWebViewClient.java
+++ b/framework/src/org/apache/cordova/AndroidWebViewClient.java
@@@ -1,318 -1,0 +1,330 @@@
+/*
+ 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 java.util.Hashtable;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.annotation.TargetApi;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.view.View;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+
+/**
+ * This class is the WebViewClient that implements callbacks for our web view.
+ * The kind of callbacks that happen here are regarding the rendering of the
+ * document instead of the chrome surrounding it, such as onPageStarted(),
+ * shouldOverrideUrlLoading(), etc. Related to but different than
+ * CordovaChromeClient.
+ *
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html">WebViewClient</a>
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see CordovaChromeClient
+ * @see CordovaWebView
+ */
+public class AndroidWebViewClient extends WebViewClient {
+
+ private static final String TAG = "AndroidWebViewClient";
+ protected final CordovaInterface cordova;
+ protected final AndroidWebView appView;
+ protected final CordovaUriHelper helper;
+ private boolean doClearHistory = false;
+ boolean isCurrentlyLoading;
+
+ /** The authorization tokens. */
+ private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
+
+ public AndroidWebViewClient(CordovaInterface cordova, AndroidWebView view) {
+ this.cordova = cordova;
+ this.appView = view;
+ helper = new CordovaUriHelper(cordova, view);
+ }
+
+ /**
+ * Give the host application a chance to take over the control when a new url
+ * is about to be loaded in the current WebView.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param url The url to be loaded.
+ * @return true to override, false for default behavior
+ */
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return helper.shouldOverrideUrlLoading(url);
+ }
+
+ /**
+ * On received http auth request.
+ * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
+ */
+ @Override
+ public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
+
+ // Get the authentication token
+ AuthenticationToken token = this.getAuthenticationToken(host, realm);
+ if (token != null) {
+ handler.proceed(token.getUserName(), token.getPassword());
+ }
+ else {
+ // Handle 401 like we'd normally do!
+ super.onReceivedHttpAuthRequest(view, handler, host, realm);
+ }
+ }
+
+ /**
+ * Notify the host application that a page has started loading.
+ * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
+ * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
+ * embedded frame changes, i.e. clicking a link whose target is an iframe.
+ *
+ * @param view The webview initiating the callback.
+ * @param url The url of the page.
+ */
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ super.onPageStarted(view, url, favicon);
+ isCurrentlyLoading = true;
+ LOG.d(TAG, "onPageStarted(" + url + ")");
+ // Flush stale messages & reset plugins.
+ this.appView.onPageReset();
+
+ // Broadcast message that page has loaded
+ this.appView.getPluginManager().postMessage("onPageStarted", url);
+ }
+
+ /**
+ * Notify the host application that a page has finished loading.
+ * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
+ *
+ *
+ * @param view The webview initiating the callback.
+ * @param url The url of the page.
+ */
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ // Ignore excessive calls.
+ if (!isCurrentlyLoading) {
+ return;
+ }
+ isCurrentlyLoading = false;
+ LOG.d(TAG, "onPageFinished(" + url + ")");
+
+ /**
+ * Because of a timing issue we need to clear this history in onPageFinished as well as
+ * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
+ * true. You see when you load a url with a # in it which is common in jQuery applications
+ * onPageStared is not called. Clearing the history at that point would break jQuery apps.
+ */
+ if (this.doClearHistory) {
+ view.clearHistory();
+ this.doClearHistory = false;
+ }
+
+ // Clear timeout flag
+ appView.loadUrlTimeout++;
+
+ // Broadcast message that page has loaded
+ this.appView.getPluginManager().postMessage("onPageFinished", url);
+
+ // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
+ if (this.appView.getVisibility() == View.INVISIBLE) {
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep(2000);
+ cordova.getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ appView.getPluginManager().postMessage("spinner", "stop");
+ }
+ });
+ } catch (InterruptedException e) {
+ }
+ }
+ });
+ t.start();
+ }
+
+ // Shutdown if blank loaded
+ if (url.equals("about:blank")) {
+ appView.getPluginManager().postMessage("exit", null);
+ }
+ }
+
+ /**
+ * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
+ * The errorCode parameter corresponds to one of the ERROR_* constants.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param errorCode The error code corresponding to an ERROR_* value.
+ * @param description A String describing the error.
+ * @param failingUrl The url that failed to load.
+ */
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+ // Ignore error due to stopLoading().
+ if (!isCurrentlyLoading) {
+ return;
+ }
+ LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
+
+ // Clear timeout flag
+ 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);
+ data.put("description", description);
+ data.put("url", failingUrl);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ this.appView.getPluginManager().postMessage("onReceivedError", data);
+ }
+
+ /**
+ * Notify the host application that an SSL error occurred while loading a resource.
+ * The host application must call either handler.cancel() or handler.proceed().
+ * Note that the decision may be retained for use in response to future SSL errors.
+ * The default behavior is to cancel the load.
+ *
+ * @param view The WebView that is initiating the callback.
+ * @param handler An SslErrorHandler object that will handle the user's response.
+ * @param error The SSL error object.
+ */
+ @TargetApi(8)
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+
+ final String packageName = this.cordova.getActivity().getPackageName();
+ final PackageManager pm = this.cordova.getActivity().getPackageManager();
+
+ ApplicationInfo appInfo;
+ try {
+ appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ // debug = true
+ handler.proceed();
+ return;
+ } else {
+ // debug = false
+ super.onReceivedSslError(view, handler, error);
+ }
+ } catch (NameNotFoundException e) {
+ // When it doubt, lock it out!
+ super.onReceivedSslError(view, handler, error);
+ }
+ }
+
+
+ /**
+ * Sets the authentication token.
+ *
+ * @param authenticationToken
+ * @param host
+ * @param realm
+ */
+ public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
+ if (host == null) {
+ host = "";
+ }
+ if (realm == null) {
+ realm = "";
+ }
+ this.authenticationTokens.put(host.concat(realm), authenticationToken);
+ }
+
+ /**
+ * Removes the authentication token.
+ *
+ * @param host
+ * @param realm
+ *
+ * @return the authentication token or null if did not exist
+ */
+ public AuthenticationToken removeAuthenticationToken(String host, String realm) {
+ return this.authenticationTokens.remove(host.concat(realm));
+ }
+
+ /**
+ * Gets the authentication token.
+ *
+ * In order it tries:
+ * 1- host + realm
+ * 2- host
+ * 3- realm
+ * 4- no host, no realm
+ *
+ * @param host
+ * @param realm
+ *
+ * @return the authentication token
+ */
+ public AuthenticationToken getAuthenticationToken(String host, String realm) {
+ AuthenticationToken token = null;
+ token = this.authenticationTokens.get(host.concat(realm));
+
+ if (token == null) {
+ // try with just the host
+ token = this.authenticationTokens.get(host);
+
+ // Try the realm
+ if (token == null) {
+ token = this.authenticationTokens.get(realm);
+ }
+
+ // if no host found, just query for default
+ if (token == null) {
+ token = this.authenticationTokens.get("");
+ }
+ }
+
+ return token;
+ }
+
+ /**
+ * Clear all authentication tokens.
+ */
+ public void clearAuthenticationTokens() {
+ this.authenticationTokens.clear();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/framework/src/org/apache/cordova/CordovaActivity.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/framework/src/org/apache/cordova/CordovaUriHelper.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/CordovaUriHelper.java
index 077e425,bb78592..f7d22da
--- a/framework/src/org/apache/cordova/CordovaUriHelper.java
+++ b/framework/src/org/apache/cordova/CordovaUriHelper.java
@@@ -19,10 -19,13 +19,13 @@@
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 {
+public class CordovaUriHelper {
private static final String TAG = "CordovaUriHelper";
@@@ -43,7 -46,8 +46,8 @@@
* @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) {
+ public boolean shouldOverrideUrlLoading(String url) {
// The WebView should support http and https when going on the Internet
if(url.startsWith("http:") || url.startsWith("https:"))
{
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/test/assets/www/error.html
----------------------------------------------------------------------
diff --cc test/assets/www/error.html
index 0000000,0000000..aad167d
new file mode 100644
--- /dev/null
+++ b/test/assets/www/error.html
@@@ -1,0 -1,0 +1,8 @@@
++<html>
++ <head>
++ <title>OH NOES!</title>
++ </head>
++ <body>
++ <h1>Things went terribly wrong!</h1>
++ </body>
++</html>
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/a7ccb924/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
----------------------------------------------------------------------
diff --cc test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
index 6f96e83,1c1789e..b143521
--- a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
+++ b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
@@@ -22,7 -22,8 +22,9 @@@ package org.apache.cordova.test
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
++import org.apache.cordova.AndroidChromeClient;
++import org.apache.cordova.AndroidWebViewClient;
import org.apache.cordova.Config;
-import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
@@@ -45,10 -47,12 +47,11 @@@ public class CordovaWebViewTestActivit
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);
- cordovaWebView.init(this,
- Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
+
+ cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
- cordovaWebView.init(this, new CordovaWebViewClient(this, cordovaWebView), new CordovaChromeClient(this, cordovaWebView),
- Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
++ cordovaWebView.init(this, Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
cordovaWebView.loadUrl("file:///android_asset/www/index.html");