Make how exec() sends & receives messages configurable.

This also deletes the cordova.shuttingDown and cordova.UsePolling flags.


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/5fecf16a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/5fecf16a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/5fecf16a

Branch: refs/heads/master
Commit: 5fecf16a62155e74dfb8d9f666e24fcf21a22ae9
Parents: 03a0aca
Author: Andrew Grieve <agri...@chromium.org>
Authored: Thu Aug 16 17:11:53 2012 -0400
Committer: Andrew Grieve <agri...@chromium.org>
Committed: Fri Aug 17 11:08:15 2012 -0400

----------------------------------------------------------------------
 lib/android/exec.js                    |  180 +++++++++++++++++++--------
 lib/android/platform.js                |   23 +---
 lib/android/plugin/android/callback.js |  138 ++++++++++----------
 lib/android/plugin/android/polling.js  |   55 ++++----
 lib/cordova.js                         |    4 -
 5 files changed, 225 insertions(+), 175 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/5fecf16a/lib/android/exec.js
----------------------------------------------------------------------
diff --git a/lib/android/exec.js b/lib/android/exec.js
index 60403be..1bd12e8 100644
--- a/lib/android/exec.js
+++ b/lib/android/exec.js
@@ -12,71 +12,141 @@
  * @param {String} action       Action to be run in cordova
  * @param {String[]} [args]     Zero or more arguments to pass to the method
  */
-var cordova = require('cordova');
+var cordova = require('cordova'),
+    callback = require('cordova/plugin/android/callback'),
+    polling = require('cordova/plugin/android/polling'),
+    jsToNativeBridgeMode,
+    nativeToJsBridgeMode,
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1,
+        LOCATION_CHANGE: 2  // Not yet implemented
+    },
+    nativeToJsModes = {
+        POLLING: 0,
+        HANGING_GET: 1,
+        LOAD_URL: 2,  // Not yet implemented
+        ONLINE_EVENT: 3,  // Not yet implemented
+        PRIVATE_API: 4  // Not yet implemented
+    };
 
-module.exports = function(success, fail, service, action, args) {
-  try {
-    var callbackId = service + cordova.callbackId++;
-    if (success || fail) {
-        cordova.callbacks[callbackId] = {success:success, fail:fail};
-    }
+function androidExec(success, fail, service, action, args) {
+    try {
+      var callbackId = service + cordova.callbackId++,
+          argsJson = JSON.stringify(args),
+          result;
+      if (success || fail) {
+          cordova.callbacks[callbackId] = {success:success, fail:fail};
+      }
 
-    var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, 
action, callbackId, true]));
+      if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT) {
+          // Explicit cast to string is required on Android 2.1 to convert from
+          // a Java string to a JS string.
+          result = '' + _cordovaExec.exec(service, action, callbackId, 
argsJson);
+      } else {
+          result = prompt(argsJson, "gap:"+JSON.stringify([service, action, 
callbackId, true]));
+      }
 
-    // If a result was returned
-    if (r.length > 0) {
-        var v = JSON.parse(r);
+      // If a result was returned
+      if (result.length > 0) {
+          var v = JSON.parse(result);
 
-        // If status is OK, then return value back to caller
-        if (v.status === cordova.callbackStatus.OK) {
+          // 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);
-                }
+              // 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;
-        }
+                  // 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 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 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);
-                }
+              // 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);
+                  }
 
-                // Clear callback if not expecting any more results
-                if (!v.keepCallback) {
-                    delete cordova.callbacks[callbackId];
-                }
-            }
-            return null;
+                  // Clear callback if not expecting any more results
+                  if (!v.keepCallback) {
+                      delete cordova.callbacks[callbackId];
+                  }
+              }
+              return null;
+          }
+      }
+    } catch (e2) {
+      console.log("Error: "+e2);
+    }
+};
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaExec) {
+        console.log('Falling back on PROMPT mode since _cordovaExec is 
missing.');
+        mode = jsToNativeModes.PROMPT;
+    }
+    jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == 0) {
+        polling.stop();
+    } else if (nativeToJsBridgeMode == 1) {
+        callback.stop();
+    }
+    nativeToJsBridgeMode = mode;
+    if (mode == 0) {
+        polling.start();
+    } else if (mode == 1) {
+        callback.start();
+    }
+};
+
+// Start listening for XHR callbacks
+// Figure out which bridge approach will work on this Android
+// device: polling or XHR-based callbacks
+androidExec.initialize = function() {
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+    }
+    if (nativeToJsBridgeMode === undefined) {
+        if (callback.isAvailable()) {
+            androidExec.setNativeToJsBridgeMode(nativeToJsModes.HANGING_GET);
+        } else {
+            androidExec.setNativeToJsBridgeMode(nativeToJsModes.POLLING);
         }
     }
