You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/10/07 21:18:38 UTC

[1/3] android commit: CB-7707 Added multipart PluginResult (close #125)

Repository: cordova-android
Updated Branches:
  refs/heads/4.0.x 9577735ff -> 2af8daff1
  refs/heads/master 2dcd50c11 -> fbeb379f1


CB-7707 Added multipart PluginResult (close #125)

Corresponds to cordova-js commit: a1f866606b3


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

Branch: refs/heads/4.0.x
Commit: fbeb379f1b2102d9d0739f92340c932bdc47873b
Parents: 2dcd50c
Author: Rui Zhao <oa...@gmail.com>
Authored: Mon Oct 6 12:05:06 2014 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Oct 7 15:17:56 2014 -0400

----------------------------------------------------------------------
 framework/assets/www/cordova.js                 | 110 +++++++++++--------
 .../apache/cordova/NativeToJsMessageQueue.java  |  85 ++++++++------
 .../src/org/apache/cordova/PluginResult.java    |  19 ++++
 3 files changed, 134 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/assets/www/cordova.js
----------------------------------------------------------------------
diff --git a/framework/assets/www/cordova.js b/framework/assets/www/cordova.js
index a777356..73805b3 100644
--- a/framework/assets/www/cordova.js
+++ b/framework/assets/www/cordova.js
@@ -1,5 +1,5 @@
 // Platform: android
-// 8ca0f3b2b87e0759c5236b91c80f18438544409c
+// 1fc2526faa6197e1637ecb48ebe0f876f008ba0f
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -263,11 +263,7 @@ var cordova = {
      * Called by native code when returning successful result from an action.
      */
     callbackSuccess: function(callbackId, args) {
-        try {
-            cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
-        } catch (e) {
-            console.log("Error in success callback: " + callbackId + " = "+e);
-        }
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
     },
 
     /**
@@ -276,30 +272,34 @@ var cordova = {
     callbackError: function(callbackId, args) {
         // 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);
-        }
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
     },
 
     /**
      * Called by native code when returning the result from an action.
      */
-    callbackFromNative: function(callbackId, success, status, args, keepCallback) {
-        var callback = cordova.callbacks[callbackId];
-        if (callback) {
-            if (success && status == cordova.callbackStatus.OK) {
-                callback.success && callback.success.apply(null, args);
-            } else if (!success) {
-                callback.fail && callback.fail.apply(null, args);
-            }
+    callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status == cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else {
+                    callback.fail && callback.fail.apply(null, args);
+                }
 
-            // Clear callback if not expecting any more results
-            if (!keepCallback) {
-                delete cordova.callbacks[callbackId];
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
             }
         }
+        catch (err) {
+            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
+            console && console.log && console.log(msg);
+            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
+            throw err;
+        }
     },
     addConstructor: function(func) {
         channel.onCordovaReady.subscribe(function() {
@@ -1013,6 +1013,42 @@ androidExec.setNativeToJsBridgeMode = function(mode) {
     }
 };
 
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        var bytes = window.atob(data);
+        var arraybuffer = new Uint8Array(bytes.length);
+        for (var i = 0; i < bytes.length; i++) {
+            arraybuffer[i] = bytes.charCodeAt(i);
+        }
+        payload.push(arraybuffer.buffer);
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
 // Processes a single message, as encoded by NativeToJsMessageQueue.java.
 function processMessage(message) {
     try {
@@ -1026,32 +1062,10 @@ function processMessage(message) {
             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 = null;
-            } else if (payloadKind == 'n') {
-                payload = +message.slice(nextSpaceIdx + 2);
-            } else if (payloadKind == 'A') {
-                var data = message.slice(nextSpaceIdx + 2);
-                var bytes = window.atob(data);
-                var arraybuffer = new Uint8Array(bytes.length);
-                for (var i = 0; i < bytes.length; i++) {
-                    arraybuffer[i] = bytes.charCodeAt(i);
-                }
-                payload = arraybuffer.buffer;
-            } else if (payloadKind == 'S') {
-                payload = window.atob(message.slice(nextSpaceIdx + 2));
-            } else {
-                payload = JSON.parse(message.slice(nextSpaceIdx + 1));
-            }
-            cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
+            var payloadMessage = message.slice(nextSpaceIdx + 1);
+            var payload = [];
+            buildPayload(payload, payloadMessage);
+            cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
         } else {
             console.log("processMessage failed: invalid message: " + JSON.stringify(message));
         }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
index 497366f..9799a92 100755
--- a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -37,6 +37,7 @@ public class NativeToJsMessageQueue {
 
     // Set this to true to force plugin results to be encoding as
     // JS instead of the custom format (useful for benchmarking).
+    // Doesn't work for multipart messages.
     private static final boolean FORCE_ENCODE_USING_EVAL = false;
 
     // Disable sending back native->JS messages during an exec() when the active
@@ -419,53 +420,43 @@ public class NativeToJsMessageQueue {
             this.pluginResult = pluginResult;
         }
         
-        int calculateEncodedLength() {
-            if (pluginResult == null) {
-                return jsPayloadOrCallbackId.length() + 1;
-            }
-            int statusLen = String.valueOf(pluginResult.getStatus()).length();
-            int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
+        static int calculateEncodedLengthHelper(PluginResult pluginResult) {
             switch (pluginResult.getMessageType()) {
                 case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
                 case PluginResult.MESSAGE_TYPE_NULL: // N
-                    ret += 1;
-                    break;
+                    return 1;
                 case PluginResult.MESSAGE_TYPE_NUMBER: // n
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
                 case PluginResult.MESSAGE_TYPE_STRING: // s
-                    ret += 1 + pluginResult.getStrMessage().length();
-                    break;
+                    return 1 + pluginResult.getStrMessage().length();
                 case PluginResult.MESSAGE_TYPE_BINARYSTRING:
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
                 case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    int ret = 1;
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        int length = calculateEncodedLengthHelper(pluginResult.getMultipartMessage(i));
+                        int argLength = String.valueOf(length).length();
+                        ret += argLength + 1 + length;
+                    }
+                    return ret;
                 case PluginResult.MESSAGE_TYPE_JSON:
                 default:
-                    ret += pluginResult.getMessage().length();
+                    return pluginResult.getMessage().length();
             }
-            return ret;
         }
         
-        void encodeAsMessage(StringBuilder sb) {
+        int calculateEncodedLength() {
             if (pluginResult == null) {
-                sb.append('J')
-                  .append(jsPayloadOrCallbackId);
-                return;
+                return jsPayloadOrCallbackId.length() + 1;
+            }
+            int statusLen = String.valueOf(pluginResult.getStatus()).length();
+            int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
+            return ret + calculateEncodedLengthHelper(pluginResult);
             }
-            int status = pluginResult.getStatus();
-            boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
-            boolean resultOk = status == PluginResult.Status.OK.ordinal();
-            boolean keepCallback = pluginResult.getKeepCallback();
 
-            sb.append((noResult || resultOk) ? 'S' : 'F')
-              .append(keepCallback ? '1' : '0')
-              .append(status)
-              .append(' ')
-              .append(jsPayloadOrCallbackId)
-              .append(' ');
+        static void encodeAsMessageHelper(StringBuilder sb, PluginResult pluginResult) {
             switch (pluginResult.getMessageType()) {
                 case PluginResult.MESSAGE_TYPE_BOOLEAN:
                     sb.append(pluginResult.getMessage().charAt(0)); // t or f.
@@ -489,12 +480,42 @@ public class NativeToJsMessageQueue {
                     sb.append('A');
                     sb.append(pluginResult.getMessage());
                     break;
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    sb.append('M');
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        PluginResult multipartMessage = pluginResult.getMultipartMessage(i);
+                        sb.append(String.valueOf(calculateEncodedLengthHelper(multipartMessage)));
+                        sb.append(' ');
+                        encodeAsMessageHelper(sb, multipartMessage);
+                    }
+                    break;
                 case PluginResult.MESSAGE_TYPE_JSON:
                 default:
                     sb.append(pluginResult.getMessage()); // [ or {
             }
         }
         
+        void encodeAsMessage(StringBuilder sb) {
+            if (pluginResult == null) {
+                sb.append('J')
+                  .append(jsPayloadOrCallbackId);
+                return;
+            }
+            int status = pluginResult.getStatus();
+            boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
+            boolean resultOk = status == PluginResult.Status.OK.ordinal();
+            boolean keepCallback = pluginResult.getKeepCallback();
+
+            sb.append((noResult || resultOk) ? 'S' : 'F')
+              .append(keepCallback ? '1' : '0')
+              .append(status)
+              .append(' ')
+              .append(jsPayloadOrCallbackId)
+              .append(' ');
+
+            encodeAsMessageHelper(sb, pluginResult);
+        }
+
         void encodeAsJsMessage(StringBuilder sb) {
             if (pluginResult == null) {
                 sb.append(jsPayloadOrCallbackId);

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/src/org/apache/cordova/PluginResult.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/PluginResult.java b/framework/src/org/apache/cordova/PluginResult.java
old mode 100755
new mode 100644
index 920cbc2..2b3ac72
--- a/framework/src/org/apache/cordova/PluginResult.java
+++ b/framework/src/org/apache/cordova/PluginResult.java
@@ -18,6 +18,8 @@
 */
 package org.apache.cordova;
 
+import java.util.List;
+
 import org.json.JSONArray;
 import org.json.JSONObject;
 
@@ -29,6 +31,7 @@ public class PluginResult {
     private boolean keepCallback = false;
     private String strMessage;
     private String encodedMessage;
+    private List<PluginResult> multipartMessages;
 
     public PluginResult(Status status) {
         this(status, PluginResult.StatusMessages[status.ordinal()]);
@@ -80,6 +83,13 @@ public class PluginResult {
         this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
     }
     
+    // The keepCallback and status of multipartMessages are ignored.
+    public PluginResult(Status status, List<PluginResult> multipartMessages) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_MULTIPART;
+        this.multipartMessages = multipartMessages;
+    }
+
     public void setKeepCallback(boolean b) {
         this.keepCallback = b;
     }
@@ -99,6 +109,14 @@ public class PluginResult {
         return encodedMessage;
     }
 
+    public int getMultipartMessagesSize() {
+        return multipartMessages.size();
+    }
+
+    public PluginResult getMultipartMessage(int index) {
+        return multipartMessages.get(index);
+    }
+
     /**
      * If messageType == MESSAGE_TYPE_STRING, then returns the message string.
      * Otherwise, returns null.
@@ -150,6 +168,7 @@ public class PluginResult {
     // Use BINARYSTRING when your string may contain null characters.
     // This is required to work around a bug in the platform :(.
     public static final int MESSAGE_TYPE_BINARYSTRING = 7;
+    public static final int MESSAGE_TYPE_MULTIPART = 8;
 
     public static String[] StatusMessages = new String[] {
         "No result",


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[3/3] android commit: Merge branch 'master' into 4.0.x (multipart PluginResult)

Posted by ag...@apache.org.
Merge branch 'master' into 4.0.x (multipart PluginResult)


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

Branch: refs/heads/4.0.x
Commit: 2af8daff1db2a057c9df74d20e51c7c81b65a034
Parents: 9577735 fbeb379
Author: Andrew Grieve <ag...@chromium.org>
Authored: Tue Oct 7 15:18:07 2014 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Oct 7 15:18:07 2014 -0400

----------------------------------------------------------------------
 framework/assets/www/cordova.js                 | 110 +++++++++++--------
 .../apache/cordova/NativeToJsMessageQueue.java  |  85 ++++++++------
 .../src/org/apache/cordova/PluginResult.java    |  19 ++++
 3 files changed, 134 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2af8daff/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[2/3] android commit: CB-7707 Added multipart PluginResult (close #125)

Posted by ag...@apache.org.
CB-7707 Added multipart PluginResult (close #125)

Corresponds to cordova-js commit: a1f866606b3


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

Branch: refs/heads/master
Commit: fbeb379f1b2102d9d0739f92340c932bdc47873b
Parents: 2dcd50c
Author: Rui Zhao <oa...@gmail.com>
Authored: Mon Oct 6 12:05:06 2014 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Oct 7 15:17:56 2014 -0400

----------------------------------------------------------------------
 framework/assets/www/cordova.js                 | 110 +++++++++++--------
 .../apache/cordova/NativeToJsMessageQueue.java  |  85 ++++++++------
 .../src/org/apache/cordova/PluginResult.java    |  19 ++++
 3 files changed, 134 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/assets/www/cordova.js
----------------------------------------------------------------------
diff --git a/framework/assets/www/cordova.js b/framework/assets/www/cordova.js
index a777356..73805b3 100644
--- a/framework/assets/www/cordova.js
+++ b/framework/assets/www/cordova.js
@@ -1,5 +1,5 @@
 // Platform: android
-// 8ca0f3b2b87e0759c5236b91c80f18438544409c
+// 1fc2526faa6197e1637ecb48ebe0f876f008ba0f
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -263,11 +263,7 @@ var cordova = {
      * Called by native code when returning successful result from an action.
      */
     callbackSuccess: function(callbackId, args) {
-        try {
-            cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
-        } catch (e) {
-            console.log("Error in success callback: " + callbackId + " = "+e);
-        }
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
     },
 
     /**
@@ -276,30 +272,34 @@ var cordova = {
     callbackError: function(callbackId, args) {
         // 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);
-        }
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
     },
 
     /**
      * Called by native code when returning the result from an action.
      */
-    callbackFromNative: function(callbackId, success, status, args, keepCallback) {
-        var callback = cordova.callbacks[callbackId];
-        if (callback) {
-            if (success && status == cordova.callbackStatus.OK) {
-                callback.success && callback.success.apply(null, args);
-            } else if (!success) {
-                callback.fail && callback.fail.apply(null, args);
-            }
+    callbackFromNative: function(callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status == cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else {
+                    callback.fail && callback.fail.apply(null, args);
+                }
 
-            // Clear callback if not expecting any more results
-            if (!keepCallback) {
-                delete cordova.callbacks[callbackId];
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
             }
         }
+        catch (err) {
+            var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
+            console && console.log && console.log(msg);
+            cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
+            throw err;
+        }
     },
     addConstructor: function(func) {
         channel.onCordovaReady.subscribe(function() {
@@ -1013,6 +1013,42 @@ androidExec.setNativeToJsBridgeMode = function(mode) {
     }
 };
 
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        var bytes = window.atob(data);
+        var arraybuffer = new Uint8Array(bytes.length);
+        for (var i = 0; i < bytes.length; i++) {
+            arraybuffer[i] = bytes.charCodeAt(i);
+        }
+        payload.push(arraybuffer.buffer);
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
 // Processes a single message, as encoded by NativeToJsMessageQueue.java.
 function processMessage(message) {
     try {
@@ -1026,32 +1062,10 @@ function processMessage(message) {
             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 = null;
-            } else if (payloadKind == 'n') {
-                payload = +message.slice(nextSpaceIdx + 2);
-            } else if (payloadKind == 'A') {
-                var data = message.slice(nextSpaceIdx + 2);
-                var bytes = window.atob(data);
-                var arraybuffer = new Uint8Array(bytes.length);
-                for (var i = 0; i < bytes.length; i++) {
-                    arraybuffer[i] = bytes.charCodeAt(i);
-                }
-                payload = arraybuffer.buffer;
-            } else if (payloadKind == 'S') {
-                payload = window.atob(message.slice(nextSpaceIdx + 2));
-            } else {
-                payload = JSON.parse(message.slice(nextSpaceIdx + 1));
-            }
-            cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
+            var payloadMessage = message.slice(nextSpaceIdx + 1);
+            var payload = [];
+            buildPayload(payload, payloadMessage);
+            cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
         } else {
             console.log("processMessage failed: invalid message: " + JSON.stringify(message));
         }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
index 497366f..9799a92 100755
--- a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -37,6 +37,7 @@ public class NativeToJsMessageQueue {
 
     // Set this to true to force plugin results to be encoding as
     // JS instead of the custom format (useful for benchmarking).
+    // Doesn't work for multipart messages.
     private static final boolean FORCE_ENCODE_USING_EVAL = false;
 
     // Disable sending back native->JS messages during an exec() when the active
@@ -419,53 +420,43 @@ public class NativeToJsMessageQueue {
             this.pluginResult = pluginResult;
         }
         
-        int calculateEncodedLength() {
-            if (pluginResult == null) {
-                return jsPayloadOrCallbackId.length() + 1;
-            }
-            int statusLen = String.valueOf(pluginResult.getStatus()).length();
-            int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
+        static int calculateEncodedLengthHelper(PluginResult pluginResult) {
             switch (pluginResult.getMessageType()) {
                 case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
                 case PluginResult.MESSAGE_TYPE_NULL: // N
-                    ret += 1;
-                    break;
+                    return 1;
                 case PluginResult.MESSAGE_TYPE_NUMBER: // n
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
                 case PluginResult.MESSAGE_TYPE_STRING: // s
-                    ret += 1 + pluginResult.getStrMessage().length();
-                    break;
+                    return 1 + pluginResult.getStrMessage().length();
                 case PluginResult.MESSAGE_TYPE_BINARYSTRING:
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
                 case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
-                    ret += 1 + pluginResult.getMessage().length();
-                    break;
+                    return 1 + pluginResult.getMessage().length();
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    int ret = 1;
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        int length = calculateEncodedLengthHelper(pluginResult.getMultipartMessage(i));
+                        int argLength = String.valueOf(length).length();
+                        ret += argLength + 1 + length;
+                    }
+                    return ret;
                 case PluginResult.MESSAGE_TYPE_JSON:
                 default:
-                    ret += pluginResult.getMessage().length();
+                    return pluginResult.getMessage().length();
             }
-            return ret;
         }
         
-        void encodeAsMessage(StringBuilder sb) {
+        int calculateEncodedLength() {
             if (pluginResult == null) {
-                sb.append('J')
-                  .append(jsPayloadOrCallbackId);
-                return;
+                return jsPayloadOrCallbackId.length() + 1;
+            }
+            int statusLen = String.valueOf(pluginResult.getStatus()).length();
+            int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
+            return ret + calculateEncodedLengthHelper(pluginResult);
             }
-            int status = pluginResult.getStatus();
-            boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
-            boolean resultOk = status == PluginResult.Status.OK.ordinal();
-            boolean keepCallback = pluginResult.getKeepCallback();
 
-            sb.append((noResult || resultOk) ? 'S' : 'F')
-              .append(keepCallback ? '1' : '0')
-              .append(status)
-              .append(' ')
-              .append(jsPayloadOrCallbackId)
-              .append(' ');
+        static void encodeAsMessageHelper(StringBuilder sb, PluginResult pluginResult) {
             switch (pluginResult.getMessageType()) {
                 case PluginResult.MESSAGE_TYPE_BOOLEAN:
                     sb.append(pluginResult.getMessage().charAt(0)); // t or f.
@@ -489,12 +480,42 @@ public class NativeToJsMessageQueue {
                     sb.append('A');
                     sb.append(pluginResult.getMessage());
                     break;
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    sb.append('M');
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        PluginResult multipartMessage = pluginResult.getMultipartMessage(i);
+                        sb.append(String.valueOf(calculateEncodedLengthHelper(multipartMessage)));
+                        sb.append(' ');
+                        encodeAsMessageHelper(sb, multipartMessage);
+                    }
+                    break;
                 case PluginResult.MESSAGE_TYPE_JSON:
                 default:
                     sb.append(pluginResult.getMessage()); // [ or {
             }
         }
         
+        void encodeAsMessage(StringBuilder sb) {
+            if (pluginResult == null) {
+                sb.append('J')
+                  .append(jsPayloadOrCallbackId);
+                return;
+            }
+            int status = pluginResult.getStatus();
+            boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
+            boolean resultOk = status == PluginResult.Status.OK.ordinal();
+            boolean keepCallback = pluginResult.getKeepCallback();
+
+            sb.append((noResult || resultOk) ? 'S' : 'F')
+              .append(keepCallback ? '1' : '0')
+              .append(status)
+              .append(' ')
+              .append(jsPayloadOrCallbackId)
+              .append(' ');
+
+            encodeAsMessageHelper(sb, pluginResult);
+        }
+
         void encodeAsJsMessage(StringBuilder sb) {
             if (pluginResult == null) {
                 sb.append(jsPayloadOrCallbackId);

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/fbeb379f/framework/src/org/apache/cordova/PluginResult.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/PluginResult.java b/framework/src/org/apache/cordova/PluginResult.java
old mode 100755
new mode 100644
index 920cbc2..2b3ac72
--- a/framework/src/org/apache/cordova/PluginResult.java
+++ b/framework/src/org/apache/cordova/PluginResult.java
@@ -18,6 +18,8 @@
 */
 package org.apache.cordova;
 
+import java.util.List;
+
 import org.json.JSONArray;
 import org.json.JSONObject;
 
@@ -29,6 +31,7 @@ public class PluginResult {
     private boolean keepCallback = false;
     private String strMessage;
     private String encodedMessage;
+    private List<PluginResult> multipartMessages;
 
     public PluginResult(Status status) {
         this(status, PluginResult.StatusMessages[status.ordinal()]);
@@ -80,6 +83,13 @@ public class PluginResult {
         this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
     }
     
+    // The keepCallback and status of multipartMessages are ignored.
+    public PluginResult(Status status, List<PluginResult> multipartMessages) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_MULTIPART;
+        this.multipartMessages = multipartMessages;
+    }
+
     public void setKeepCallback(boolean b) {
         this.keepCallback = b;
     }
@@ -99,6 +109,14 @@ public class PluginResult {
         return encodedMessage;
     }
 
+    public int getMultipartMessagesSize() {
+        return multipartMessages.size();
+    }
+
+    public PluginResult getMultipartMessage(int index) {
+        return multipartMessages.get(index);
+    }
+
     /**
      * If messageType == MESSAGE_TYPE_STRING, then returns the message string.
      * Otherwise, returns null.
@@ -150,6 +168,7 @@ public class PluginResult {
     // Use BINARYSTRING when your string may contain null characters.
     // This is required to work around a bug in the platform :(.
     public static final int MESSAGE_TYPE_BINARYSTRING = 7;
+    public static final int MESSAGE_TYPE_MULTIPART = 8;
 
     public static String[] StatusMessages = new String[] {
         "No result",


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org