You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2012/09/18 16:47:24 UTC

[2/6] js commit: [android] Add non-eval based plugin result decoding.

[android] Add non-eval based plugin result decoding.


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/74ae56fa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/74ae56fa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/74ae56fa

Branch: refs/heads/master
Commit: 74ae56fa12b18a479e06674618ed1777622d896e
Parents: 898933d
Author: Andrew Grieve <ag...@chromium.org>
Authored: Fri Sep 7 15:14:32 2012 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Sep 18 10:46:48 2012 -0400

----------------------------------------------------------------------
 lib/android/exec.js                    |  133 +++++++++++++--------------
 lib/android/plugin/android/callback.js |   11 +--
 lib/android/plugin/android/polling.js  |   11 +--
 lib/cordova.js                         |   57 +++++-------
 4 files changed, 91 insertions(+), 121 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/74ae56fa/lib/android/exec.js
----------------------------------------------------------------------
diff --git a/lib/android/exec.js b/lib/android/exec.js
index 3a836fe..95c9652 100644
--- a/lib/android/exec.js
+++ b/lib/android/exec.js
@@ -78,77 +78,22 @@ function androidExec(success, fail, service, action, args) {
             androidExec.setNativeToJsBridgeMode(nativeToJsModes.POLLING);
         }
     }
-    try {
-      var callbackId = service + cordova.callbackId++,
-          argsJson = JSON.stringify(args),
-          result;
-      if (success || fail) {
-          cordova.callbacks[callbackId] = {success:success, fail:fail};
-      }
-
-      if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
-          window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
-      } else {
-          // Explicit cast to string is required on Android 2.1 to convert from
-          // a Java string to a JS string.
-          result = '' + nativeApiProvider.get().exec(service, action, callbackId, argsJson);
-      }
-
-      // If a result was returned
-      if (result) {
-          var v = JSON.parse(result);
-
-          // If status is OK, then return value back to caller
-          if (v.status === cordova.callbackStatus.OK) {
-
-              // If there is a success callback, then call it now with
-              // returned value
-              if (success) {
-                  try {
-                      success(v.message);
-                  } catch (e) {
-                      console.log("Error in success callback: " + callbackId  + " = " + e);
-                  }
-
-                  // Clear callback if not expecting any more results
-                  if (!v.keepCallback) {
-                      delete cordova.callbacks[callbackId];
-                  }
-              }
-              return v.message;
-          }
-
-          // If no result
-          else if (v.status === cordova.callbackStatus.NO_RESULT) {
-              // Clear callback if not expecting any more results
-              if (!v.keepCallback) {
-                  delete cordova.callbacks[callbackId];
-              }
-          }
-
-          // If error, then display error
-          else {
-              console.log("Error: Status="+v.status+" Message="+v.message);
-
-              // If there is a fail callback, then call it now with returned value
-              if (fail) {
-                  try {
-                      fail(v.message);
-                  }
-                  catch (e1) {
-                      console.log("Error in error callback: "+callbackId+" = "+e1);
-                  }
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
 
-                  // Clear callback if not expecting any more results
-                  if (!v.keepCallback) {
-                      delete cordova.callbacks[callbackId];
-                  }
-              }
-              return null;
-          }
-      }
-    } catch (e2) {
-      console.log("Error: "+e2);
+    if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
+        window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
+    } else {
+        var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);
+        // Explicit cast to string is required on Android 2.1 to convert from
+        // a Java string to a JS string.
+        if (messages) {
+            messages = String(messages);
+        }
+        androidExec.processMessages(messages);
     }
 }
 
@@ -206,4 +151,52 @@ androidExec.setNativeToJsBridgeMode = function(mode) {
     }
 };
 
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    try {
+        var firstChar = message.charAt(0);
+        if (firstChar == 'J') {
+            eval(message.slice(1));
+        } else if (firstChar == 'S' || firstChar == 'F') {
+            var success = firstChar == 'S';
+            var keepCallback = message.charAt(1) == '1';
+            var spaceIdx = message.indexOf(' ', 2);
+            var status = +message.slice(2, spaceIdx);
+            var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+            var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+            var payloadKind = message.charAt(nextSpaceIdx + 1);
+            var payload;
+            if (payloadKind == 's') {
+                payload = message.slice(nextSpaceIdx + 2);
+            } else if (payloadKind == 't') {
+                payload = true;
+            } else if (payloadKind == 'f') {
+                payload = false;
+            } else if (payloadKind == 'n') {
+                payload = +message.slice(nextSpaceIdx + 2);
+            } else {
+                payload = JSON.parse(message.slice(nextSpaceIdx + 1));
+            }
+            cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+        } else {
+            console.log("processMessage failed: invalid message:" + message);
+        }
+    } catch (e) {
+        console.log("processMessage failed: Message: " + message);
+        console.log("processMessage failed: Error: " + e);
+        console.log("processMessage failed: Stack: " + e.stack);
+    }
+}
+
+// This is called from the NativeToJsMessageQueue.java.
+androidExec.processMessages = function(messages) {
+    while (messages) {
+        var spaceIdx = messages.indexOf(' ');
+        var msgLen = +messages.slice(0, spaceIdx);
+        var message = messages.substr(spaceIdx + 1, msgLen);
+        messages = messages.slice(spaceIdx + msgLen + 1);
+        processMessage(message);
+    }
+};
+
 module.exports = androidExec;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/74ae56fa/lib/android/plugin/android/callback.js
