You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/07/04 05:02:48 UTC
[7/8] Merge branch 'master' into 4.0.x (Bridge fixes)
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4ca23056/framework/src/org/apache/cordova/CordovaChromeClient.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/CordovaChromeClient.java
index 847a466,f2c3350..87177b4
mode 100644,100755..100644
--- a/framework/src/org/apache/cordova/CordovaChromeClient.java
+++ b/framework/src/org/apache/cordova/CordovaChromeClient.java
@@@ -18,15 -18,391 +18,10 @@@
*/
package org.apache.cordova;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.LOG;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.annotation.TargetApi;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
import android.net.Uri;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.webkit.ConsoleMessage;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.GeolocationPermissions.Callback;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-
-/**
- * This class is the WebChromeClient that implements callbacks for our web view.
- * The kind of callbacks that happen here are on the chrome outside the document,
- * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
- * to but different than CordovaWebViewClient.
- *
- * @see <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html">WebChromeClient</a>
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see CordovaWebViewClient
- * @see CordovaWebView
- */
-public class CordovaChromeClient extends WebChromeClient {
-
- public static final int FILECHOOSER_RESULTCODE = 5173;
- private static final String LOG_TAG = "CordovaChromeClient";
- private String TAG = "CordovaLog";
- private long MAX_QUOTA = 100 * 1024 * 1024;
- protected CordovaInterface cordova;
- protected CordovaWebView appView;
-
- // the video progress view
- private View mVideoProgressView;
-
- // File Chooser
- public ValueCallback<Uri> mUploadMessage;
-
- /**
- * Constructor.
- *
- * @param cordova
- */
- public CordovaChromeClient(CordovaInterface cordova) {
- this.cordova = cordova;
- }
-
- /**
- * Constructor.
- *
- * @param ctx
- * @param app
- */
- public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
- this.cordova = ctx;
- this.appView = app;
- }
-
- /**
- * Constructor.
- *
- * @param view
- */
- public void setWebView(CordovaWebView view) {
- this.appView = view;
- }
-
- /**
- * Tell the client to display a javascript alert dialog.
- *
- * @param view
- * @param url
- * @param message
- * @param result
- * @see Other implementation in the Dialogs plugin.
- */
- @Override
- public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
- AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
- dlg.setMessage(message);
- dlg.setTitle("Alert");
- //Don't let alerts break the back button
- dlg.setCancelable(true);
- dlg.setPositiveButton(android.R.string.ok,
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.confirm();
- }
- });
- dlg.setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- result.cancel();
- }
- });
- dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
- //DO NOTHING
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK)
- {
- result.confirm();
- return false;
- }
- else
- return true;
- }
- });
- dlg.show();
- return true;
- }
-
- /**
- * Tell the client to display a confirm dialog to the user.
- *
- * @param view
- * @param url
- * @param message
- * @param result
- * @see Other implementation in the Dialogs plugin.
- */
- @Override
- public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
- AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
- dlg.setMessage(message);
- dlg.setTitle("Confirm");
- dlg.setCancelable(true);
- dlg.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.confirm();
- }
- });
- dlg.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.cancel();
- }
- });
- dlg.setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- result.cancel();
- }
- });
- dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
- //DO NOTHING
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK)
- {
- result.cancel();
- return false;
- }
- else
- return true;
- }
- });
- dlg.show();
- return true;
- }
-
- /**
- * Tell the client to display a prompt dialog to the user.
- * If the client returns true, WebView will assume that the client will
- * handle the prompt dialog and call the appropriate JsPromptResult method.
- *
- * Since we are hacking prompts for our own purposes, we should not be using them for
- * this purpose, perhaps we should hack console.log to do this instead!
- *
- * @see Other implementation in the Dialogs plugin.
- */
- @Override
- public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, JsPromptResult result) {
- // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread.
- if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
- JSONArray array;
- try {
- array = new JSONArray(defaultValue.substring(4));
- int bridgeSecret = array.getInt(0);
- String service = array.getString(1);
- String action = array.getString(2);
- String callbackId = array.getString(3);
- String r = appView.exposedJsApi.exec(bridgeSecret, service, action, callbackId, message);
- result.confirm(r == null ? "" : r);
- } catch (JSONException e) {
- e.printStackTrace();
- result.cancel();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- result.cancel();
- }
- }
-
- // Sets the native->JS bridge mode.
- else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
- try {
- int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
- appView.exposedJsApi.setNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
- result.cancel();
- } catch (NumberFormatException e){
- e.printStackTrace();
- result.cancel();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- result.cancel();
- }
- }
-
- // Polling for JavaScript messages
- else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
- int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
- try {
- String r = appView.exposedJsApi.retrieveJsMessages(bridgeSecret, "1".equals(message));
- result.confirm(r == null ? "" : r);
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- result.cancel();
- }
- }
-
- else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
- String startUrl = Config.getStartUrl();
- // 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") && startUrl.startsWith(origin))) {
- // Enable the bridge
- int bridgeMode = Integer.parseInt(defaultValue.substring(9));
- appView.jsMessageQueue.setBridgeMode(bridgeMode);
- // Tell JS the bridge secret.
- int secret = appView.exposedJsApi.generateBridgeSecret();
- result.confirm(""+secret);
- } else {
- Log.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
- result.cancel();
- }
- } else {
- // Returning false would also show a dialog, but the default one shows the origin (ugly).
- final JsPromptResult res = result;
- AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
- dlg.setMessage(message);
- final EditText input = new EditText(this.cordova.getActivity());
- if (defaultValue != null) {
- input.setText(defaultValue);
- }
- dlg.setView(input);
- dlg.setCancelable(false);
- dlg.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String usertext = input.getText().toString();
- res.confirm(usertext);
- }
- });
- dlg.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- res.cancel();
- }
- });
- dlg.show();
- }
- return true;
- }
-
- /**
- * Handle database quota exceeded notification.
- */
- @Override
- public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
- long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
- {
- LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
- quotaUpdater.updateQuota(MAX_QUOTA);
- }
-
- // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
- // Expect this to not compile in a future Android release!
- @SuppressWarnings("deprecation")
- @Override
- public void onConsoleMessage(String message, int lineNumber, String sourceID)
- {
- //This is only for Android 2.1
- if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1)
- {
- LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
- super.onConsoleMessage(message, lineNumber, sourceID);
- }
- }
-
- @TargetApi(8)
- @Override
- public boolean onConsoleMessage(ConsoleMessage consoleMessage)
- {
- if (consoleMessage.message() != null)
- LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
- return super.onConsoleMessage(consoleMessage);
- }
-
- @Override
- /**
- * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
- *
- * @param origin
- * @param callback
- */
- public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
- super.onGeolocationPermissionsShowPrompt(origin, callback);
- callback.invoke(origin, true, false);
- }
-
- // API level 7 is required for this, see if we could lower this using something else
- @Override
- public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- this.appView.showCustomView(view, callback);
- }
-
- @Override
- public void onHideCustomView() {
- this.appView.hideCustomView();
- }
-
- @Override
- /**
- * Ask the host application for a custom progress view to show while
- * a <video> is loading.
- * @return View The progress view.
- */
- public View getVideoLoadingProgressView() {
-
- if (mVideoProgressView == null) {
- // Create a new Loading view programmatically.
-
- // create the linear layout
- LinearLayout layout = new LinearLayout(this.appView.getContext());
- layout.setOrientation(LinearLayout.VERTICAL);
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- layout.setLayoutParams(layoutParams);
- // the proress bar
- ProgressBar bar = new ProgressBar(this.appView.getContext());
- LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- barLayoutParams.gravity = Gravity.CENTER;
- bar.setLayoutParams(barLayoutParams);
- layout.addView(bar);
-
- mVideoProgressView = layout;
- }
- return mVideoProgressView;
- }
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg) {
- this.openFileChooser(uploadMsg, "*/*");
- }
- public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
- this.openFileChooser(uploadMsg, acceptType, null);
- }
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
- {
- mUploadMessage = uploadMsg;
- Intent i = new Intent(Intent.ACTION_GET_CONTENT);
- i.addCategory(Intent.CATEGORY_OPENABLE);
- i.setType("*/*");
- this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
- FILECHOOSER_RESULTCODE);
- }
-
- public ValueCallback<Uri> getValueCallback() {
- return this.mUploadMessage;
- }
+public interface CordovaChromeClient {
-
- int FILECHOOSER_RESULTCODE = 0;
-
+ void setWebView(CordovaWebView appView);
-
+ ValueCallback<Uri> getValueCallback();
-
}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4ca23056/framework/src/org/apache/cordova/CordovaUriHelper.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4ca23056/framework/src/org/apache/cordova/ExposedJsApi.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/ExposedJsApi.java
index d0f8abf,97f6038..b84fcfb
mode 100644,100755..100644
--- a/framework/src/org/apache/cordova/ExposedJsApi.java
+++ b/framework/src/org/apache/cordova/ExposedJsApi.java
@@@ -1,17 -1,98 +1,12 @@@
-/*
- 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 android.webkit.JavascriptInterface;
-
-import org.apache.cordova.PluginManager;
import org.json.JSONException;
- import android.webkit.JavascriptInterface;
-
-/**
- * Contains APIs that the JS can call. All functions in here should also have
- * an equivalent entry in CordovaChromeClient.java, and be added to
- * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
+/*
+ * Any exposed Javascript API MUST implement these three things!
*/
-
-/* package */ class ExposedJsApi {
-
- private PluginManager pluginManager;
- private NativeToJsMessageQueue jsMessageQueue;
- private volatile int bridgeSecret = -1; // written by UI thread, read by JS thread.
-
- public ExposedJsApi(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
- this.pluginManager = pluginManager;
- this.jsMessageQueue = jsMessageQueue;
- }
-
- @JavascriptInterface
- public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
- verifySecret(bridgeSecret);
- // If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666.
- // We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string.
- if (arguments == null) {
- return "@Null arguments.";
- }
-
- jsMessageQueue.setPaused(true);
- try {
- // Tell the resourceApi what thread the JS is running on.
- CordovaResourceApi.jsThread = Thread.currentThread();
-
- pluginManager.exec(service, action, callbackId, arguments);
- String ret = "";
- if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
- ret = jsMessageQueue.popAndEncode(false);
- }
- return ret;
- } catch (Throwable e) {
- e.printStackTrace();
- return "";
- } finally {
- jsMessageQueue.setPaused(false);
- }
- }
-
- @JavascriptInterface
- public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
- verifySecret(bridgeSecret);
- jsMessageQueue.setBridgeMode(value);
- }
-
- @JavascriptInterface
- public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
- verifySecret(bridgeSecret);
- return jsMessageQueue.popAndEncode(fromOnlineEvent);
- }
-
- private void verifySecret(int value) throws IllegalAccessException {
- if (bridgeSecret < 0 || value != bridgeSecret) {
- throw new IllegalAccessException();
- }
- }
-
- /** Called on page transitions */
- void clearBridgeSecret() {
- bridgeSecret = -1;
- }
-
- /** Called by cordova.js to initialize the bridge. */
- int generateBridgeSecret() {
- bridgeSecret = (int)(Math.random() * Integer.MAX_VALUE);
- return bridgeSecret;
- }
+public interface ExposedJsApi {
-
- @JavascriptInterface
- public String exec(String service, String action, String callbackId, String arguments) throws JSONException;
- public void setNativeToJsBridgeMode(int value);
- public String retrieveJsMessages(boolean fromOnlineEvent);
++ public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException;
++ public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException;
++ public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException;
}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4ca23056/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
index 2501c98,67793d7..3c6ad21
--- a/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
+++ b/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
@@@ -32,9 -32,10 +32,10 @@@ import android.webkit.WebResourceRespon
import android.webkit.WebView;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
+public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{
private static final String TAG = "IceCreamCordovaWebViewClient";
+ private CordovaUriHelper helper;
public IceCreamCordovaWebViewClient(CordovaInterface cordova) {
super(cordova);
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4ca23056/framework/src/org/apache/cordova/PluginManager.java
----------------------------------------------------------------------
diff --cc framework/src/org/apache/cordova/PluginManager.java
index 50fe6b7,02536ba..c8cecf2
--- a/framework/src/org/apache/cordova/PluginManager.java
+++ b/framework/src/org/apache/cordova/PluginManager.java
@@@ -65,10 -63,6 +62,8 @@@ public class PluginManager
// Using <url-filter> is deprecated.
protected HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
- private AtomicInteger numPendingUiExecs;
-
+ private Set<String> pluginIdWhitelist;
+
/**
* Constructor.
*
@@@ -79,12 -73,7 +74,11 @@@
this.ctx = ctx;
this.app = app;
this.firstRun = true;
- this.numPendingUiExecs = new AtomicInteger(0);
}
+
+ public void setPluginIdWhitelist(Set<String> pluginIdWhitelist) {
+ this.pluginIdWhitelist = pluginIdWhitelist;
+ }
/**
* Init when loading a new HTML page into webview.