Create CordovaPlugin.java and make Plugin.java a compatibility shim.

The intent of this is to encourage plugins to execute synchronously
when appropriate by not defaulting to using a background thread.

This will also encourage plugins that do run asynchronously to run some
of its logic synchronously before dispatching to a background thread.
This is required for tasks that can be abort()ed, such as
FileTransfer. (CB-1532)

This also makes it possible to lazily parse the JSON args, which is
important for large payloads. (CB-1530)


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/commit/6e6e0275
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/tree/6e6e0275
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/diff/6e6e0275

Branch: refs/heads/master
Commit: 6e6e0275add95a8caed647bdf862aded138bfecd
Parents: ec3c5b2
Author: Andrew Grieve <agri...@chromium.org>
Authored: Mon Sep 24 23:37:34 2012 -0400
Committer: Andrew Grieve <agri...@chromium.org>
Committed: Tue Oct 2 10:14:30 2012 -0400

----------------------------------------------------------------------
 framework/src/org/apache/cordova/DroidGap.java     |   12 +-
 framework/src/org/apache/cordova/Echo.java         |   47 ++---
 framework/src/org/apache/cordova/FileTransfer.java |   30 ++--
 .../org/apache/cordova/api/CallbackContext.java    |   90 ++++++++
 .../org/apache/cordova/api/CordovaInterface.java   |    5 +-
 .../src/org/apache/cordova/api/CordovaPlugin.java  |  151 ++++++++++++++
 .../src/org/apache/cordova/api/LegacyContext.java  |    4 +-
 framework/src/org/apache/cordova/api/Plugin.java   |  159 +++++----------
 .../src/org/apache/cordova/api/PluginEntry.java    |   17 +-
 .../src/org/apache/cordova/api/PluginManager.java  |   71 ++-----
 10 files changed, 366 insertions(+), 220 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/DroidGap.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/DroidGap.java 
b/framework/src/org/apache/cordova/DroidGap.java
index 2ff76fe..f648ab8 100755
--- a/framework/src/org/apache/cordova/DroidGap.java
+++ b/framework/src/org/apache/cordova/DroidGap.java
@@ -22,9 +22,9 @@ import java.util.HashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-import org.apache.cordova.api.Plugin;
-import org.apache.cordova.api.LOG;
 import org.apache.cordova.api.CordovaInterface;
+import org.apache.cordova.api.CordovaPlugin;
+import org.apache.cordova.api.LOG;
 import org.json.JSONException;
 import org.json.JSONObject;
 