-  } catch (e2) {
-    console.log("Error: "+e2);
-  }
 };
+
+module.exports = androidExec;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/5fecf16a/lib/android/platform.js
----------------------------------------------------------------------
diff --git a/lib/android/platform.js b/lib/android/platform.js
index 4439d30..cbd21bf 100644
--- a/lib/android/platform.js
+++ b/lib/android/platform.js
@@ -3,32 +3,15 @@ module.exports = {
     initialize:function() {
         var channel = require("cordova/channel"),
             cordova = require('cordova'),
-            callback = require('cordova/plugin/android/callback'),
-            polling = require('cordova/plugin/android/polling'),
             exec = require('cordova/exec');
 
         channel.onDestroy.subscribe(function() {
-            cordova.shuttingDown = true;
+            exec.setNativeToJsBridgeMode(-1);
         });
 
-        // Start listening for XHR callbacks
-        // Figure out which bridge approach will work on this Android
-        // device: polling or XHR-based callbacks
+        // Use a setTimeout here to give apps a chance to set the bridge mode.
         setTimeout(function() {
-            if (cordova.UsePolling) {
-                polling();
-            }
-            else {
-                var isPolling = prompt("usePolling", "gap_callbackServer:");
-                cordova.UsePolling = isPolling;
-                if (isPolling == "true") {
-                    cordova.UsePolling = true;
-                    polling();
-                } else {
-                    cordova.UsePolling = false;
-                    callback();
-                }
-            }
+            exec.initialize();
         }, 1);
 
         // Inject a listener for the backbutton on the document.

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/5fecf16a/lib/android/plugin/android/callback.js
----------------------------------------------------------------------
diff --git a/lib/android/plugin/android/callback.js 
b/lib/android/plugin/android/callback.js
index d41a164..4729678 100644
--- a/lib/android/plugin/android/callback.js
+++ b/lib/android/plugin/android/callback.js
@@ -1,85 +1,85 @@
 var port = null,
     token = null,
-    cordova = require('cordova'),
-    polling = require('cordova/plugin/android/polling'),
-    callback = function() {
-      // Exit if shutting down app
-      if (cordova.shuttingDown) {
-          return;
-      }
+    exec = require('cordova/exec'),
+    xmlhttp;
 
-      // If polling flag was changed, start using polling from now on
-      if (cordova.UsePolling) {
-          polling();
-          return;
-      }
+module.exports = {
+    start: function callback() {
+        xmlhttp = new XMLHttpRequest();
 
-      var xmlhttp = new XMLHttpRequest();
+        // Callback function when XMLHttpRequest is ready
+        xmlhttp.onreadystatechange=function(){
+            if (!xmlhttp) {
+                return;
+            }
+            if(xmlhttp.readyState === 4){
+                // If callback has JavaScript statement to execute
+                if (xmlhttp.status === 200) {
 
-      // Callback function when XMLHttpRequest is ready
-      xmlhttp.onreadystatechange=function(){
-          if(xmlhttp.readyState === 4){
+                    // 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(callback, 1);
+                }
 
-              // Exit if shutting down app
-              if (cordova.shuttingDown) {
-                  return;
-              }
+                // If callback ping (used to keep XHR request from timing out)
+                else if (xmlhttp.status === 404) {
+                    setTimeout(callback, 10);
+                }
 
-              // If callback has JavaScript statement to execute
-              if (xmlhttp.status === 200) {
+                // If security error
+                else if (xmlhttp.status === 403) {
+                    console.log("JSCallback Error: Invalid token.  Stopping 
callbacks.");
+                }
 
-                  // 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(callback, 1);
-              }
+                // If server is stopping
+                else if (xmlhttp.status === 503) {
+                    console.log("JSCallback Server Closed: Stopping 
callbacks.");
+                }
 
-              // If callback ping (used to keep XHR request from timing out)
-              else if (xmlhttp.status === 404) {
-                  setTimeout(callback, 10);
-              }
+                // If request wasn't GET
+                else if (xmlhttp.status === 400) {
+                    console.log("JSCallback Error: Bad request.  Stopping 
callbacks.");
+                }
 
-              // If security error
-              else if (xmlhttp.status === 403) {
-                  console.log("JSCallback Error: Invalid token.  Stopping 
callbacks.");
-              }
+                // If error, revert to polling
+                else {
+                    console.log("JSCallback Error: Request failed.");
+                    exec.setNativeToJsBridgeMode(exec.nativeToJsModes.POLLING);
+                }
+            }
+        };
 
-              // If server is stopping
-              else if (xmlhttp.status === 503) {
-                  console.log("JSCallback Server Closed: Stopping callbacks.");
-              }
+        if (port === null) {
+            port = prompt("getPort", "gap_callbackServer:");
+        }
+        if (token === null) {
+            token = prompt("getToken", "gap_callbackServer:");
+        }
+        xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true);
+        xmlhttp.send();
+    },
 
-              // If request wasn't GET
-              else if (xmlhttp.status === 400) {
-                  console.log("JSCallback Error: Bad request.  Stopping 
callbacks.");
-              }
+    stop: function() {
+        if (xmlhttp) {
+            var tmp = xmlhttp;
+            xmlhttp = null;
+            tmp.abort();
+        }
+    },
 
-              // If error, revert to polling
-              else {
-                  console.log("JSCallback Error: Request failed.");
-                  cordova.UsePolling = true;
-                  polling();
-              }
-          }
-      };
+    isAvailable: function() {
+        return ("true" != prompt("usePolling", "gap_callbackServer:"));
+    }
 
-      if (port === null) {
-          port = prompt("getPort", "gap_callbackServer:");
-      }
-      if (token === null) {
-          token = prompt("getToken", "gap_callbackServer:");
-      }
-      xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true);
-      xmlhttp.send();
 };
 
-module.exports = callback;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/5fecf16a/lib/android/plugin/android/polling.js
----------------------------------------------------------------------
diff --git a/lib/android/plugin/android/polling.js 
b/lib/android/plugin/android/polling.js
index 0d6e87e..406dc62 100644
--- a/lib/android/plugin/android/polling.js
+++ b/lib/android/plugin/android/polling.js
@@ -1,33 +1,34 @@
 var cordova = require('cordova'),
     period = 50,
-    polling = function() {
-      // Exit if shutting down app
-      if (cordova.shuttingDown) {
-          return;
-      }
+    enabled = false;
 
-      // If polling flag was changed, stop using polling from now on and 
switch to XHR server / callback
-      if (!cordova.UsePolling) {
-          require('cordova/plugin/android/callback')();
-          return;
-      }
 
-      var msg = prompt("", "gap_poll:");
-      if (msg) {
-          setTimeout(function() {
-              try {
-                  var t = eval(""+msg);
-              }
-              catch (e) {
-                  console.log("JSCallbackPolling: Message from Server: " + 
msg);
-                  console.log("JSCallbackPolling Error: "+e);
-              }
-          }, 1);
-          setTimeout(polling, 1);
-      }
-      else {
-          setTimeout(polling, period);
-      }
+function doPoll() {
+    if (!enabled) {
+        return;
+    }
+    var msg = prompt("", "gap_poll:");
+    if (msg) {
+        try {
+            eval(""+msg);
+        }
+        catch (e) {
+            console.log("JSCallbackPolling: Message from Server: " + msg);
+            console.log("JSCallbackPolling Error: "+e);
+        }
+        setTimeout(doPoll, 1);
+    } else {
+        setTimeout(doPoll, period);
+    }
+}
+
+module.exports = {
+    start: function() {
+        enabled = true;
+        setTimeout(doPoll, 1);
+    },
+    stop: function() {
+        enabled = false;
+    }
 };
 
-module.exports = polling;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/5fecf16a/lib/cordova.js
----------------------------------------------------------------------
diff --git a/lib/cordova.js b/lib/cordova.js
index dbaf478..ea5f7cd 100644
--- a/lib/cordova.js
+++ b/lib/cordova.js
@@ -136,10 +136,6 @@ var cordova = {
             window.dispatchEvent(evt);
         }
     },
-    // TODO: this is Android only; think about how to do this better
-    shuttingDown:false,
-    UsePolling:false,
-    // END TODO
 
     // TODO: iOS only
     // This queue holds the currently executing command and all pending

Reply via email to