----------------------------------------------------------------------
diff --git a/lib/android/plugin/android/callback.js b/lib/android/plugin/android/callback.js
index f101655..a87a645 100644
--- a/lib/android/plugin/android/callback.js
+++ b/lib/android/plugin/android/callback.js
@@ -39,17 +39,8 @@ function startXhr() {
 
                 // Need to url decode the response
                 var msg = decodeURIComponent(xmlhttp.responseText);
-                setTimeout(function() {
-                    try {
-                        var t = eval(msg);
-                    }
-                    catch (e) {
-                        // If we're getting an error here, seeing the message will help in debugging
-                        console.log("JSCallback: Message from Server: " + msg);
-                        console.log("JSCallback Error: "+e);
-                    }
-                }, 1);
                 setTimeout(startXhr, 1);
+                exec.processMessages(msg);
             }
 
             // If callback ping (used to keep XHR request from timing out)

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/74ae56fa/lib/android/plugin/android/polling.js
----------------------------------------------------------------------
diff --git a/lib/android/plugin/android/polling.js b/lib/android/plugin/android/polling.js
index b3b99bb..89b5f0f 100644
--- a/lib/android/plugin/android/polling.js
+++ b/lib/android/plugin/android/polling.js
@@ -25,15 +25,10 @@ var cordova = require('cordova'),
     enabled = false;
 
 function pollOnce() {
-    var msg = nativeApiProvider.get().retrieveJsMessages();
+    var exec = require('cordova/exec'),
+        msg = nativeApiProvider.get().retrieveJsMessages();
     if (msg) {
-        try {
-            eval(""+msg);
-        }
-        catch (e) {
-            console.log("JSCallbackPolling: Message from Server: " + msg);
-            console.log("JSCallbackPolling Error: "+e);
-        }
+        exec.processMessages(msg);
         return true;
     }
     return false;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/74ae56fa/lib/cordova.js
----------------------------------------------------------------------
diff --git a/lib/cordova.js b/lib/cordova.js
index e8fda63..fc4a744 100644
--- a/lib/cordova.js
+++ b/lib/cordova.js
@@ -192,51 +192,42 @@ var cordova = {
 
     /**
      * Called by native code when returning successful result from an action.
-     *
-     * @param callbackId
-     * @param args
      */
     callbackSuccess: function(callbackId, args) {
-        if (cordova.callbacks[callbackId]) {
-
-            // If result is to be sent to callback
-            if (args.status == cordova.callbackStatus.OK) {
-                try {
-                    if (cordova.callbacks[callbackId].success) {
-                        cordova.callbacks[callbackId].success(args.message);
-                    }
-                }
-                catch (e) {
-                    console.log("Error in success callback: "+callbackId+" = "+e);
-                }
-            }
-
-            // Clear callback if not expecting any more results
-            if (!args.keepCallback) {
-                delete cordova.callbacks[callbackId];
-            }
+        try {
+            cordova.callbackFromNative(callbackId, true, args.status, args.message, args.keepCallback);
+        } catch (e) {
+            console.log("Error in error callback: " + callbackId + " = "+e);
         }
     },
 
     /**
      * Called by native code when returning error result from an action.
-     *
-     * @param callbackId
-     * @param args
      */
     callbackError: function(callbackId, args) {
-        if (cordova.callbacks[callbackId]) {
-            try {
-                if (cordova.callbacks[callbackId].fail) {
-                    cordova.callbacks[callbackId].fail(args.message);
-                }
-            }
-            catch (e) {
-                console.log("Error in error callback: "+callbackId+" = "+e);
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        try {
+            cordova.callbackFromNative(callbackId, false, args.status, args.message, args.keepCallback);
+        } catch (e) {
+            console.log("Error in error callback: " + callbackId + " = "+e);
+        }
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function(callbackId, success, status, message, keepCallback) {
+        var callback = cordova.callbacks[callbackId];
+        if (callback) {
+            if (success && status == cordova.callbackStatus.OK) {
+                callback.success && callback.success(message);
+            } else if (!success) {
+                callback.fail && callback.fail(message);
             }
 
             // Clear callback if not expecting any more results
-            if (!args.keepCallback) {
+            if (!keepCallback) {
                 delete cordova.callbacks[callbackId];
             }
         }