@@ -162,7 +162,7 @@ public class DroidGap extends Activity implements 
CordovaInterface {
     String baseUrl = null;
 
     // Plugin to call when activity result is received
-    protected Plugin activityResultCallback = null;
+    protected CordovaPlugin activityResultCallback = null;
     protected boolean activityResultKeepRunning;
 
     // Default background color for activity
@@ -773,7 +773,7 @@ public class DroidGap extends Activity implements 
CordovaInterface {
      * @param intent            The intent to start
      * @param requestCode       The request code that is passed to callback to 
identify the activity
      */
-    public void startActivityForResult(Plugin command, Intent intent, int 
requestCode) {
+    public void startActivityForResult(CordovaPlugin command, Intent intent, 
int requestCode) {
         this.activityResultCallback = command;
         this.activityResultKeepRunning = this.keepRunning;
 
@@ -798,13 +798,13 @@ public class DroidGap extends Activity implements 
CordovaInterface {
      */
     protected void onActivityResult(int requestCode, int resultCode, Intent 
intent) {
         super.onActivityResult(requestCode, resultCode, intent);
-        Plugin callback = this.activityResultCallback;
+        CordovaPlugin callback = this.activityResultCallback;
         if (callback != null) {
             callback.onActivityResult(requestCode, resultCode, intent);
         }
     }
 
-    public void setActivityResultCallback(Plugin plugin) {
+    public void setActivityResultCallback(CordovaPlugin plugin) {
         this.activityResultCallback = plugin;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/Echo.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/Echo.java 
b/framework/src/org/apache/cordova/Echo.java
index 23654c9..b91c3c4 100644
--- a/framework/src/org/apache/cordova/Echo.java
+++ b/framework/src/org/apache/cordova/Echo.java
@@ -18,40 +18,27 @@
 */
 package org.apache.cordova;
 
-import org.apache.cordova.api.Plugin;
-import org.apache.cordova.api.PluginResult;
+import org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
 import org.json.JSONArray;
 import org.json.JSONException;
 
-public class Echo extends Plugin {
+public class Echo extends CordovaPlugin {
 
-    /**
-     * Executes the request and returns PluginResult.
-     *
-     * @param action        The action to execute.
-     * @param args          JSONArry of arguments for the plugin.
-     * @param callbackId    The callback id used when calling back into 
JavaScript.
-     * @return              A PluginResult object with a status and message.
-     */
-    public PluginResult execute(String action, JSONArray args, String 
callbackId) {
-        try {
-            String result = args.getString(0);
-            if ("echo".equals(action) || "echoAsync".equals(action)) {
-                return new PluginResult(PluginResult.Status.OK, result);
-            }
-               return new PluginResult(PluginResult.Status.INVALID_ACTION);
-        } catch (JSONException e) {
-            return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+    @Override
+    public boolean execute(String action, JSONArray args, final 
CallbackContext callbackContext) throws JSONException {
+        final String result = args.getString(0);
+        if ("echo".equals(action)) {
+            callbackContext.success(result);
+            return true;
+        } else if ("echoAsync".equals(action)) {
+            cordova.getThreadPool().execute(new Runnable() {
+                @Override public void run() {
+                    callbackContext.success(result);
+                }
+            });
+            return true;
         }
-    }
-
-    /**
-     * Identifies if action to be executed returns a value and should be run 
synchronously.
-     *
-     * @param action    The action to execute
-     * @return          T=returns value
-     */
-    public boolean isSynch(String action) {
-        return "echo".equals(action);
+        return false;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/FileTransfer.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/FileTransfer.java 
b/framework/src/org/apache/cordova/FileTransfer.java
index 1917d8a..deee291 100644
--- a/framework/src/org/apache/cordova/FileTransfer.java
+++ b/framework/src/org/apache/cordova/FileTransfer.java
@@ -44,7 +44,8 @@ import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 
-import org.apache.cordova.api.Plugin;
+import org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
 import org.apache.cordova.api.PluginResult;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -55,7 +56,7 @@ import android.os.Build;
 import android.util.Log;
 import android.webkit.CookieManager;
 
-public class FileTransfer extends Plugin {
+public class FileTransfer extends CordovaPlugin {
 
     private static final String LOG_TAG = "FileTransfer";
     private static final String LINE_START = "--";
@@ -116,7 +117,7 @@ public class FileTransfer extends Plugin {
     * @see org.apache.cordova.api.Plugin#execute(java.lang.String, 
org.json.JSONArray, java.lang.String)
     */
     @Override
-    public PluginResult execute(String action, JSONArray args, String 
callbackId) {
+    public boolean execute(String action, JSONArray args, final 
CallbackContext callbackContext) throws JSONException {
         if (action.equals("upload") || action.equals("download")) {
             String source = null;
             String target = null;
@@ -129,15 +130,18 @@ public class FileTransfer extends Plugin {
             }
 
             if (action.equals("upload")) {
-                return upload(URLDecoder.decode(source), target, args, 
callbackId);
+                upload(URLDecoder.decode(source), target, args, 
callbackContext);
             } else {
-                return download(source, target, args, callbackId);
+                download(source, target, args, callbackContext);
             }
+            return true;
         } else if (action.equals("abort")) {
-            return abort(args);
-        } else {
-            return new PluginResult(PluginResult.Status.INVALID_ACTION);
+            String objectId = args.getString(0);
+            abort(objectId);
+            callbackContext.success();
+            return true;
         }
+        return false;
     }
 
     /**
@@ -145,7 +149,7 @@ public class FileTransfer extends Plugin {
      * @param source        Full path of the file on the file system
      * @param target        URL of the server to receive the file
      * @param args          JSON Array of args
-     * @param callbackId    callback id for optional progress reports
+     * @param callbackContext    callback id for optional progress reports
      *
      * args[2] fileKey       Name of file request parameter
      * args[3] fileName      File name to be used on server
@@ -153,7 +157,7 @@ public class FileTransfer extends Plugin {
      * args[5] params        key:value pairs of user-defined parameters
      * @return FileUploadResult containing result of upload request
      */
-    private PluginResult upload(String source, String target, JSONArray args, 
String callbackId) {
+    private PluginResult upload(String source, String target, JSONArray args, 
CallbackContext callbackContext) {
         Log.d(LOG_TAG, "upload " + source + " to " +  target);
 
         HttpURLConnection conn = null;
@@ -350,7 +354,7 @@ public class FileTransfer extends Plugin {
                     progress.setLoaded(totalBytes);
                     PluginResult progressResult = new 
PluginResult(PluginResult.Status.OK, progress.toJSONObject());
                     progressResult.setKeepCallback(true);
-                    success(progressResult, callbackId);
+                    callbackContext.sendPluginResult(progressResult);
                 }
                 synchronized (abortTriggered) {
                     if (objectId != null && abortTriggered.contains(objectId)) 
{
@@ -536,7 +540,7 @@ public class FileTransfer extends Plugin {
      * @param target           Full path of the file on the file system
      * @return JSONObject      the downloaded file
      */
-    private PluginResult download(String source, String target, JSONArray 
args, String callbackId) {
+    private PluginResult download(String source, String target, JSONArray 
args, CallbackContext callbackContext) {
         Log.d(LOG_TAG, "download " + source + " to " +  target);
 
         HttpURLConnection connection = null;
@@ -617,7 +621,7 @@ public class FileTransfer extends Plugin {
                         progress.setLoaded(totalBytes);
                         PluginResult progressResult = new 
PluginResult(PluginResult.Status.OK, progress.toJSONObject());
                         progressResult.setKeepCallback(true);
-                        success(progressResult, callbackId);
+                        callbackContext.sendPluginResult(progressResult);
                     }
                     synchronized (abortTriggered) {
                         if (objectId != null && 
abortTriggered.contains(objectId)) {

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/CallbackContext.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/CallbackContext.java 
b/framework/src/org/apache/cordova/api/CallbackContext.java
new file mode 100644
index 0000000..c9dc9d7
--- /dev/null
+++ b/framework/src/org/apache/cordova/api/CallbackContext.java
@@ -0,0 +1,90 @@
+package org.apache.cordova.api;
+
+import android.util.Log;
+
+import org.apache.cordova.CordovaWebView;
+import org.json.JSONObject;
+
+public class CallbackContext {
+    private static final String LOG_TAG = "CordovaPlugin";
+
+    private String callbackId;
+    private CordovaWebView webView;
+    private boolean finished;
+    private int changingThreads;
+
+    public CallbackContext(String callbackId, CordovaWebView webView) {
+        this.callbackId = callbackId;
+        this.webView = webView;
+    }
+    
+    public boolean isFinished() {
+        return finished;
+    }
+    
+    public boolean isChangingThreads() {
+        return changingThreads > 0;
+    }
+    
+    public String getCallbackId() {
+        return callbackId;
+    }
+
+    public void sendPluginResult(PluginResult pluginResult) {
+        synchronized (this) {
+            if (finished) {
+                Log.w(LOG_TAG, "Attempted to send a second callback for ID: " 
+ callbackId + "\nResult was: " + pluginResult.getMessage());
+                return;
+            } else {
+                finished = !pluginResult.getKeepCallback();
+            }
+        }
+        webView.sendPluginResult(pluginResult, callbackId);
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(JSONObject message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(String message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success() {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK));
+    }
+
+    /**
+     * Helper for error callbacks that just returns the Status.ERROR by default
+     *
+     * @param message           The message to add to the error result.
+     */
+    public void error(JSONObject message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
+    }
+
+    /**
+     * Helper for error callbacks that just returns the Status.ERROR by default
+     *
+     * @param message           The message to add to the error result.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
+     */
+    public void error(String message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/CordovaInterface.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/CordovaInterface.java 
b/framework/src/org/apache/cordova/api/CordovaInterface.java
index 40367ca..6499feb 100755
--- a/framework/src/org/apache/cordova/api/CordovaInterface.java
+++ b/framework/src/org/apache/cordova/api/CordovaInterface.java
@@ -38,15 +38,14 @@ public interface CordovaInterface {
      * @param intent      The intent to start
      * @param requestCode   The request code that is passed to callback to 
identify the activity
      */
-    abstract public void startActivityForResult(Plugin command, Intent intent, 
int requestCode);
+    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(Plugin plugin);
-
+    abstract public void setActivityResultCallback(CordovaPlugin plugin);
 
     /**
      * Get the Android activity.

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/CordovaPlugin.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/CordovaPlugin.java 
b/framework/src/org/apache/cordova/api/CordovaPlugin.java
new file mode 100644
index 0000000..8a1da49
--- /dev/null
+++ b/framework/src/org/apache/cordova/api/CordovaPlugin.java
@@ -0,0 +1,151 @@
+/*
+       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.api;
+
+import org.apache.cordova.CordovaWebView;
+import org.json.JSONArray;
+import org.json.JSONException;
+import android.content.Intent;
+
+
+/**
+ * Plugins must extend this class and override one of the execute methods.
+ */
+public class CordovaPlugin {
+    public String id;
+    public CordovaWebView webView;                                     // 
WebView object
+    public CordovaInterface cordova;
+
+    /**
+     * @param ctx The context of the main Activity.
+     */
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        assert this.cordova == null;
+        this.cordova = cordova;
+        this.webView = webView;
+    }
+    
+    /**
+     * 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 callbackId    The callback id 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 callbackId    The callback id used when calling back into 
JavaScript.
+     * @return              Whether the action was valid.
+     */
+    public boolean execute(String action, JSONArray 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 receives a new intent.
+     */
+    public void onNewIntent(Intent intent) {
+    }
+
+    /**
+     * The final call you receive before your activity is destroyed.
+     */
+    public void onDestroy() {
+    }
+
+    /**
+     * 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 data                             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) {
+    }
+
+    /**
+     * By specifying a <url-filter> in plugins.xml you can map a URL (using 
startsWith atm) to this method.
+     *
+     * @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;
+    }
+
+    /**
+     * 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() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/LegacyContext.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/LegacyContext.java 
b/framework/src/org/apache/cordova/api/LegacyContext.java
index 8942cd3..b8bc0ae 100644
--- a/framework/src/org/apache/cordova/api/LegacyContext.java
+++ b/framework/src/org/apache/cordova/api/LegacyContext.java
@@ -65,13 +65,13 @@ public class LegacyContext implements CordovaInterface {
     }
 
     @Deprecated
-    public void setActivityResultCallback(Plugin arg0) {
+    public void setActivityResultCallback(CordovaPlugin arg0) {
         Log.i(LOG_TAG, "Replace ctx.setActivityResultCallback() with 
cordova.setActivityResultCallback()");
         this.cordova.setActivityResultCallback(arg0);
     }
 
     @Deprecated
-    public void startActivityForResult(Plugin arg0, Intent arg1, int arg2) {
+    public void startActivityForResult(CordovaPlugin arg0, Intent arg1, int 
arg2) {
         Log.i(LOG_TAG, "Replace ctx.startActivityForResult() with 
cordova.startActivityForResult()");
         this.cordova.startActivityForResult(arg0, arg1, arg2);
     }

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/Plugin.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/Plugin.java 
b/framework/src/org/apache/cordova/api/Plugin.java
index e856b88..72171f2 100755
--- a/framework/src/org/apache/cordova/api/Plugin.java
+++ b/framework/src/org/apache/cordova/api/Plugin.java
@@ -20,42 +20,29 @@ package org.apache.cordova.api;
 
 import org.apache.cordova.CordovaWebView;
 import org.json.JSONArray;
+import org.json.JSONException;
 import org.json.JSONObject;
-import android.content.Intent;
-
-import android.util.Log;
 
 /**
- * Plugin interface must be implemented by any plugin classes.
- *
- * The execute method is called by the PluginManager.
+ * Legacy Plugin class. This acts as a shim to support the old execute() 
signature.
+ * New plugins should extend CordovaPlugin directly.
  */
-public abstract class Plugin {
-
-    public String id;
-    public CordovaWebView webView;                                     // 
WebView object
+@Deprecated
+public abstract class Plugin extends CordovaPlugin {
     public LegacyContext    ctx;                               // 
LegacyContext object
-    public CordovaInterface cordova;
 
-    /**
-     * Executes the request and returns PluginResult.
-     *
-     * @param action           The action to execute.
-     * @param args                     JSONArry of arguments for the plugin.
-     * @param callbackId       The callback id used when calling back into 
JavaScript.
-     * @return                                 A PluginResult object with a 
status and message.
-     */
     public abstract PluginResult execute(String action, JSONArray args, String 
callbackId);
 
-    /**
-     * Identifies if action to be executed returns a value and should be run 
synchronously.
-     *
-     * @param action   The action to execute
-     * @return                 T=returns value
-     */
     public boolean isSynch(String action) {
         return false;
     }
+    
+    @Override
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        super.initialize(cordova, webView);
+        this.setContext(cordova);
+        this.setView(webView);
+    }
 
     /**
      * Sets the context of the Plugin. This can then be used to do things like
@@ -77,66 +64,35 @@ public abstract class Plugin {
     public void setView(CordovaWebView webView) {
         this.webView = webView;
     }
-
-    /**
-     * 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 receives a new intent.
-     */
-    public void onNewIntent(Intent intent) {
-    }
-
-    /**
-     * The final call you receive before your activity is destroyed.
-     */
-    public void onDestroy() {
-    }
-
-    /**
-     * 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 data                             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) {
-    }
-
-    /**
-     * By specifying a <url-filter> in plugins.xml you can map a URL (using 
startsWith atm) to this method.
-     *
-     * @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;
+    
+    @Override
+    public boolean execute(final String action, final JSONArray args, final 
CallbackContext callbackContext) throws JSONException {
+        final String callbackId = callbackContext.getCallbackId();
+        boolean runAsync = !isSynch(action);
+        if (runAsync) {
+            // Run this on a different thread so that this one can return back 
to JS
+            cordova.getThreadPool().execute(new Runnable() {
+                public void run() {
+                    PluginResult cr;
+                    try {
+                        cr = execute(action, args, callbackId);
+                    } catch (Throwable e) {
+                        cr = new PluginResult(PluginResult.Status.ERROR, 
e.getMessage());
+                    }
+                    sendPluginResult(cr, callbackId);
+                }
+            });
+        } else {
+            PluginResult cr = execute(action, args, callbackId);
+    
+            // Interpret a null response as NO_RESULT, which *does* clear the 
callbacks on the JS side.
+            if (cr == null) {
+                cr = new PluginResult(PluginResult.Status.NO_RESULT);
+            }
+            
+            callbackContext.sendPluginResult(cr);
+        }
+        return true;
     }
 
     /**
@@ -161,8 +117,8 @@ public abstract class Plugin {
      * that execute should return null and the callback from the async 
operation can
      * call success(...) or error(...)
      *
-     * @param pluginResult             The result to return.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param pluginResult      The result to return.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void success(PluginResult pluginResult, String callbackId) {
         this.webView.sendPluginResult(pluginResult, callbackId);
@@ -171,8 +127,8 @@ public abstract class Plugin {
     /**
      * Helper for success callbacks that just returns the Status.OK by default
      *
-     * @param message                  The message to add to the success 
result.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param message           The message to add to the success result.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void success(JSONObject message, String callbackId) {
         this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, 
message), callbackId);
@@ -181,8 +137,8 @@ public abstract class Plugin {
     /**
      * Helper for success callbacks that just returns the Status.OK by default
      *
-     * @param message                  The message to add to the success 
result.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param message           The message to add to the success result.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void success(String message, String callbackId) {
         this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, 
message), callbackId);
@@ -191,8 +147,8 @@ public abstract class Plugin {
     /**
      * Call the JavaScript error callback for this plugin.
      *
-     * @param pluginResult             The result to return.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param pluginResult      The result to return.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void error(PluginResult pluginResult, String callbackId) {
         this.webView.sendPluginResult(pluginResult, callbackId);
@@ -201,8 +157,8 @@ public abstract class Plugin {
     /**
      * Helper for error callbacks that just returns the Status.ERROR by default
      *
-     * @param message                  The message to add to the error result.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param message           The message to add to the error result.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void error(JSONObject message, String callbackId) {
         this.webView.sendPluginResult(new 
PluginResult(PluginResult.Status.ERROR, message), callbackId);
@@ -211,20 +167,11 @@ public abstract class Plugin {
     /**
      * Helper for error callbacks that just returns the Status.ERROR by default
      *
-     * @param message                  The message to add to the error result.
-     * @param callbackId               The callback id used when calling back 
into JavaScript.
+     * @param message           The message to add to the error result.
+     * @param callbackId        The callback id used when calling back into 
JavaScript.
      */
     public void error(String message, String callbackId) {
         this.webView.sendPluginResult(new 
PluginResult(PluginResult.Status.ERROR, message), callbackId);
     }
 
-    /**
-     * 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() {
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/PluginEntry.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/PluginEntry.java 
b/framework/src/org/apache/cordova/api/PluginEntry.java
index e32e098..9b9af6b 100755
--- a/framework/src/org/apache/cordova/api/PluginEntry.java
+++ b/framework/src/org/apache/cordova/api/PluginEntry.java
@@ -43,7 +43,7 @@ public class PluginEntry {
      * Plugin objects are only created when they are called from JavaScript.  
(see PluginManager.exec)
      * The exception is if the onload flag is set, then they are created when 
PluginManager is initialized.
      */
-    public Plugin plugin = null;
+    public CordovaPlugin plugin = null;
 
     /**
      * Flag that indicates the plugin object should be created when 
PluginManager is initialized.
@@ -69,7 +69,7 @@ public class PluginEntry {
      *
      * @return                      The plugin object
      */
-    public Plugin createPlugin(CordovaWebView webView, CordovaInterface ctx) {
+    public CordovaPlugin createPlugin(CordovaWebView webView, CordovaInterface 
ctx) {
         if (this.plugin != null) {
             return this.plugin;
         }
@@ -77,9 +77,8 @@ public class PluginEntry {
             @SuppressWarnings("rawtypes")
             Class c = getClassByName(this.pluginClass);
             if (isCordovaPlugin(c)) {
-                this.plugin = (Plugin) c.newInstance();
-                this.plugin.setContext(ctx);
-                this.plugin.setView(webView);
+                this.plugin = (CordovaPlugin) c.newInstance();
+                this.plugin.initialize(ctx, webView);
                 return plugin;
             }
         } catch (Exception e) {
@@ -106,16 +105,12 @@ public class PluginEntry {
     }
 
     /**
-     * Get the interfaces that a class implements and see if it implements the
-     * org.apache.cordova.api.Plugin interface.
-     *
-     * @param c                     The class to check the interfaces of.
-     * @return                      Boolean indicating if the class implements 
org.apache.cordova.api.Plugin
+     * Returns whether the given class extends CordovaPlugin.
      */
     @SuppressWarnings("rawtypes")
     private boolean isCordovaPlugin(Class c) {
         if (c != null) {
-            return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || 
org.apache.cordova.api.Plugin.class.isAssignableFrom(c);
+            return 
org.apache.cordova.api.CordovaPlugin.class.isAssignableFrom(c);
         }
         return false;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/6e6e0275/framework/src/org/apache/cordova/api/PluginManager.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/PluginManager.java 
b/framework/src/org/apache/cordova/api/PluginManager.java
index 9c2fa1a..cafa79d 100755
--- a/framework/src/org/apache/cordova/api/PluginManager.java
+++ b/framework/src/org/apache/cordova/api/PluginManager.java
@@ -32,6 +32,7 @@ import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Intent;
 import android.content.res.XmlResourceParser;
+import android.util.Log;
 
 /**
  * PluginManager is exposed to JavaScript in the Cordova WebView.
@@ -207,59 +208,31 @@ public class PluginManager {
      *                      how to deal with it.
      * @param callbackId    String containing the id of the callback that is 
execute in JavaScript if
      *                      this is an async plugin call.
-     * @param args          An Array literal string containing any arguments 
needed in the
+     * @param rawArgs       An Array literal string containing any arguments 
needed in the
      *                      plugin execute method.
      * @return Whether the task completed synchronously.
      */
-    public boolean exec(final String service, final String action, final 
String callbackId, final String jsonArgs) {
-        PluginResult cr = null;
-        final Plugin plugin = this.getPlugin(service);
-        boolean runAsync = !plugin.isSynch(action);
+    public boolean exec(String service, String action, String callbackId, 
String rawArgs) {
+        CordovaPlugin plugin = this.getPlugin(service);
+        if (plugin == null) {
+            PluginResult cr = new 
PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
+            app.sendPluginResult(cr, callbackId);
+            return true;
+        }
         try {
-            final JSONArray args = new JSONArray(jsonArgs);
-            //final CordovaInterface ctx = this.ctx;
-            if (plugin != null) {
-                if (runAsync) {
-                    // Run this on a different thread so that this one can 
return back to JS
-                    ctx.getThreadPool().execute(new Runnable() {
-                        public void run() {
-                            try {
-                                // Call execute on the plugin so that it can 
do it's thing
-                                PluginResult cr = plugin.execute(action, args, 
callbackId);
-                                app.sendPluginResult(cr, callbackId);
-                            } catch (Exception e) {
-                                PluginResult cr = new 
PluginResult(PluginResult.Status.ERROR, e.getMessage());
-                                app.sendPluginResult(cr, callbackId);
-                            }
-                        }
-                    });
-                    return false;
-                } else {
-                    // Call execute on the plugin so that it can do it's thing
-                    cr = plugin.execute(action, args, callbackId);
-
-                    // If no result to be sent and keeping callback, then no 
need to sent back to JavaScript
-                    if ((cr.getStatus() == 
PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
-                        return true;
-                    }
-                }
+            CallbackContext callbackContext = new CallbackContext(callbackId, 
app);
+            boolean wasValidAction = plugin.execute(action, rawArgs, 
callbackContext);
+            if (!wasValidAction) {
+                PluginResult cr = new 
PluginResult(PluginResult.Status.INVALID_ACTION);
+                app.sendPluginResult(cr, callbackId);
+                return true;
             }
+            return callbackContext.isFinished();
         } catch (JSONException e) {
-            System.out.println("ERROR: " + e.toString());
-            cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
-        }
-        // if async we have already returned at this point unless there was an 
error...
-        if (runAsync) {
-            if (cr == null) {
-                cr = new 
PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
-            }
+            PluginResult cr = new 
PluginResult(PluginResult.Status.JSON_EXCEPTION);
             app.sendPluginResult(cr, callbackId);
+            return true;
         }
-        if (cr == null) {
-               cr = new PluginResult(PluginResult.Status.NO_RESULT);
-        }
-        app.sendPluginResult(cr, callbackId);
-        return true;
     }
 
     @Deprecated
@@ -273,14 +246,14 @@ public class PluginManager {
      * If the service doesn't exist, then return null.
      *
      * @param service       The name of the service.
-     * @return              Plugin or null
+     * @return              CordovaPlugin or null
      */
-    private Plugin getPlugin(String service) {
+    private CordovaPlugin getPlugin(String service) {
         PluginEntry entry = this.entries.get(service);
         if (entry == null) {
             return null;
         }
-        Plugin plugin = entry.plugin;
+        CordovaPlugin plugin = entry.plugin;
         if (plugin == null) {
             plugin = entry.createPlugin(this.app, this.ctx);
         }
@@ -403,7 +376,7 @@ public class PluginManager {
     public void onReset() {
         Iterator<PluginEntry> it = this.entries.values().iterator();
         while (it.hasNext()) {
-            Plugin plugin = it.next().plugin;
+            CordovaPlugin plugin = it.next().plugin;
             if (plugin != null) {
                 plugin.onReset();
             }

Reply via email to