You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2017/05/01 21:17:30 UTC
[48/63] [abbrv] cordova-lib git commit: CB-11242: updated tests and
fixtures
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
new file mode 100644
index 0000000..9459a11
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
@@ -0,0 +1,182 @@
+/*
+ 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.security.SecureRandom;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+/**
+ * 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
+ */
+public class CordovaBridge {
+ private static final String LOG_TAG = "CordovaBridge";
+ private PluginManager pluginManager;
+ private NativeToJsMessageQueue jsMessageQueue;
+ private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
+
+ public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
+ this.pluginManager = pluginManager;
+ this.jsMessageQueue = jsMessageQueue;
+ }
+
+ public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
+ if (!verifySecret("exec()", bridgeSecret)) {
+ return null;
+ }
+ // 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 = null;
+ if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
+ ret = jsMessageQueue.popAndEncode(false);
+ }
+ return ret;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ return "";
+ } finally {
+ jsMessageQueue.setPaused(false);
+ }
+ }
+
+ public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
+ if (!verifySecret("setNativeToJsBridgeMode()", bridgeSecret)) {
+ return;
+ }
+ jsMessageQueue.setBridgeMode(value);
+ }
+
+ public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
+ if (!verifySecret("retrieveJsMessages()", bridgeSecret)) {
+ return null;
+ }
+ return jsMessageQueue.popAndEncode(fromOnlineEvent);
+ }
+
+ private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
+ if (!jsMessageQueue.isBridgeEnabled()) {
+ if (bridgeSecret == -1) {
+ LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
+ } else {
+ LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
+ }
+ return false;
+ }
+ // 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;
+ }
+
+ /** Called on page transitions */
+ void clearBridgeSecret() {
+ expectedBridgeSecret = -1;
+ }
+
+ public boolean isSecretEstablished() {
+ return expectedBridgeSecret != -1;
+ }
+
+ /** Called by cordova.js to initialize the bridge. */
+ int generateBridgeSecret() {
+ SecureRandom randGen = new SecureRandom();
+ expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
+ return expectedBridgeSecret;
+ }
+
+ public void reset() {
+ jsMessageQueue.reset();
+ clearBridgeSecret();
+ }
+
+ public String promptOnJsPrompt(String origin, String message, String defaultValue) {
+ 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 = jsExec(bridgeSecret, service, action, callbackId, message);
+ return r == null ? "" : r;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+ // Sets the native->JS bridge mode.
+ else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
+ try {
+ int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
+ jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
+ } catch (NumberFormatException e){
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+ // Polling for JavaScript messages
+ else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
+ int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
+ try {
+ String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
+ return r == null ? "" : r;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+ else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
+ // Protect against random iframes being able to talk through the bridge.
+ // Trust only pages which the app would have been allowed to navigate to anyway.
+ if (pluginManager.shouldAllowBridgeAccess(origin)) {
+ // Enable the bridge
+ int bridgeMode = Integer.parseInt(defaultValue.substring(9));
+ jsMessageQueue.setBridgeMode(bridgeMode);
+ // Tell JS the bridge secret.
+ int secret = generateBridgeSecret();
+ return ""+secret;
+ } else {
+ LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
+ }
+ return "";
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
new file mode 100644
index 0000000..5dd0eca
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
@@ -0,0 +1,96 @@
+/*
+ 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.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import android.webkit.ClientCertRequest;
+
+/**
+ * Implementation of the ICordovaClientCertRequest for Android WebView.
+ */
+public class CordovaClientCertRequest implements ICordovaClientCertRequest {
+
+ private final ClientCertRequest request;
+
+ public CordovaClientCertRequest(ClientCertRequest request) {
+ this.request = request;
+ }
+
+ /**
+ * Cancel this request
+ */
+ public void cancel()
+ {
+ request.cancel();
+ }
+
+ /*
+ * Returns the host name of the server requesting the certificate.
+ */
+ public String getHost()
+ {
+ return request.getHost();
+ }
+
+ /*
+ * Returns the acceptable types of asymmetric keys (can be null).
+ */
+ public String[] getKeyTypes()
+ {
+ return request.getKeyTypes();
+ }
+
+ /*
+ * Returns the port number of the server requesting the certificate.
+ */
+ public int getPort()
+ {
+ return request.getPort();
+ }
+
+ /*
+ * Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
+ */
+ public Principal[] getPrincipals()
+ {
+ return request.getPrincipals();
+ }
+
+ /*
+ * Ignore the request for now. Do not remember user's choice.
+ */
+ public void ignore()
+ {
+ request.ignore();
+ }
+
+ /*
+ * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
+ *
+ * @param privateKey The privateKey
+ * @param chain The certificate chain
+ */
+ public void proceed(PrivateKey privateKey, X509Certificate[] chain)
+ {
+ request.proceed(privateKey, chain);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
new file mode 100644
index 0000000..a219c99
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
@@ -0,0 +1,152 @@
+/*
+ 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+/**
+ * Helper class for WebViews to implement prompt(), alert(), confirm() dialogs.
+ */
+public class CordovaDialogsHelper {
+ private final Context context;
+ private AlertDialog lastHandledDialog;
+
+ public CordovaDialogsHelper(Context context) {
+ this.context = context;
+ }
+
+ public void showAlert(String message, final Result result) {
+ AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+ 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.gotResult(true, null);
+ }
+ });
+ dlg.setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ result.gotResult(false, null);
+ }
+ });
+ dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+ //DO NOTHING
+ public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ result.gotResult(true, null);
+ return false;
+ }
+ else
+ return true;
+ }
+ });
+ lastHandledDialog = dlg.show();
+ }
+
+ public void showConfirm(String message, final Result result) {
+ AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+ 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.gotResult(true, null);
+ }
+ });
+ dlg.setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ result.gotResult(false, null);
+ }
+ });
+ dlg.setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ result.gotResult(false, null);
+ }
+ });
+ dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+ //DO NOTHING
+ public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ result.gotResult(false, null);
+ return false;
+ }
+ else
+ return true;
+ }
+ });
+ lastHandledDialog = dlg.show();
+ }
+
+ /**
+ * 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!
+ */
+ public void showPrompt(String message, String defaultValue, final Result result) {
+ // Returning false would also show a dialog, but the default one shows the origin (ugly).
+ AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+ dlg.setMessage(message);
+ final EditText input = new EditText(context);
+ 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();
+ result.gotResult(true, userText);
+ }
+ });
+ dlg.setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ result.gotResult(false, null);
+ }
+ });
+ lastHandledDialog = dlg.show();
+ }
+
+ public void destroyLastDialog(){
+ if (lastHandledDialog != null){
+ lastHandledDialog.cancel();
+ }
+ }
+
+ public interface Result {
+ public void gotResult(boolean success, String value);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
new file mode 100644
index 0000000..724381e
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
@@ -0,0 +1,51 @@
+/*
+ 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.HttpAuthHandler;
+
+/**
+ * Specifies interface for HTTP auth handler object which is used to handle auth requests and
+ * specifying user credentials.
+ */
+public class CordovaHttpAuthHandler implements ICordovaHttpAuthHandler {
+
+ private final HttpAuthHandler handler;
+
+ public CordovaHttpAuthHandler(HttpAuthHandler handler) {
+ this.handler = handler;
+ }
+
+ /**
+ * Instructs the WebView to cancel the authentication request.
+ */
+ public void cancel () {
+ this.handler.cancel();
+ }
+
+ /**
+ * Instructs the WebView to proceed with the authentication with the given credentials.
+ *
+ * @param username
+ * @param password
+ */
+ public void proceed (String username, String password) {
+ this.handler.proceed(username, password);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
new file mode 100755
index 0000000..3b8468f
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
@@ -0,0 +1,88 @@
+/*
+ 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.app.Activity;
+import android.content.Intent;
+
+import org.apache.cordova.CordovaPlugin;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * The Activity interface that is implemented by CordovaActivity.
+ * It is used to isolate plugin development, and remove dependency on entire Cordova library.
+ */
+public interface CordovaInterface {
+
+ /**
+ * Launch an activity for which you would like a result when it finished. When this activity exits,
+ * your onActivityResult() method will be called.
+ *
+ * @param command The command object
+ * @param intent The intent to start
+ * @param requestCode The request code that is passed to callback to identify the activity
+ */
+ abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode);
+
+ /**
+ * Set the plugin to be called when a sub-activity exits.
+ *
+ * @param plugin The plugin on which onActivityResult is to be called
+ */
+ abstract public void setActivityResultCallback(CordovaPlugin plugin);
+
+ /**
+ * Get the Android activity.
+ *
+ * @return the Activity
+ */
+ public abstract Activity getActivity();
+
+
+ /**
+ * Called when a message is sent to plugin.
+ *
+ * @param id The message id
+ * @param data The message data
+ * @return Object or null
+ */
+ public Object onMessage(String id, Object data);
+
+ /**
+ * Returns a shared thread pool that can be used for background tasks.
+ */
+ public ExecutorService getThreadPool();
+
+ /**
+ * Sends a permission request to the activity for one permission.
+ */
+ public void requestPermission(CordovaPlugin plugin, int requestCode, String permission);
+
+ /**
+ * Sends a permission request to the activity for a group of permissions
+ */
+ public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions);
+
+ /**
+ * Check for a permission. Returns true if the permission is granted, false otherwise.
+ */
+ public boolean hasPermission(String permission);
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
new file mode 100644
index 0000000..71dcb78
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
@@ -0,0 +1,241 @@
+/*
+ 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.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Pair;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Default implementation of CordovaInterface.
+ */
+public class CordovaInterfaceImpl implements CordovaInterface {
+ private static final String TAG = "CordovaInterfaceImpl";
+ protected Activity activity;
+ protected ExecutorService threadPool;
+ protected PluginManager pluginManager;
+
+ protected ActivityResultHolder savedResult;
+ protected CallbackMap permissionResultCallbacks;
+ protected CordovaPlugin activityResultCallback;
+ protected String initCallbackService;
+ protected int activityResultRequestCode;
+ protected boolean activityWasDestroyed = false;
+ protected Bundle savedPluginState;
+
+ public CordovaInterfaceImpl(Activity activity) {
+ this(activity, Executors.newCachedThreadPool());
+ }
+
+ public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) {
+ this.activity = activity;
+ this.threadPool = threadPool;
+ this.permissionResultCallbacks = new CallbackMap();
+ }
+
+ @Override
+ public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
+ setActivityResultCallback(command);
+ try {
+ activity.startActivityForResult(intent, requestCode);
+ } catch (RuntimeException e) { // E.g.: ActivityNotFoundException
+ activityResultCallback = null;
+ throw e;
+ }
+ }
+
+ @Override
+ public void setActivityResultCallback(CordovaPlugin plugin) {
+ // Cancel any previously pending activity.
+ if (activityResultCallback != null) {
+ activityResultCallback.onActivityResult(activityResultRequestCode, Activity.RESULT_CANCELED, null);
+ }
+ activityResultCallback = plugin;
+ }
+
+ @Override
+ public Activity getActivity() {
+ return activity;
+ }
+
+ @Override
+ public Object onMessage(String id, Object data) {
+ if ("exit".equals(id)) {
+ activity.finish();
+ }
+ return null;
+ }
+
+ @Override
+ public ExecutorService getThreadPool() {
+ return threadPool;
+ }
+
+ /**
+ * Dispatches any pending onActivityResult callbacks and sends the resume event if the
+ * Activity was destroyed by the OS.
+ */
+ public void onCordovaInit(PluginManager pluginManager) {
+ this.pluginManager = pluginManager;
+ if (savedResult != null) {
+ onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent);
+ } else if(activityWasDestroyed) {
+ // If there was no Activity result, we still need to send out the resume event if the
+ // Activity was destroyed by the OS
+ activityWasDestroyed = false;
+ if(pluginManager != null)
+ {
+ CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
+ if(appPlugin != null) {
+ JSONObject obj = new JSONObject();
+ try {
+ obj.put("action", "resume");
+ } catch (JSONException e) {
+ LOG.e(TAG, "Failed to create event message", e);
+ }
+ appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, obj));
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Routes the result to the awaiting plugin. Returns false if no plugin was waiting.
+ */
+ public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
+ CordovaPlugin callback = activityResultCallback;
+ if(callback == null && initCallbackService != null) {
+ // The application was restarted, but had defined an initial callback
+ // before being shut down.
+ savedResult = new ActivityResultHolder(requestCode, resultCode, intent);
+ if (pluginManager != null) {
+ callback = pluginManager.getPlugin(initCallbackService);
+ if(callback != null) {
+ callback.onRestoreStateForActivityResult(savedPluginState.getBundle(callback.getServiceName()),
+ new ResumeCallback(callback.getServiceName(), pluginManager));
+ }
+ }
+ }
+ activityResultCallback = null;
+
+ if (callback != null) {
+ LOG.d(TAG, "Sending activity result to plugin");
+ initCallbackService = null;
+ savedResult = null;
+ callback.onActivityResult(requestCode, resultCode, intent);
+ return true;
+ }
+ LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : "."));
+ return false;
+ }
+
+ /**
+ * Call this from your startActivityForResult() overload. This is required to catch the case
+ * where plugins use Activity.startActivityForResult() + CordovaInterface.setActivityResultCallback()
+ * rather than CordovaInterface.startActivityForResult().
+ */
+ public void setActivityResultRequestCode(int requestCode) {
+ activityResultRequestCode = requestCode;
+ }
+
+ /**
+ * Saves parameters for startActivityForResult().
+ */
+ public void onSaveInstanceState(Bundle outState) {
+ if (activityResultCallback != null) {
+ String serviceName = activityResultCallback.getServiceName();
+ outState.putString("callbackService", serviceName);
+ }
+ if(pluginManager != null){
+ outState.putBundle("plugin", pluginManager.onSaveInstanceState());
+ }
+
+ }
+
+ /**
+ * Call this from onCreate() so that any saved startActivityForResult parameters will be restored.
+ */
+ public void restoreInstanceState(Bundle savedInstanceState) {
+ initCallbackService = savedInstanceState.getString("callbackService");
+ savedPluginState = savedInstanceState.getBundle("plugin");
+ activityWasDestroyed = true;
+ }
+
+ private static class ActivityResultHolder {
+ private int requestCode;
+ private int resultCode;
+ private Intent intent;
+
+ public ActivityResultHolder(int requestCode, int resultCode, Intent intent) {
+ this.requestCode = requestCode;
+ this.resultCode = resultCode;
+ this.intent = intent;
+ }
+ }
+
+ /**
+ * Called by the system when the user grants permissions
+ *
+ * @param requestCode
+ * @param permissions
+ * @param grantResults
+ */
+ public void onRequestPermissionResult(int requestCode, String[] permissions,
+ int[] grantResults) throws JSONException {
+ Pair<CordovaPlugin, Integer> callback = permissionResultCallbacks.getAndRemoveCallback(requestCode);
+ if(callback != null) {
+ callback.first.onRequestPermissionResult(callback.second, permissions, grantResults);
+ }
+ }
+
+ public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
+ String[] permissions = new String [1];
+ permissions[0] = permission;
+ requestPermissions(plugin, requestCode, permissions);
+ }
+
+ public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) {
+ int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode);
+ getActivity().requestPermissions(permissions, mappedRequestCode);
+ }
+
+ public boolean hasPermission(String permission)
+ {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ {
+ int result = activity.checkSelfPermission(permission);
+ return PackageManager.PERMISSION_GRANTED == result;
+ }
+ else
+ {
+ return true;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
new file mode 100644
index 0000000..41af1db
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
@@ -0,0 +1,422 @@
+/*
+ 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 org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CallbackContext;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Plugins must extend this class and override one of the execute methods.
+ */
+public class CordovaPlugin {
+ public CordovaWebView webView;
+ public CordovaInterface cordova;
+ protected CordovaPreferences preferences;
+ private String serviceName;
+
+ /**
+ * Call this after constructing to initialize the plugin.
+ * Final because we want to be able to change args without breaking plugins.
+ */
+ public final void privateInitialize(String serviceName, CordovaInterface cordova, CordovaWebView webView, CordovaPreferences preferences) {
+ assert this.cordova == null;
+ this.serviceName = serviceName;
+ this.cordova = cordova;
+ this.webView = webView;
+ this.preferences = preferences;
+ initialize(cordova, webView);
+ pluginInitialize();
+ }
+
+ /**
+ * Called after plugin construction and fields have been initialized.
+ * Prefer to use pluginInitialize instead since there is no value in
+ * having parameters on the initialize() function.
+ */
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ }
+
+ /**
+ * Called after plugin construction and fields have been initialized.
+ */
+ protected void pluginInitialize() {
+ }
+
+ /**
+ * Returns the plugin's service name (what you'd use when calling pluginManger.getPlugin())
+ */
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ /**
+ * Executes the request.
+ *
+ * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+ * cordova.getThreadPool().execute(runnable);
+ *
+ * To run on the UI thread, use:
+ * cordova.getActivity().runOnUiThread(runnable);
+ *
+ * @param action The action to execute.
+ * @param rawArgs The exec() arguments in JSON form.
+ * @param callbackContext The callback context used when calling back into JavaScript.
+ * @return Whether the action was valid.
+ */
+ public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
+ JSONArray args = new JSONArray(rawArgs);
+ return execute(action, args, callbackContext);
+ }
+
+ /**
+ * Executes the request.
+ *
+ * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+ * cordova.getThreadPool().execute(runnable);
+ *
+ * To run on the UI thread, use:
+ * cordova.getActivity().runOnUiThread(runnable);
+ *
+ * @param action The action to execute.
+ * @param args The exec() arguments.
+ * @param callbackContext The callback context used when calling back into JavaScript.
+ * @return Whether the action was valid.
+ */
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ CordovaArgs cordovaArgs = new CordovaArgs(args);
+ return execute(action, cordovaArgs, callbackContext);
+ }
+
+ /**
+ * Executes the request.
+ *
+ * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+ * cordova.getThreadPool().execute(runnable);
+ *
+ * To run on the UI thread, use:
+ * cordova.getActivity().runOnUiThread(runnable);
+ *
+ * @param action The action to execute.
+ * @param args The exec() arguments, wrapped with some Cordova helpers.
+ * @param callbackContext The callback context used when calling back into JavaScript.
+ * @return Whether the action was valid.
+ */
+ public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
+ return false;
+ }
+
+ /**
+ * Called when the system is about to start resuming a previous activity.
+ *
+ * @param multitasking Flag indicating if multitasking is turned on for app
+ */
+ public void onPause(boolean multitasking) {
+ }
+
+ /**
+ * Called when the activity will start interacting with the user.
+ *
+ * @param multitasking Flag indicating if multitasking is turned on for app
+ */
+ public void onResume(boolean multitasking) {
+ }
+
+ /**
+ * Called when the activity is becoming visible to the user.
+ */
+ public void onStart() {
+ }
+
+ /**
+ * Called when the activity is no longer visible to the user.
+ */
+ public void onStop() {
+ }
+
+ /**
+ * Called when the activity receives a new intent.
+ */
+ public void onNewIntent(Intent intent) {
+ }
+
+ /**
+ * The final call you receive before your activity is destroyed.
+ */
+ public void onDestroy() {
+ }
+
+ /**
+ * Called when the Activity is being destroyed (e.g. if a plugin calls out to an external
+ * Activity and the OS kills the CordovaActivity in the background). The plugin should save its
+ * state in this method only if it is awaiting the result of an external Activity and needs
+ * to preserve some information so as to handle that result; onRestoreStateForActivityResult()
+ * will only be called if the plugin is the recipient of an Activity result
+ *
+ * @return Bundle containing the state of the plugin or null if state does not need to be saved
+ */
+ public Bundle onSaveInstanceState() {
+ return null;
+ }
+
+ /**
+ * Called when a plugin is the recipient of an Activity result after the CordovaActivity has
+ * been destroyed. The Bundle will be the same as the one the plugin returned in
+ * onSaveInstanceState()
+ *
+ * @param state Bundle containing the state of the plugin
+ * @param callbackContext Replacement Context to return the plugin result to
+ */
+ public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {}
+
+ /**
+ * Called when a message is sent to plugin.
+ *
+ * @param id The message id
+ * @param data The message data
+ * @return Object to stop propagation or null
+ */
+ public Object onMessage(String id, Object data) {
+ return null;
+ }
+
+ /**
+ * Called when an activity you launched exits, giving you the requestCode you started it with,
+ * the resultCode it returned, and any additional data from it.
+ *
+ * @param requestCode The request code originally supplied to startActivityForResult(),
+ * allowing you to identify who this result came from.
+ * @param resultCode The integer result code returned by the child activity through its setResult().
+ * @param intent An Intent, which can return result data to the caller (various data can be
+ * attached to Intent "extras").
+ */
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ }
+
+ /**
+ * Hook for blocking the loading of external resources.
+ *
+ * This will be called when the WebView's shouldInterceptRequest wants to
+ * know whether to open a connection to an external resource. Return false
+ * to block the request: if any plugin returns false, Cordova will block
+ * the request. If all plugins return null, the default policy will be
+ * enforced. If at least one plugin returns true, and no plugins return
+ * false, then the request will proceed.
+ *
+ * Note that this only affects resource requests which are routed through
+ * WebViewClient.shouldInterceptRequest, such as XMLHttpRequest requests and
+ * img tag loads. WebSockets and media requests (such as <video> and <audio>
+ * tags) are not affected by this method. Use CSP headers to control access
+ * to such resources.
+ */
+ public Boolean shouldAllowRequest(String url) {
+ return null;
+ }
+
+ /**
+ * Hook for blocking navigation by the Cordova WebView. This applies both to top-level and
+ * iframe navigations.
+ *
+ * This will be called when the WebView's needs to know whether to navigate
+ * to a new page. Return false to block the navigation: if any plugin
+ * returns false, Cordova will block the navigation. If all plugins return
+ * null, the default policy will be enforced. It at least one plugin returns
+ * true, and no plugins return false, then the navigation will proceed.
+ */
+ public Boolean shouldAllowNavigation(String url) {
+ return null;
+ }
+
+ /**
+ * Hook for allowing page to call exec(). By default, this returns the result of
+ * shouldAllowNavigation(). It's generally unsafe to allow untrusted content to be loaded
+ * into a CordovaWebView, even within an iframe, so it's best not to touch this.
+ */
+ public Boolean shouldAllowBridgeAccess(String url) {
+ return shouldAllowNavigation(url);
+ }
+
+ /**
+ * Hook for blocking the launching of Intents by the Cordova application.
+ *
+ * This will be called when the WebView will not navigate to a page, but
+ * could launch an intent to handle the URL. Return false to block this: if
+ * any plugin returns false, Cordova will block the navigation. If all
+ * plugins return null, the default policy will be enforced. If at least one
+ * plugin returns true, and no plugins return false, then the URL will be
+ * opened.
+ */
+ public Boolean shouldOpenExternalUrl(String url) {
+ return null;
+ }
+
+ /**
+ * Allows plugins to handle a link being clicked. Return true here to cancel the navigation.
+ *
+ * @param url The URL that is trying to be loaded in the Cordova webview.
+ * @return Return true to prevent the URL from loading. Default is false.
+ */
+ public boolean onOverrideUrlLoading(String url) {
+ return false;
+ }
+
+ /**
+ * Hook for redirecting requests. Applies to WebView requests as well as requests made by plugins.
+ * To handle the request directly, return a URI in the form:
+ *
+ * cdvplugin://pluginId/...
+ *
+ * And implement handleOpenForRead().
+ * To make this easier, use the toPluginUri() and fromPluginUri() helpers:
+ *
+ * public Uri remapUri(Uri uri) { return toPluginUri(uri); }
+ *
+ * public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
+ * Uri origUri = fromPluginUri(uri);
+ * ...
+ * }
+ */
+ public Uri remapUri(Uri uri) {
+ return null;
+ }
+
+ /**
+ * Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.
+ * Should never return null.
+ * Added in cordova-android@4.0.0
+ */
+ public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
+ throw new FileNotFoundException("Plugin can't handle uri: " + uri);
+ }
+
+ /**
+ * Refer to remapUri()
+ * Added in cordova-android@4.0.0
+ */
+ protected Uri toPluginUri(Uri origUri) {
+ return new Uri.Builder()
+ .scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)
+ .authority(serviceName)
+ .appendQueryParameter("origUri", origUri.toString())
+ .build();
+ }
+
+ /**
+ * Refer to remapUri()
+ * Added in cordova-android@4.0.0
+ */
+ protected Uri fromPluginUri(Uri pluginUri) {
+ return Uri.parse(pluginUri.getQueryParameter("origUri"));
+ }
+
+ /**
+ * Called when the WebView does a top-level navigation or refreshes.
+ *
+ * Plugins should stop any long-running processes and clean up internal state.
+ *
+ * Does nothing by default.
+ */
+ public void onReset() {
+ }
+
+ /**
+ * Called when the system received an HTTP authentication request. Plugin can use
+ * the supplied HttpAuthHandler to process this auth challenge.
+ *
+ * @param view The WebView that is initiating the callback
+ * @param handler The HttpAuthHandler used to set the WebView's response
+ * @param host The host requiring authentication
+ * @param realm The realm for which authentication is required
+ *
+ * @return Returns True if plugin will resolve this auth challenge, otherwise False
+ *
+ */
+ public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
+ return false;
+ }
+
+ /**
+ * Called when he system received an SSL client certificate request. Plugin can use
+ * the supplied ClientCertRequest to process this certificate challenge.
+ *
+ * @param view The WebView that is initiating the callback
+ * @param request The client certificate request
+ *
+ * @return Returns True if plugin will resolve this auth challenge, otherwise False
+ *
+ */
+ public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
+ return false;
+ }
+
+ /**
+ * Called by the system when the device configuration changes while your activity is running.
+ *
+ * @param newConfig The new device configuration
+ */
+ public void onConfigurationChanged(Configuration newConfig) {
+ }
+
+ /**
+ * Called by the Plugin Manager when we need to actually request permissions
+ *
+ * @param requestCode Passed to the activity to track the request
+ *
+ * @return Returns the permission that was stored in the plugin
+ */
+
+ public void requestPermissions(int requestCode) {
+ }
+
+ /*
+ * Called by the WebView implementation to check for geolocation permissions, can be used
+ * by other Java methods in the event that a plugin is using this as a dependency.
+ *
+ * @return Returns true if the plugin has all the permissions it needs to operate.
+ */
+
+ public boolean hasPermisssion() {
+ return true;
+ }
+
+ /**
+ * Called by the system when the user grants permissions
+ *
+ * @param requestCode
+ * @param permissions
+ * @param grantResults
+ */
+ public void onRequestPermissionResult(int requestCode, String[] permissions,
+ int[] grantResults) throws JSONException {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
new file mode 100644
index 0000000..4dbc93e
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
@@ -0,0 +1,101 @@
+/*
+ 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.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.cordova.LOG;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CordovaPreferences {
+ private HashMap<String, String> prefs = new HashMap<String, String>(20);
+ private Bundle preferencesBundleExtras;
+
+ public void setPreferencesBundle(Bundle extras) {
+ preferencesBundleExtras = extras;
+ }
+
+ public void set(String name, String value) {
+ prefs.put(name.toLowerCase(Locale.ENGLISH), value);
+ }
+
+ public void set(String name, boolean value) {
+ set(name, "" + value);
+ }
+
+ public void set(String name, int value) {
+ set(name, "" + value);
+ }
+
+ public void set(String name, double value) {
+ set(name, "" + value);
+ }
+
+ public Map<String, String> getAll() {
+ return prefs;
+ }
+
+ public boolean getBoolean(String name, boolean defaultValue) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ String value = prefs.get(name);
+ if (value != null) {
+ return Boolean.parseBoolean(value);
+ }
+ return defaultValue;
+ }
+
+ // Added in 4.0.0
+ public boolean contains(String name) {
+ return getString(name, null) != null;
+ }
+
+ public int getInteger(String name, int defaultValue) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ String value = prefs.get(name);
+ if (value != null) {
+ // Use Integer.decode() can't handle it if the highest bit is set.
+ return (int)(long)Long.decode(value);
+ }
+ return defaultValue;
+ }
+
+ public double getDouble(String name, double defaultValue) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ String value = prefs.get(name);
+ if (value != null) {
+ return Double.valueOf(value);
+ }
+ return defaultValue;
+ }
+
+ public String getString(String name, String defaultValue) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ String value = prefs.get(name);
+ if (value != null) {
+ return value;
+ }
+ return defaultValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
new file mode 100644
index 0000000..e725e25
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
@@ -0,0 +1,471 @@
+/*
+ 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.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Looper;
+import android.util.Base64;
+import android.webkit.MimeTypeMap;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.util.Locale;
+
+/**
+ * What this class provides:
+ * 1. Helpers for reading & writing to URLs.
+ * - E.g. handles assets, resources, content providers, files, data URIs, http[s]
+ * - E.g. Can be used to query for mime-type & content length.
+ *
+ * 2. To allow plugins to redirect URLs (via remapUrl).
+ * - All plugins should call remapUrl() on URLs they receive from JS *before*
+ * passing the URL onto other utility functions in this class.
+ * - For an example usage of this, refer to the org.apache.cordova.file plugin.
+ *
+ * Future Work:
+ * - Consider using a Cursor to query content URLs for their size (like the file plugin does).
+ * - Allow plugins to remapUri to "cdv-plugin://plugin-name/foo", which CordovaResourceApi
+ * would then delegate to pluginManager.getPlugin(plugin-name).openForRead(url)
+ * - Currently, plugins *can* do this by remapping to a data: URL, but it's inefficient
+ * for large payloads.
+ */
+public class CordovaResourceApi {
+ @SuppressWarnings("unused")
+ private static final String LOG_TAG = "CordovaResourceApi";
+
+ public static final int URI_TYPE_FILE = 0;
+ public static final int URI_TYPE_ASSET = 1;
+ public static final int URI_TYPE_CONTENT = 2;
+ public static final int URI_TYPE_RESOURCE = 3;
+ public static final int URI_TYPE_DATA = 4;
+ public static final int URI_TYPE_HTTP = 5;
+ public static final int URI_TYPE_HTTPS = 6;
+ public static final int URI_TYPE_PLUGIN = 7;
+ public static final int URI_TYPE_UNKNOWN = -1;
+
+ public static final String PLUGIN_URI_SCHEME = "cdvplugin";
+
+ private static final String[] LOCAL_FILE_PROJECTION = { "_data" };
+
+ public static Thread jsThread;
+
+ private final AssetManager assetManager;
+ private final ContentResolver contentResolver;
+ private final PluginManager pluginManager;
+ private boolean threadCheckingEnabled = true;
+
+
+ public CordovaResourceApi(Context context, PluginManager pluginManager) {
+ this.contentResolver = context.getContentResolver();
+ this.assetManager = context.getAssets();
+ this.pluginManager = pluginManager;
+ }
+
+ public void setThreadCheckingEnabled(boolean value) {
+ threadCheckingEnabled = value;
+ }
+
+ public boolean isThreadCheckingEnabled() {
+ return threadCheckingEnabled;
+ }
+
+
+ public static int getUriType(Uri uri) {
+ assertNonRelative(uri);
+ String scheme = uri.getScheme();
+ if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
+ return URI_TYPE_CONTENT;
+ }
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equalsIgnoreCase(scheme)) {
+ return URI_TYPE_RESOURCE;
+ }
+ if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
+ if (uri.getPath().startsWith("/android_asset/")) {
+ return URI_TYPE_ASSET;
+ }
+ return URI_TYPE_FILE;
+ }
+ if ("data".equalsIgnoreCase(scheme)) {
+ return URI_TYPE_DATA;
+ }
+ if ("http".equalsIgnoreCase(scheme)) {
+ return URI_TYPE_HTTP;
+ }
+ if ("https".equalsIgnoreCase(scheme)) {
+ return URI_TYPE_HTTPS;
+ }
+ if (PLUGIN_URI_SCHEME.equalsIgnoreCase(scheme)) {
+ return URI_TYPE_PLUGIN;
+ }
+ return URI_TYPE_UNKNOWN;
+ }
+
+ public Uri remapUri(Uri uri) {
+ assertNonRelative(uri);
+ Uri pluginUri = pluginManager.remapUri(uri);
+ return pluginUri != null ? pluginUri : uri;
+ }
+
+ public String remapPath(String path) {
+ return remapUri(Uri.fromFile(new File(path))).getPath();
+ }
+
+ /**
+ * Returns a File that points to the resource, or null if the resource
+ * is not on the local filesystem.
+ */
+ public File mapUriToFile(Uri uri) {
+ assertBackgroundThread();
+ switch (getUriType(uri)) {
+ case URI_TYPE_FILE:
+ return new File(uri.getPath());
+ case URI_TYPE_CONTENT: {
+ Cursor cursor = contentResolver.query(uri, LOCAL_FILE_PROJECTION, null, null, null);
+ if (cursor != null) {
+ try {
+ int columnIndex = cursor.getColumnIndex(LOCAL_FILE_PROJECTION[0]);
+ if (columnIndex != -1 && cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ String realPath = cursor.getString(columnIndex);
+ if (realPath != null) {
+ return new File(realPath);
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public String getMimeType(Uri uri) {
+ switch (getUriType(uri)) {
+ case URI_TYPE_FILE:
+ case URI_TYPE_ASSET:
+ return getMimeTypeFromPath(uri.getPath());
+ case URI_TYPE_CONTENT:
+ case URI_TYPE_RESOURCE:
+ return contentResolver.getType(uri);
+ case URI_TYPE_DATA: {
+ return getDataUriMimeType(uri);
+ }
+ case URI_TYPE_HTTP:
+ case URI_TYPE_HTTPS: {
+ try {
+ HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
+ conn.setDoInput(false);
+ conn.setRequestMethod("HEAD");
+ String mimeType = conn.getHeaderField("Content-Type");
+ if (mimeType != null) {
+ mimeType = mimeType.split(";")[0];
+ }
+ return mimeType;
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ //This already exists
+ private String getMimeTypeFromPath(String path) {
+ String extension = path;
+ int lastDot = extension.lastIndexOf('.');
+ if (lastDot != -1) {
+ extension = extension.substring(lastDot + 1);
+ }
+ // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
+ extension = extension.toLowerCase(Locale.getDefault());
+ if (extension.equals("3ga")) {
+ return "audio/3gpp";
+ } else if (extension.equals("js")) {
+ // Missing from the map :(.
+ return "text/javascript";
+ }
+ return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ }
+
+ /**
+ * Opens a stream to the given URI, also providing the MIME type & length.
+ * @return Never returns null.
+ * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+ * resolved before being passed into this function.
+ * @throws Throws an IOException if the URI cannot be opened.
+ * @throws Throws an IllegalStateException if called on a foreground thread.
+ */
+ public OpenForReadResult openForRead(Uri uri) throws IOException {
+ return openForRead(uri, false);
+ }
+
+ /**
+ * Opens a stream to the given URI, also providing the MIME type & length.
+ * @return Never returns null.
+ * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+ * resolved before being passed into this function.
+ * @throws Throws an IOException if the URI cannot be opened.
+ * @throws Throws an IllegalStateException if called on a foreground thread and skipThreadCheck is false.
+ */
+ public OpenForReadResult openForRead(Uri uri, boolean skipThreadCheck) throws IOException {
+ if (!skipThreadCheck) {
+ assertBackgroundThread();
+ }
+ switch (getUriType(uri)) {
+ case URI_TYPE_FILE: {
+ FileInputStream inputStream = new FileInputStream(uri.getPath());
+ String mimeType = getMimeTypeFromPath(uri.getPath());
+ long length = inputStream.getChannel().size();
+ return new OpenForReadResult(uri, inputStream, mimeType, length, null);
+ }
+ case URI_TYPE_ASSET: {
+ String assetPath = uri.getPath().substring(15);
+ AssetFileDescriptor assetFd = null;
+ InputStream inputStream;
+ long length = -1;
+ try {
+ assetFd = assetManager.openFd(assetPath);
+ inputStream = assetFd.createInputStream();
+ length = assetFd.getLength();
+ } catch (FileNotFoundException e) {
+ // Will occur if the file is compressed.
+ inputStream = assetManager.open(assetPath);
+ }
+ String mimeType = getMimeTypeFromPath(assetPath);
+ return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
+ }
+ case URI_TYPE_CONTENT:
+ case URI_TYPE_RESOURCE: {
+ String mimeType = contentResolver.getType(uri);
+ AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, "r");
+ InputStream inputStream = assetFd.createInputStream();
+ long length = assetFd.getLength();
+ return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
+ }
+ case URI_TYPE_DATA: {
+ OpenForReadResult ret = readDataUri(uri);
+ if (ret == null) {
+ break;
+ }
+ return ret;
+ }
+ case URI_TYPE_HTTP:
+ case URI_TYPE_HTTPS: {
+ HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
+ conn.setDoInput(true);
+ String mimeType = conn.getHeaderField("Content-Type");
+ if (mimeType != null) {
+ mimeType = mimeType.split(";")[0];
+ }
+ int length = conn.getContentLength();
+ InputStream inputStream = conn.getInputStream();
+ return new OpenForReadResult(uri, inputStream, mimeType, length, null);
+ }
+ case URI_TYPE_PLUGIN: {
+ String pluginId = uri.getHost();
+ CordovaPlugin plugin = pluginManager.getPlugin(pluginId);
+ if (plugin == null) {
+ throw new FileNotFoundException("Invalid plugin ID in URI: " + uri);
+ }
+ return plugin.handleOpenForRead(uri);
+ }
+ }
+ throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
+ }
+
+ public OutputStream openOutputStream(Uri uri) throws IOException {
+ return openOutputStream(uri, false);
+ }
+
+ /**
+ * Opens a stream to the given URI.
+ * @return Never returns null.
+ * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+ * resolved before being passed into this function.
+ * @throws Throws an IOException if the URI cannot be opened.
+ */
+ public OutputStream openOutputStream(Uri uri, boolean append) throws IOException {
+ assertBackgroundThread();
+ switch (getUriType(uri)) {
+ case URI_TYPE_FILE: {
+ File localFile = new File(uri.getPath());
+ File parent = localFile.getParentFile();
+ if (parent != null) {
+ parent.mkdirs();
+ }
+ return new FileOutputStream(localFile, append);
+ }
+ case URI_TYPE_CONTENT:
+ case URI_TYPE_RESOURCE: {
+ AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, append ? "wa" : "w");
+ return assetFd.createOutputStream();
+ }
+ }
+ throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
+ }
+
+ public HttpURLConnection createHttpConnection(Uri uri) throws IOException {
+ assertBackgroundThread();
+ return (HttpURLConnection)new URL(uri.toString()).openConnection();
+ }
+
+ // Copies the input to the output in the most efficient manner possible.
+ // Closes both streams.
+ public void copyResource(OpenForReadResult input, OutputStream outputStream) throws IOException {
+ assertBackgroundThread();
+ try {
+ InputStream inputStream = input.inputStream;
+ if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
+ FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
+ FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
+ long offset = 0;
+ long length = input.length;
+ if (input.assetFd != null) {
+ offset = input.assetFd.getStartOffset();
+ }
+ // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
+ // position first.
+ inChannel.position(offset);
+ outChannel.transferFrom(inChannel, 0, length);
+ } else {
+ final int BUFFER_SIZE = 8192;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (;;) {
+ int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+ if (bytesRead <= 0) {
+ break;
+ }
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ }
+ } finally {
+ input.inputStream.close();
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ }
+ }
+
+ public void copyResource(Uri sourceUri, OutputStream outputStream) throws IOException {
+ copyResource(openForRead(sourceUri), outputStream);
+ }
+
+ // Added in 3.5.0.
+ public void copyResource(Uri sourceUri, Uri dstUri) throws IOException {
+ copyResource(openForRead(sourceUri), openOutputStream(dstUri));
+ }
+
+ private void assertBackgroundThread() {
+ if (threadCheckingEnabled) {
+ Thread curThread = Thread.currentThread();
+ if (curThread == Looper.getMainLooper().getThread()) {
+ throw new IllegalStateException("Do not perform IO operations on the UI thread. Use CordovaInterface.getThreadPool() instead.");
+ }
+ if (curThread == jsThread) {
+ throw new IllegalStateException("Tried to perform an IO operation on the WebCore thread. Use CordovaInterface.getThreadPool() instead.");
+ }
+ }
+ }
+
+ private String getDataUriMimeType(Uri uri) {
+ String uriAsString = uri.getSchemeSpecificPart();
+ int commaPos = uriAsString.indexOf(',');
+ if (commaPos == -1) {
+ return null;
+ }
+ String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
+ if (mimeParts.length > 0) {
+ return mimeParts[0];
+ }
+ return null;
+ }
+
+ private OpenForReadResult readDataUri(Uri uri) {
+ String uriAsString = uri.getSchemeSpecificPart();
+ int commaPos = uriAsString.indexOf(',');
+ if (commaPos == -1) {
+ return null;
+ }
+ String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
+ String contentType = null;
+ boolean base64 = false;
+ if (mimeParts.length > 0) {
+ contentType = mimeParts[0];
+ }
+ for (int i = 1; i < mimeParts.length; ++i) {
+ if ("base64".equalsIgnoreCase(mimeParts[i])) {
+ base64 = true;
+ }
+ }
+ String dataPartAsString = uriAsString.substring(commaPos + 1);
+ byte[] data;
+ if (base64) {
+ data = Base64.decode(dataPartAsString, Base64.DEFAULT);
+ } else {
+ try {
+ data = dataPartAsString.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ data = dataPartAsString.getBytes();
+ }
+ }
+ InputStream inputStream = new ByteArrayInputStream(data);
+ return new OpenForReadResult(uri, inputStream, contentType, data.length, null);
+ }
+
+ private static void assertNonRelative(Uri uri) {
+ if (!uri.isAbsolute()) {
+ throw new IllegalArgumentException("Relative URIs are not supported.");
+ }
+ }
+
+ public static final class OpenForReadResult {
+ public final Uri uri;
+ public final InputStream inputStream;
+ public final String mimeType;
+ public final long length;
+ public final AssetFileDescriptor assetFd;
+
+ public OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
+ this.uri = uri;
+ this.inputStream = inputStream;
+ this.mimeType = mimeType;
+ this.length = length;
+ this.assetFd = assetFd;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
new file mode 100644
index 0000000..62e53a0
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
@@ -0,0 +1,142 @@
+/*
+ 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.List;
+import java.util.Map;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.webkit.WebChromeClient.CustomViewCallback;
+
+/**
+ * Main interface for interacting with a Cordova webview - implemented by CordovaWebViewImpl.
+ * This is an interface so that it can be easily mocked in tests.
+ * Methods may be added to this interface without a major version bump, as plugins & embedders
+ * are not expected to implement it.
+ */
+public interface CordovaWebView {
+ public static final String CORDOVA_VERSION = "6.2.1";
+
+ void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);
+
+ boolean isInitialized();
+
+ View getView();
+
+ void loadUrlIntoView(String url, boolean recreatePlugins);
+
+ void stopLoading();
+
+ boolean canGoBack();
+
+ void clearCache();
+
+ /** Use parameter-less overload */
+ @Deprecated
+ void clearCache(boolean b);
+
+ void clearHistory();
+
+ boolean backHistory();
+
+ void handlePause(boolean keepRunning);
+
+ void onNewIntent(Intent intent);
+
+ void handleResume(boolean keepRunning);
+
+ void handleStart();
+
+ void handleStop();
+
+ void handleDestroy();
+
+ /**
+ * Send JavaScript statement back to JavaScript.
+ *
+ * Deprecated (https://issues.apache.org/jira/browse/CB-6851)
+ * Instead of executing snippets of JS, you should use the exec bridge
+ * to create a Java->JS communication channel.
+ * To do this:
+ * 1. Within plugin.xml (to have your JS run before deviceready):
+ * <js-module><runs/></js-module>
+ * 2. Within your .js (call exec on start-up):
+ * require('cordova/channel').onCordovaReady.subscribe(function() {
+ * require('cordova/exec')(win, null, 'Plugin', 'method', []);
+ * function win(message) {
+ * ... process message from java here ...
+ * }
+ * });
+ * 3. Within your .java:
+ * PluginResult dataResult = new PluginResult(PluginResult.Status.OK, CODE);
+ * dataResult.setKeepCallback(true);
+ * savedCallbackContext.sendPluginResult(dataResult);
+ */
+ @Deprecated
+ void sendJavascript(String statememt);
+
+ /**
+ * Load the specified URL in the Cordova webview or a new browser instance.
+ *
+ * NOTE: If openExternal is false, only whitelisted URLs can be loaded.
+ *
+ * @param url The url to load.
+ * @param openExternal Load url in browser instead of Cordova webview.
+ * @param clearHistory Clear the history stack, so new page becomes top of history
+ * @param params Parameters for new app
+ */
+ void showWebPage(String url, boolean openExternal, boolean clearHistory, Map<String, Object> params);
+
+ /**
+ * Deprecated in 4.0.0. Use your own View-toggling logic.
+ */
+ @Deprecated
+ boolean isCustomViewShowing();
+
+ /**
+ * Deprecated in 4.0.0. Use your own View-toggling logic.
+ */
+ @Deprecated
+ void showCustomView(View view, CustomViewCallback callback);
+
+ /**
+ * Deprecated in 4.0.0. Use your own View-toggling logic.
+ */
+ @Deprecated
+ void hideCustomView();
+
+ CordovaResourceApi getResourceApi();
+
+ void setButtonPlumbedToJs(int keyCode, boolean override);
+ boolean isButtonPlumbedToJs(int keyCode);
+
+ void sendPluginResult(PluginResult cr, String callbackId);
+
+ PluginManager getPluginManager();
+ CordovaWebViewEngine getEngine();
+ CordovaPreferences getPreferences();
+ ICordovaCookieManager getCookieManager();
+
+ String getUrl();
+
+ // TODO: Work on deleting these by removing refs from plugins.
+ Context getContext();
+ void loadUrl(String url);
+ Object postMessage(String id, Object data);
+}
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/07bed560/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
new file mode 100644
index 0000000..c8e5a55
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
@@ -0,0 +1,85 @@
+/*
+ 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.view.KeyEvent;
+import android.view.View;
+import android.webkit.ValueCallback;
+
+/**
+ * Interface for all Cordova engines.
+ * No methods will be added to this class (in order to be compatible with existing engines).
+ * Instead, we will create a new interface: e.g. CordovaWebViewEngineV2
+ */
+public interface CordovaWebViewEngine {
+ void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client,
+ CordovaResourceApi resourceApi, PluginManager pluginManager,
+ NativeToJsMessageQueue nativeToJsMessageQueue);
+
+ CordovaWebView getCordovaWebView();
+ ICordovaCookieManager getCookieManager();
+ View getView();
+
+ void loadUrl(String url, boolean clearNavigationStack);
+
+ void stopLoading();
+
+ /** Return the currently loaded URL */
+ String getUrl();
+
+ void clearCache();
+
+ /** After calling clearHistory(), canGoBack() should be false. */
+ void clearHistory();
+
+ boolean canGoBack();
+
+ /** Returns whether a navigation occurred */
+ boolean goBack();
+
+ /** Pauses / resumes the WebView's event loop. */
+ void setPaused(boolean value);
+
+ /** Clean up all resources associated with the WebView. */
+ void destroy();
+
+ /** Add the evaulate Javascript method **/
+ void evaluateJavascript(String js, ValueCallback<String> callback);
+
+ /**
+ * Used to retrieve the associated CordovaWebView given a View without knowing the type of Engine.
+ * E.g. ((CordovaWebView.EngineView)activity.findViewById(android.R.id.webView)).getCordovaWebView();
+ */
+ public interface EngineView {
+ CordovaWebView getCordovaWebView();
+ }
+
+ /**
+ * Contains methods that an engine uses to communicate with the parent CordovaWebView.
+ * Methods may be added in future cordova versions, but never removed.
+ */
+ public interface Client {
+ Boolean onDispatchKeyEvent(KeyEvent event);
+ void clearLoadTimeoutTimer();
+ void onPageStarted(String newUrl);
+ void onReceivedError(int errorCode, String description, String failingUrl);
+ void onPageFinishedLoading(String url);
+ boolean onNavigationAttempt(String url);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org