From e8d48e1f43db6548d8f3a2df166399c77f08aa27 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Thu, 27 Feb 2014 15:36:30 -0500 Subject: [PATCH 01/19] Add NOTICE file --- NOTICE | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/NOTICE b/NOTICE index 40c5e74c..8ec56a52 100644 --- a/NOTICE +++ b/NOTICE @@ -1,17 +1,5 @@ Apache Cordova -Copyright 2014 The Apache Software Foundation +Copyright 2012 The Apache Software Foundation This product includes software developed at -The Apache Software Foundation (http://www.apache.org) - -========================================================================= -== NOTICE file corresponding to the section 4 d of == -== the Apache License, Version 2.0, == -== in this case for the Android-specific code. == -========================================================================= - -This product includes software developed as part of -The Android Open Source Project (http://source.android.com). - -This software includes software developed at Square, Inc. -Copyright (C) 2013 Square, Inc. +The Apache Software Foundation (http://www.apache.org/). From 9a00ccdaccf940348d88c4e5ccd771299311043c Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Thu, 6 Mar 2014 21:25:48 -0500 Subject: [PATCH 02/19] Catch uncaught exceptions in from plugins and turn them into error responses. When a plugin throws an unchecked exception, we're not catching it anywhere and so the error callback is not being called. This change adds a try/catch to catch such exceptions. --- framework/src/org/apache/cordova/PluginManager.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java index e9795e86..f0957222 100755 --- a/framework/src/org/apache/cordova/PluginManager.java +++ b/framework/src/org/apache/cordova/PluginManager.java @@ -236,22 +236,25 @@ public class PluginManager { app.sendPluginResult(cr, callbackId); return; } + CallbackContext callbackContext = new CallbackContext(callbackId, app); try { - CallbackContext callbackContext = new CallbackContext(callbackId, app); long pluginStartTime = System.currentTimeMillis(); boolean wasValidAction = plugin.execute(action, rawArgs, callbackContext); long duration = System.currentTimeMillis() - pluginStartTime; - + if (duration > SLOW_EXEC_WARNING_THRESHOLD) { Log.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool()."); } if (!wasValidAction) { PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION); - app.sendPluginResult(cr, callbackId); + callbackContext.sendPluginResult(cr); } } catch (JSONException e) { PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION); - app.sendPluginResult(cr, callbackId); + callbackContext.sendPluginResult(cr); + } catch (Exception e) { + Log.e(TAG, "Uncaught exception from plugin", e); + callbackContext.error(e.getMessage()); } } From b715d20385a3932dd687460f90db44610d833ad2 Mon Sep 17 00:00:00 2001 From: hadeslee Date: Fri, 21 Mar 2014 12:06:23 +0800 Subject: [PATCH 03/19] Remove incorrect usage of AlertDialog.Builder.create AlertDialog.Builder.show() will create an AlertDialog before it show. This is the source code snippet: /** * Creates a {@link AlertDialog} with the arguments supplied to this builder and * {@link Dialog#show()}'s the dialog. */ public AlertDialog show() { AlertDialog dialog = create(); dialog.show(); return dialog; } github: close #96 --- framework/src/org/apache/cordova/CordovaChromeClient.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaChromeClient.java b/framework/src/org/apache/cordova/CordovaChromeClient.java index 5977e00e..54c8948f 100755 --- a/framework/src/org/apache/cordova/CordovaChromeClient.java +++ b/framework/src/org/apache/cordova/CordovaChromeClient.java @@ -139,7 +139,6 @@ public class CordovaChromeClient extends WebChromeClient { return true; } }); - dlg.create(); dlg.show(); return true; } @@ -188,7 +187,6 @@ public class CordovaChromeClient extends WebChromeClient { return true; } }); - dlg.create(); dlg.show(); return true; } @@ -280,7 +278,6 @@ public class CordovaChromeClient extends WebChromeClient { res.cancel(); } }); - dlg.create(); dlg.show(); } return true; From 298cd9e06529ad795deeaf9d9664a51d3bed65be Mon Sep 17 00:00:00 2001 From: Michal Mocny Date: Tue, 1 Apr 2014 11:33:40 -0400 Subject: [PATCH 04/19] Fix CB-6048: Set launchMode=singleTop so tapping app icon does not always restart app --- bin/templates/project/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/templates/project/AndroidManifest.xml b/bin/templates/project/AndroidManifest.xml index 8a57854c..b031b609 100644 --- a/bin/templates/project/AndroidManifest.xml +++ b/bin/templates/project/AndroidManifest.xml @@ -32,7 +32,7 @@ - From 0add4af2081703961ab6c6567b7ad940932601a8 Mon Sep 17 00:00:00 2001 From: Ian Clelland Date: Wed, 2 Apr 2014 13:27:59 -0400 Subject: [PATCH 05/19] Update JS snapshot to version 3.5.0-dev-81f9a00 --- framework/assets/www/cordova.js | 168 ++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 72 deletions(-) diff --git a/framework/assets/www/cordova.js b/framework/assets/www/cordova.js index 8855fc7f..45c1943a 100644 --- a/framework/assets/www/cordova.js +++ b/framework/assets/www/cordova.js @@ -1,5 +1,5 @@ // Platform: android -// 3.5.0-dev-ddf13aa +// 3.5.0-dev-81f9a00 /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -19,7 +19,7 @@ under the License. */ ;(function() { -var CORDOVA_JS_BUILD_LABEL = '3.5.0-dev-ddf13aa'; +var CORDOVA_JS_BUILD_LABEL = '3.5.0-dev-81f9a00'; // file: src/scripts/require.js /*jshint -W079 */ @@ -437,6 +437,16 @@ base64.fromArrayBuffer = function(arrayBuffer) { return uint8ToBase64(array); }; +base64.toArrayBuffer = function(str) { + var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary'); + var arrayBuffer = new ArrayBuffer(decodedStr.length); + var array = new Uint8Array(arrayBuffer); + for (var i=0, len=decodedStr.length; i < len; i++) { + array[i] = decodedStr.charCodeAt(i); + } + return arrayBuffer; +}; + //------------------------------------------------------------------------------ /* This code is based on the performance tests at http://jsperf.com/b64tests @@ -919,7 +929,7 @@ function androidExec(success, fail, service, action, args) { androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT); return; } else { - androidExec.processMessages(messages); + androidExec.processMessages(messages, true); } } } @@ -963,7 +973,6 @@ androidExec.nativeToJsModes = nativeToJsModes; androidExec.setJsToNativeBridgeMode = function(mode) { if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) { - console.log('Falling back on PROMPT mode since _cordovaNative is missing. Expected for Android 3.2 and lower only.'); mode = jsToNativeModes.PROMPT; } nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT); @@ -1028,48 +1037,64 @@ function processMessage(message) { } cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback); } else { - console.log("processMessage failed: invalid message:" + message); + console.log("processMessage failed: invalid message: " + JSON.stringify(message)); } } catch (e) { - console.log("processMessage failed: Message: " + message); console.log("processMessage failed: Error: " + e); console.log("processMessage failed: Stack: " + e.stack); + console.log("processMessage failed: Message: " + message); } } +var isProcessing = false; + // This is called from the NativeToJsMessageQueue.java. -androidExec.processMessages = function(messages) { +androidExec.processMessages = function(messages, opt_useTimeout) { if (messages) { messagesFromNative.push(messages); - // Check for the reentrant case, and enqueue the message if that's the case. - if (messagesFromNative.length > 1) { - return; - } + } + // Check for the reentrant case. + if (isProcessing) { + return; + } + if (opt_useTimeout) { + window.setTimeout(androidExec.processMessages, 0); + return; + } + isProcessing = true; + try { + // TODO: add setImmediate polyfill and process only one message at a time. while (messagesFromNative.length) { - // Don't unshift until the end so that reentrancy can be detected. - messages = messagesFromNative[0]; + var msg = popMessageFromQueue(); // The Java side can send a * message to indicate that it // still has messages waiting to be retrieved. - if (messages == '*') { - messagesFromNative.shift(); - window.setTimeout(pollOnce, 0); + if (msg == '*' && messagesFromNative.length === 0) { + setTimeout(pollOnce, 0); return; } - - 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); - if (messages) { - messagesFromNative[0] = messages; - } else { - messagesFromNative.shift(); - } + processMessage(msg); } + } finally { + isProcessing = false; } }; +function popMessageFromQueue() { + var messageBatch = messagesFromNative.shift(); + if (messageBatch == '*') { + return '*'; + } + + var spaceIdx = messageBatch.indexOf(' '); + var msgLen = +messageBatch.slice(0, spaceIdx); + var message = messageBatch.substr(spaceIdx + 1, msgLen); + messageBatch = messageBatch.slice(spaceIdx + msgLen + 1); + if (messageBatch) { + messagesFromNative.unshift(messageBatch); + } + return message; +} + module.exports = androidExec; }); @@ -1191,9 +1216,13 @@ modulemapper.clobbers('cordova/exec', 'Cordova.exec'); // Call the platform-specific initialization. platform.bootstrap && platform.bootstrap(); -pluginloader.load(function() { - channel.onPluginsReady.fire(); -}); +// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js. +// The delay allows the attached modules to be defined before the plugin loader looks for them. +setTimeout(function() { + pluginloader.load(function() { + channel.onPluginsReady.fire(); + }); +}, 0); /** * Create all cordova objects once native side is ready. @@ -1444,43 +1473,51 @@ var modulemapper = require('cordova/modulemapper'); var urlutil = require('cordova/urlutil'); // Helper function to inject a