You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2013/05/10 01:00:37 UTC

[35/43] Version 2.7.0-rc.1

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators b/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators
new file mode 100755
index 0000000..7911763
--- /dev/null
+++ b/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators
@@ -0,0 +1,23 @@
+#!/bin/bash
+# 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.
+
+set -e
+
+CORDOVA_LIB_PATH=$( cd "$( dirname "$0" )" && pwd )
+
+bash "$CORDOVA_LIB_PATH"/cordova list-started-emulators
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators.bat
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators.bat b/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators.bat
new file mode 100644
index 0000000..f1b3c5d
--- /dev/null
+++ b/lib/cordova-android/bin/templates/cordova/lib/list-started-emulators.bat
@@ -0,0 +1,9 @@
+@ECHO OFF
+SET full_path=%~dp0
+IF EXIST %full_path%cordova.js (
+    cscript "%full_path%cordova.js" list-started-emulators //nologo
+) ELSE (
+    ECHO. 
+    ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/lib/start-emulator
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/lib/start-emulator b/lib/cordova-android/bin/templates/cordova/lib/start-emulator
new file mode 100755
index 0000000..8e8964d
--- /dev/null
+++ b/lib/cordova-android/bin/templates/cordova/lib/start-emulator
@@ -0,0 +1,23 @@
+#!/bin/bash
+# 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.
+
+set -e
+
+CORDOVA_LIB_PATH=$( cd "$( dirname "$0" )" && pwd )
+
+bash "$CORDOVA_LIB_PATH"/cordova start-emulator "$@"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/lib/start-emulator.bat
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/lib/start-emulator.bat b/lib/cordova-android/bin/templates/cordova/lib/start-emulator.bat
new file mode 100644
index 0000000..4f3fb5d
--- /dev/null
+++ b/lib/cordova-android/bin/templates/cordova/lib/start-emulator.bat
@@ -0,0 +1,9 @@
+@ECHO OFF
+SET full_path=%~dp0
+IF EXIST %full_path%cordova.js (
+    cscript "%full_path%cordova.js" start-emulator %* //nologo
+) ELSE (
+    ECHO. 
+    ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/log
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/log b/lib/cordova-android/bin/templates/cordova/log
index 087a200..01fe107 100755
--- a/lib/cordova-android/bin/templates/cordova/log
+++ b/lib/cordova-android/bin/templates/cordova/log
@@ -1,3 +1,4 @@
+#!/bin/bash
 # 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
@@ -15,10 +16,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#!/bin/bash
-
 set -e
 
 CORDOVA_PATH=$( cd "$( dirname "$0" )/.." && pwd )
 
-bash "$CORDOVA_PATH"/cordova/cordova log
+bash "$CORDOVA_PATH"/cordova/lib/cordova log "$@"

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/log.bat
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/log.bat b/lib/cordova-android/bin/templates/cordova/log.bat
index b8cc6be..2c492e7 100644
--- a/lib/cordova-android/bin/templates/cordova/log.bat
+++ b/lib/cordova-android/bin/templates/cordova/log.bat
@@ -1,18 +1,2 @@
-:: 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.
-
-%~dp0\cordova.bat log
+@ECHO OFF
+%~dp0\cordova.bat log %*

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/release
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/release b/lib/cordova-android/bin/templates/cordova/release
deleted file mode 100755
index 73d873e..0000000
--- a/lib/cordova-android/bin/templates/cordova/release
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-
-#!/bin/bash
-
-set -e
-
-CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
-
-bash "$CORDOVA_PATH"/cordova release

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/run
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/run b/lib/cordova-android/bin/templates/cordova/run
index 840a8d5..ec352b0 100755
--- a/lib/cordova-android/bin/templates/cordova/run
+++ b/lib/cordova-android/bin/templates/cordova/run
@@ -1,3 +1,4 @@
+#!/bin/bash
 # 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
@@ -15,10 +16,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#!/bin/bash
-
 set -e
 
 CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
 
-bash "$CORDOVA_PATH"/cordova run
+bash "$CORDOVA_PATH"/lib/cordova run "$@"

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/templates/cordova/run.bat
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/templates/cordova/run.bat b/lib/cordova-android/bin/templates/cordova/run.bat
index 7c470ed..b1cab64 100644
--- a/lib/cordova-android/bin/templates/cordova/run.bat
+++ b/lib/cordova-android/bin/templates/cordova/run.bat
@@ -1 +1,2 @@
-%~dp0\cordova.bat run
+@ECHO OFF
+%~dp0\cordova.bat run %*
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/update
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/update b/lib/cordova-android/bin/update
index 0e86886..92ceda8 100755
--- a/lib/cordova-android/bin/update
+++ b/lib/cordova-android/bin/update
@@ -130,10 +130,17 @@ else
 fi
 
 # creating cordova folder and copying run/build/log/launch scripts
+mkdir "$PROJECT_PATH"/cordova
+mkdir "$PROJECT_PATH"/cordova/lib
 cp "$BUILD_PATH"/bin/templates/cordova/appinfo.jar "$PROJECT_PATH"/cordova/appinfo.jar
-cp "$BUILD_PATH"/bin/templates/cordova/cordova "$PROJECT_PATH"/cordova/cordova
 cp "$BUILD_PATH"/bin/templates/cordova/build "$PROJECT_PATH"/cordova/build
-cp "$BUILD_PATH"/bin/templates/cordova/release "$PROJECT_PATH"/cordova/release
 cp "$BUILD_PATH"/bin/templates/cordova/clean "$PROJECT_PATH"/cordova/clean
 cp "$BUILD_PATH"/bin/templates/cordova/log "$PROJECT_PATH"/cordova/log
 cp "$BUILD_PATH"/bin/templates/cordova/run "$PROJECT_PATH"/cordova/run
+cp "$BUILD_PATH"/bin/templates/cordova/lib/cordova "$PROJECT_PATH"/cordova/lib/cordova
+cp "$BUILD_PATH"/bin/templates/cordova/lib/install-device "$PROJECT_PATH"/cordova/lib/install-device
+cp "$BUILD_PATH"/bin/templates/cordova/lib/install-emulator "$PROJECT_PATH"/cordova/lib/install-emulator
+cp "$BUILD_PATH"/bin/templates/cordova/lib/list-devices "$PROJECT_PATH"/cordova/lib/list-devices
+cp "$BUILD_PATH"/bin/templates/cordova/lib/list-emulator-images "$PROJECT_PATH"/cordova/lib/list-emulator-images
+cp "$BUILD_PATH"/bin/templates/cordova/lib/list-started-emulators "$PROJECT_PATH"/cordova/lib/list-started-emulators
+cp "$BUILD_PATH"/bin/templates/cordova/lib/start-emulator "$PROJECT_PATH"/cordova/lib/start-emulator

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/bin/update.js
----------------------------------------------------------------------
diff --git a/lib/cordova-android/bin/update.js b/lib/cordova-android/bin/update.js
index 244dcc1..748d602 100644
--- a/lib/cordova-android/bin/update.js
+++ b/lib/cordova-android/bin/update.js
@@ -183,11 +183,17 @@ if(fso.FolderExists(ROOT + '\\framework')) {
 createAppInfoJar();
 WScript.Echo("Copying cordova command tools...");
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\appinfo.jar ' + PROJECT_PATH + '\\cordova\\appinfo.jar /Y');
-exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.js ' + PROJECT_PATH + '\\cordova\\cordova.js /Y');
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.bat ' + PROJECT_PATH + '\\cordova\\cordova.bat /Y');
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\clean.bat ' + PROJECT_PATH + '\\cordova\\clean.bat /Y');
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\build.bat ' + PROJECT_PATH + '\\cordova\\build.bat /Y');
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\log.bat ' + PROJECT_PATH + '\\cordova\\log.bat /Y');
 exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\run.bat ' + PROJECT_PATH + '\\cordova\\run.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\cordova.js ' + PROJECT_PATH + '\\cordova\\lib\\cordova.js /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\install-device.bat ' + PROJECT_PATH + '\\cordova\\lib\\install-device.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\install-emulator.bat ' + PROJECT_PATH + '\\cordova\\lib\\install-emulator.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\list-emulator-images.bat ' + PROJECT_PATH + '\\cordova\\lib\\list-emulator-images.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\list-devices.bat ' + PROJECT_PATH + '\\cordova\\lib\\list-devices.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\list-started-emulators.bat ' + PROJECT_PATH + '\\cordova\\lib\\list-started-emulators.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\lib\\start-emulator.bat ' + PROJECT_PATH + '\\cordova\\lib\\start-emulator.bat /Y');
 
 cleanup();

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/assets/js/cordova.android.js
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/assets/js/cordova.android.js b/lib/cordova-android/framework/assets/js/cordova.android.js
index 93e85d1..2941307 100644
--- a/lib/cordova-android/framework/assets/js/cordova.android.js
+++ b/lib/cordova-android/framework/assets/js/cordova.android.js
@@ -1,8 +1,8 @@
 // Platform: android
 
-// commit 125dca530923a44a8f44f68f5e1970cbdd4e7faf
+// commit d0ffb852378ff018bac2f3b12c38098a19b8ce00
 
-// File generated at :: Mon Apr 01 2013 13:28:03 GMT-0700 (PDT)
+// File generated at :: Thu Apr 18 2013 15:10:54 GMT-0400 (EDT)
 
 /*
  Licensed to the Apache Software Foundation (ASF) under one
@@ -219,6 +219,10 @@ var cordova = {
             }
             else {
               setTimeout(function() {
+                  // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                  if (type == 'deviceready') {
+                      document.dispatchEvent(evt);
+                  }
                   documentEventHandlers[type].fire(evt);
               }, 0);
             }
@@ -742,6 +746,7 @@ channel.createSticky('onDestroy');
 // Channels that must fire before "deviceready" is fired.
 channel.waitForInitialization('onCordovaReady');
 channel.waitForInitialization('onCordovaConnectionReady');
+channel.waitForInitialization('onDOMContentLoaded');
 
 module.exports = channel;
 
@@ -840,32 +845,27 @@ function androidExec(success, fail, service, action, args) {
     }
 
     var callbackId = service + cordova.callbackId++,
-        argsJson = JSON.stringify(args),
-        returnValue;
+        argsJson = JSON.stringify(args);
 
-    // TODO: Returning the payload of a synchronous call was deprecated in 2.2.0.
-    // Remove it after 6 months.
-    function captureReturnValue(value) {
-        returnValue = value;
-        success && success(value);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
     }
 
-    cordova.callbacks[callbackId] = {success:captureReturnValue, fail:fail};
-
     if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
         window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
     } else {
         var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);
-        androidExec.processMessages(messages);
-    }
-    if (cordova.callbacks[callbackId]) {
-        if (success || fail) {
-            cordova.callbacks[callbackId].success = success;
+        // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+        // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+        if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && messages === "@Null arguments.") {
+            androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+            androidExec(success, fail, service, action, args);
+            androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+            return;
         } else {
-            delete cordova.callbacks[callbackId];
+            androidExec.processMessages(messages);
         }
     }
-    return returnValue;
 }
 
 function pollOnce() {
@@ -981,30 +981,30 @@ function processMessage(message) {
 androidExec.processMessages = function(messages) {
     if (messages) {
         messagesFromNative.push(messages);
+        // Check for the reentrant case, and enqueue the message if that's the case.
+        if (messagesFromNative.length > 1) {
+            return;
+        }
         while (messagesFromNative.length) {
-            messages = messagesFromNative.shift();
+            // Don't unshift until the end so that reentrancy can be detected.
+            messages = messagesFromNative[0];
             // The Java side can send a * message to indicate that it
             // still has messages waiting to be retrieved.
-            // TODO(agrieve): This is currently disabled on the Java side
-            // since it breaks returning the result in exec of synchronous
-            // plugins. Once we remove this ability, we can remove this comment.
             if (messages == '*') {
+                messagesFromNative.shift();
                 window.setTimeout(pollOnce, 0);
-                continue;
+                return;
             }
 
             var spaceIdx = messages.indexOf(' ');
             var msgLen = +messages.slice(0, spaceIdx);
             var message = messages.substr(spaceIdx + 1, msgLen);
             messages = messages.slice(spaceIdx + msgLen + 1);
-            // Put the remaining messages back into queue in case an exec()
-            // is made by the callback.
+            processMessage(message);
             if (messages) {
-                messagesFromNative.unshift(messages);
-            }
-
-            if (message) {
-                processMessage(message);
+                messagesFromNative[0] = messages;
+            } else {
+                messagesFromNative.shift();
             }
         }
     }
@@ -2398,7 +2398,7 @@ function initRead(reader, file) {
 
     if (typeof file == 'string') {
         // Deprecated in Cordova 2.4.
-        console.warning('Using a string argument with FileReader.readAs functions is deprecated.');
+        console.warn('Using a string argument with FileReader.readAs functions is deprecated.');
         reader._fileName = file;
     } else if (typeof file.fullPath == 'string') {
         reader._fileName = file.fullPath;
@@ -2756,7 +2756,7 @@ function getBasicAuthHeader(urlString) {
         var origin = protocol + url.host;
 
         // check whether there are the username:password credentials in the url
-        if (url.href.indexOf(origin) != 0) { // credentials found
+        if (url.href.indexOf(origin) !== 0) { // credentials found
             var atIndex = url.href.indexOf("@");
             credentials = url.href.substring(protocol.length, atIndex);
         }
@@ -2805,15 +2805,11 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
     var params = null;
     var chunkedMode = true;
     var headers = null;
-
+    var httpMethod = null;
     var basicAuthHeader = getBasicAuthHeader(server);
     if (basicAuthHeader) {
-        if (!options) {
-            options = new FileUploadOptions();
-        }
-        if (!options.headers) {
-            options.headers = {};
-        }
+        options = options || {};
+        options.headers = options.headers || {};
         options.headers[basicAuthHeader.name] = basicAuthHeader.value;
     }
 
@@ -2822,6 +2818,12 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
         fileName = options.fileName;
         mimeType = options.mimeType;
         headers = options.headers;
+        httpMethod = options.httpMethod || "POST";
+        if (httpMethod.toUpperCase() == "PUT"){
+            httpMethod = "PUT";
+        } else {
+            httpMethod = "POST";
+        }
         if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") {
             chunkedMode = options.chunkedMode;
         }
@@ -2848,7 +2850,7 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
             successCallback && successCallback(result);
         }
     };
-    exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id]);
+    exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
 };
 
 /**
@@ -2866,12 +2868,8 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro
 
     var basicAuthHeader = getBasicAuthHeader(source);
     if (basicAuthHeader) {
-        if (!options) {
-            options = {};
-        }
-        if (!options.headers) {
-            options.headers = {};
-        }
+        options = options || {};
+        options.headers = options.headers || {};
         options.headers[basicAuthHeader.name] = basicAuthHeader.value;
     }
 
@@ -2910,12 +2908,11 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro
 };
 
 /**
- * Aborts the ongoing file transfer on this object
- * @param successCallback {Function}  Callback to be invoked upon success
- * @param errorCallback {Function}    Callback to be invoked upon error
+ * Aborts the ongoing file transfer on this object. The original error
+ * callback for the file transfer will be called if necessary.
  */
-FileTransfer.prototype.abort = function(successCallback, errorCallback) {
-    exec(successCallback, errorCallback, 'FileTransfer', 'abort', [this._id]);
+FileTransfer.prototype.abort = function() {
+    exec(null, null, 'FileTransfer', 'abort', [this._id]);
 };
 
 module.exports = FileTransfer;
@@ -2959,12 +2956,13 @@ define("cordova/plugin/FileUploadOptions", function(require, exports, module) {
  * @param headers {Object}   Keys are header names, values are header values. Multiple
  *                           headers of the same name are not supported.
  */
-var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers) {
+var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
     this.fileKey = fileKey || null;
     this.fileName = fileName || null;
     this.mimeType = mimeType || null;
     this.params = params || null;
     this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
 };
 
 module.exports = FileUploadOptions;
@@ -3299,6 +3297,7 @@ define("cordova/plugin/InAppBrowser", function(require, exports, module) {
 
 var exec = require('cordova/exec');
 var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
 
 function InAppBrowser() {
    this.channels = {
@@ -3327,6 +3326,26 @@ InAppBrowser.prototype = {
         if (eventname in this.channels) {
             this.channels[eventname].unsubscribe(f);
         }
+    },
+
+    executeScript: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, "InAppBrowser", "injectScriptCode", [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, "InAppBrowser", "injectScriptFile", [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('executeScript requires exactly one of code or file to be specified');
+        }
+    },
+
+    insertCSS: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, "InAppBrowser", "injectStyleCode", [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, "InAppBrowser", "injectStyleFile", [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('insertCSS requires exactly one of code or file to be specified');
+        }
     }
 };
 
@@ -3335,6 +3354,13 @@ module.exports = function(strUrl, strWindowName, strWindowFeatures) {
     var cb = function(eventname) {
        iab._eventHandler(eventname);
     };
+
+    // Don't catch calls that write to existing frames (e.g. named iframes).
+    if (window.frames && window.frames[strWindowName]) {
+        var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+        return origOpenFunc.apply(window, arguments);
+    }
+
     exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
     return iab;
 };
@@ -4858,7 +4884,7 @@ console.debug = function() {
 console.assert = function(expression) {
     if (expression) return;
 
-    var message = utils.vformat(arguments[1], [].slice.call(arguments, 2));
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
     console.log("ASSERT: " + message);
 };
 
@@ -5958,10 +5984,10 @@ function logWithArgs(level, args) {
  * Parameters passed after message are used applied to
  * the message with utils.format()
  */
-logger.logLevel = function(level, message /* , ... */) {
+logger.logLevel = function(level /* , ... */) {
     // format the message with the parameters
-    var formatArgs = [].slice.call(arguments, 2);
-    message    = utils.vformat(message, formatArgs);
+    var formatArgs = [].slice.call(arguments, 1);
+    var message    = logger.format.apply(logger.format, formatArgs);
 
     if (LevelsMap[level] === null) {
         throw new Error("invalid logging level: " + level);
@@ -5996,6 +6022,92 @@ logger.logLevel = function(level, message /* , ... */) {
     }
 };
 
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
 // when deviceready fires, log queued messages
 logger.__onDeviceReady = function() {
     if (DeviceReady) return;
@@ -6164,13 +6276,13 @@ module.exports = {
             console.log("Notification.confirm(string, function, string, string) is deprecated.  Use Notification.confirm(string, function, string, array).");
         }
 
-        // Android and iOS take an array of button label names.
+        // Some platforms take an array of button label names.
         // Other platforms take a comma separated list.
         // For compatibility, we convert to the desired type based on the platform.
-        if (platform.id == "android" || platform.id == "ios") {
+        if (platform.id == "android" || platform.id == "ios" || platform.id == "windowsphone") {
             if (typeof _buttonLabels === 'string') {
                 var buttonLabelString = _buttonLabels;
-                _buttonLabels = buttonLabelString.split(",");
+                _buttonLabels = _buttonLabels.split(","); // not crazy about changing the var type here
             }
         } else {
             if (Array.isArray(_buttonLabels)) {
@@ -6521,62 +6633,6 @@ utils.alert = function(msg) {
     }
 };
 
-/**
- * Formats a string and arguments following it ala sprintf()
- *
- * see utils.vformat() for more information
- */
-utils.format = function(formatString /* ,... */) {
-    var args = [].slice.call(arguments, 1);
-    return utils.vformat(formatString, args);
-};
-
-/**
- * Formats a string and arguments following it ala vsprintf()
- *
- * format chars:
- *   %j - format arg as JSON
- *   %o - format arg as JSON
- *   %c - format arg as ''
- *   %% - replace with '%'
- * any other char following % will format it's
- * arg via toString().
- *
- * for rationale, see FireBug's Console API:
- *    http://getfirebug.com/wiki/index.php/Console_API
- */
-utils.vformat = function(formatString, args) {
-    if (formatString === null || formatString === undefined) return "";
-    if (arguments.length == 1) return formatString.toString();
-    if (typeof formatString != "string") return formatString.toString();
-
-    var pattern = /(.*?)%(.)(.*)/;
-    var rest    = formatString;
-    var result  = [];
-
-    while (args.length) {
-        var arg   = args.shift();
-        var match = pattern.exec(rest);
-
-        if (!match) break;
-
-        rest = match[3];
-
-        result.push(match[1]);
-
-        if (match[2] == '%') {
-            result.push('%');
-            args.unshift(arg);
-            continue;
-        }
-
-        result.push(formatted(arg, match[2]));
-    }
-
-    result.push(rest);
-
-    return result.join('');
-};
 
 //------------------------------------------------------------------------------
 function UUIDcreatePart(length) {
@@ -6591,26 +6647,6 @@ function UUIDcreatePart(length) {
     return uuidpart;
 }
 
-//------------------------------------------------------------------------------
-function formatted(object, formatChar) {
-
-    try {
-        switch(formatChar) {
-            case 'j':
-            case 'o': return JSON.stringify(object);
-            case 'c': return '';
-        }
-    }
-    catch (e) {
-        return "error JSON.stringify()ing argument: " + e;
-    }
-
-    if ((object === null) || (object === undefined)) {
-        return Object.prototype.toString.call(object);
-    }
-
-    return object.toString();
-}
 
 });
 
@@ -6620,6 +6656,25 @@ window.cordova = require('cordova');
 // file: lib/scripts/bootstrap.js
 
 (function (context) {
+    var channel = require('cordova/channel');
+    var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+    function logUnfiredChannels(arr) {
+        for (var i = 0; i < arr.length; ++i) {
+            if (arr[i].state != 2) {
+                console.log('Channel not fired: ' + arr[i].type);
+            }
+        }
+    }
+
+    window.setTimeout(function() {
+        if (channel.onDeviceReady.state != 2) {
+            console.log('deviceready has not fired after 5 seconds.');
+            logUnfiredChannels(platformInitChannelsArray);
+            logUnfiredChannels(channel.deviceReadyChannelsArray);
+        }
+    }, 5000);
+
     // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
     // We replace it so that properties that can't be clobbered can instead be overridden.
     function replaceNavigator(origNavigator) {
@@ -6641,8 +6696,6 @@ window.cordova = require('cordova');
         context.navigator = replaceNavigator(context.navigator);
     }
 
-    var channel = require("cordova/channel");
-
     // _nativeReady is global variable that the native side can set
     // to signify that the native code is ready. It is a global since
     // it may be called before any cordova JS is ready.
@@ -6651,32 +6704,33 @@ window.cordova = require('cordova');
     }
 
     /**
-     * Create all cordova objects once page has fully loaded and native side is ready.
+     * Create all cordova objects once native side is ready.
      */
     channel.join(function() {
-        var builder = require('cordova/builder'),
-            platform = require('cordova/platform');
-
-        builder.buildIntoButDoNotClobber(platform.defaults, context);
-        builder.buildIntoAndClobber(platform.clobbers, context);
-        builder.buildIntoAndMerge(platform.merges, context);
-
         // Call the platform-specific initialization
-        platform.initialize();
+        require('cordova/platform').initialize();
 
         // Fire event to notify that all objects are created
         channel.onCordovaReady.fire();
 
-        // Fire onDeviceReady event once all constructors have run and
-        // cordova info has been received from native side.
+        // Fire onDeviceReady event once page has fully loaded, all
+        // constructors have run and cordova info has been received from native
+        // side.
+        // This join call is deliberately made after platform.initialize() in
+        // order that plugins may manipulate channel.deviceReadyChannelsArray
+        // if necessary.
         channel.join(function() {
             require('cordova').fireDocumentEvent('deviceready');
         }, channel.deviceReadyChannelsArray);
 
-    }, [ channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady ]);
+    }, platformInitChannelsArray);
 
 }(window));
 
+// file: lib/scripts/bootstrap-android.js
+
+require('cordova/channel').onNativeReady.fire();
+
 // file: lib/scripts/plugin_loader.js
 
 // Tries to load all plugins' js-modules.
@@ -6752,35 +6806,31 @@ window.cordova = require('cordova');
         }
     }
 
+
     // Try to XHR the cordova_plugins.json file asynchronously.
-    try { // we commented we were going to try, so let us actually try and catch 
+    try { // we commented we were going to try, so let us actually try and catch
         var xhr = new context.XMLHttpRequest();
-        xhr.onreadystatechange = function() {
-            if (this.readyState != 4) { // not DONE
-                return;
-            }
-
+        xhr.onload = function() {
             // If the response is a JSON string which composes an array, call handlePluginsObject.
             // If the request fails, or the response is not a JSON array, just call finishPluginLoading.
-            if (this.status == 200) {
-                var obj = JSON.parse(this.responseText);
-                if (obj && obj instanceof Array && obj.length > 0) {
-                    handlePluginsObject(obj);
-                } else {
-                    finishPluginLoading();
-                }
+            var obj = JSON.parse(this.responseText);
+            if (obj && obj instanceof Array && obj.length > 0) {
+                handlePluginsObject(obj);
             } else {
                 finishPluginLoading();
             }
         };
+        xhr.onerror = function() {
+            finishPluginLoading();
+        };
         xhr.open('GET', 'cordova_plugins.json', true); // Async
         xhr.send();
     }
-    catch(err) {
+    catch(err){
         finishPluginLoading();
     }
 }(window));
 
 
 
-})();
+})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/libs/commons-codec-1.7.jar
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/libs/commons-codec-1.7.jar b/lib/cordova-android/framework/libs/commons-codec-1.7.jar
deleted file mode 100644
index efa7f72..0000000
Binary files a/lib/cordova-android/framework/libs/commons-codec-1.7.jar and /dev/null differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/proguard-project.txt
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/proguard-project.txt b/lib/cordova-android/framework/proguard-project.txt
deleted file mode 100644
index f2fe155..0000000
--- a/lib/cordova-android/framework/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-#   http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-#   public *;
-#}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/CameraLauncher.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/CameraLauncher.java b/lib/cordova-android/framework/src/org/apache/cordova/CameraLauncher.java
index 22a9b94..426d250 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/CameraLauncher.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/CameraLauncher.java
@@ -42,6 +42,7 @@ import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Matrix;
 import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Rect;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.net.Uri;
@@ -396,19 +397,21 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
                             (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) {
                         this.callbackContext.success(uri.toString());
                     } else {
+                        String uriString = uri.toString();
                         // Get the path to the image. Makes loading so much easier.
-                        String imagePath = FileHelper.getRealPath(uri, this.cordova);
-                        String mimeType = FileHelper.getMimeType(imagePath, this.cordova);
-                        // Log.d(LOG_TAG, "Real path = " + imagePath);
-                        // Log.d(LOG_TAG, "mime type = " + mimeType);
+                        String mimeType = FileHelper.getMimeType(uriString, this.cordova);
                         // If we don't have a valid image so quit.
-                        if (imagePath == null || mimeType == null || 
-                                !(mimeType.equalsIgnoreCase("image/jpeg") || mimeType.equalsIgnoreCase("image/png"))) {
+                        if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) {
                         	Log.d(LOG_TAG, "I either have a null image path or bitmap");
                             this.failPicture("Unable to retrieve path to picture!");
                             return;
                         }
-                        Bitmap bitmap = getScaledBitmap(imagePath);
+                        Bitmap bitmap = null;
+                        try {
+                            bitmap = getScaledBitmap(uriString);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
                         if (bitmap == null) {
                         	Log.d(LOG_TAG, "I either have a null image path or bitmap");
                             this.failPicture("Unable to create bitmap!");
@@ -416,14 +419,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
                         }
 
                         if (this.correctOrientation) {
-                            String[] cols = { MediaStore.Images.Media.ORIENTATION };
-                            Cursor cursor = this.cordova.getActivity().getContentResolver().query(intent.getData(),
-                                    cols, null, null, null);
-                            if (cursor != null) {
-                                cursor.moveToPosition(0);
-                                rotate = cursor.getInt(0);
-                                cursor.close();
-                            }
+                            rotate = getImageOrientation(uri);
                             if (rotate != 0) {
                                 Matrix matrix = new Matrix();
                                 matrix.setRotate(rotate);
@@ -443,15 +439,17 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
                                 try {
                                     // Create an ExifHelper to save the exif data that is lost during compression
                                     String resizePath = DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/resize.jpg";
+                                    // Some content: URIs do not map to file paths (e.g. picasa).
+                                    String realPath = FileHelper.getRealPath(uri, this.cordova);
                                     ExifHelper exif = new ExifHelper();
-                                    try {
-                                        if (this.encodingType == JPEG) {
-                                            exif.createInFile(FileHelper.getRealPath(uri, this.cordova));
+                                    if (realPath != null && this.encodingType == JPEG) {
+                                        try {
+                                            exif.createInFile(realPath);
                                             exif.readExifData();
                                             rotate = exif.getOrientation();
+                                        } catch (IOException e) {
+                                            e.printStackTrace();
                                         }
-                                    } catch (IOException e) {
-                                        e.printStackTrace();
                                     }
 
                                     OutputStream os = new FileOutputStream(resizePath);
@@ -459,7 +457,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
                                     os.close();
 
                                     // Restore exif data to file
-                                    if (this.encodingType == JPEG) {
+                                    if (realPath != null && this.encodingType == JPEG) {
                                         exif.createOutFile(resizePath);
                                         exif.writeExifData();
                                     }
@@ -493,6 +491,19 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
         }
     }
 
+    private int getImageOrientation(Uri uri) {
+        String[] cols = { MediaStore.Images.Media.ORIENTATION };
+        Cursor cursor = cordova.getActivity().getContentResolver().query(uri,
+                cols, null, null, null);
+        int rotate = 0;
+        if (cursor != null) {
+            cursor.moveToPosition(0);
+            rotate = cursor.getInt(0);
+            cursor.close();
+        }
+        return rotate;
+    }
+
     /**
      * Figure out if the bitmap should be rotated. For instance if the picture was taken in
      * portrait mode
@@ -563,17 +574,18 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
      *
      * @param imagePath
      * @return
+     * @throws IOException 
      */
-    private Bitmap getScaledBitmap(String imagePath) {
+    private Bitmap getScaledBitmap(String imageUrl) throws IOException {
         // If no new width or height were specified return the original bitmap
         if (this.targetWidth <= 0 && this.targetHeight <= 0) {
-            return BitmapFactory.decodeFile(imagePath);
+            return BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova));
         }
 
         // figure out the original width and height of the image
         BitmapFactory.Options options = new BitmapFactory.Options();
         options.inJustDecodeBounds = true;
-        BitmapFactory.decodeFile(imagePath, options);
+        BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options);
         
         //CB-2292: WTF? Why is the width null?
         if(options.outWidth == 0 || options.outHeight == 0)
@@ -587,7 +599,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
         // Load in the smallest bitmap possible that is closest to the size we want
         options.inJustDecodeBounds = false;
         options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight);
-        Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options);
+        Bitmap unscaledBitmap = BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options);
         if (unscaledBitmap == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/Config.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Config.java b/lib/cordova-android/framework/src/org/apache/cordova/Config.java
index f5de38d..594c2b2 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/Config.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Config.java
@@ -171,7 +171,7 @@ public class Config {
                     LOG.i("CordovaLog", "Found start page location: %s", src);
 
                     if (src != null) {
-                        Pattern schemeRegex = Pattern.compile("^[a-z]+://");
+                        Pattern schemeRegex = Pattern.compile("^[a-z-]+://");
                         Matcher matcher = schemeRegex.matcher(src);
                         if (matcher.find()) {
                             startUrl = src;
@@ -220,19 +220,33 @@ public class Config {
             } else { // specific access
                 // check if subdomains should be included
                 // TODO: we should not add more domains if * has already been added
+                Pattern schemeRegex = Pattern.compile("^[a-z-]+://");
+                Matcher matcher = schemeRegex.matcher(origin);
                 if (subdomains) {
-                    // XXX making it stupid friendly for people who forget to include protocol/SSL
+                    // Check for http or https protocols
                     if (origin.startsWith("http")) {
                         this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
-                    } else {
+                    }
+                    // Check for other protocols
+                    else if(matcher.find()){
+                        this.whiteList.add(Pattern.compile("^" + origin.replaceFirst("//", "//(.*\\.)?")));
+                    }
+                    // XXX making it stupid friendly for people who forget to include protocol/SSL
+                    else {
                         this.whiteList.add(Pattern.compile("^https?://(.*\\.)?" + origin));
                     }
                     LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
                 } else {
-                    // XXX making it stupid friendly for people who forget to include protocol/SSL
+                    // Check for http or https protocols
                     if (origin.startsWith("http")) {
                         this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
-                    } else {
+                    }
+                    // Check for other protocols
+                    else if(matcher.find()){
+                        this.whiteList.add(Pattern.compile("^" + origin));
+                    }
+                    // XXX making it stupid friendly for people who forget to include protocol/SSL
+                    else {
                         this.whiteList.add(Pattern.compile("^https?://" + origin));
                     }
                     LOG.d(TAG, "Origin to allow: %s", origin);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/CordovaLocationListener.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/CordovaLocationListener.java b/lib/cordova-android/framework/src/org/apache/cordova/CordovaLocationListener.java
old mode 100755
new mode 100644
index 7b7a9f7..01c828b
--- a/lib/cordova-android/framework/src/org/apache/cordova/CordovaLocationListener.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/CordovaLocationListener.java
@@ -22,6 +22,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import org.apache.cordova.api.CallbackContext;
 
@@ -42,6 +44,8 @@ public class CordovaLocationListener implements LocationListener {
 
     public HashMap<String, CallbackContext> watches = new HashMap<String, CallbackContext>();
     private List<CallbackContext> callbacks = new ArrayList<CallbackContext>();
+    
+    private Timer timer = null;
 
     private String TAG = "[Cordova Location Listener]";
 
@@ -52,11 +56,12 @@ public class CordovaLocationListener implements LocationListener {
     }
 
     protected void fail(int code, String message) {
+    	this.cancelTimer();
         for (CallbackContext callbackContext: this.callbacks)
         {
-            this.owner.fail(code, message, callbackContext);
+            this.owner.fail(code, message, callbackContext, false);
         }
-        if(this.owner.isGlobalListener(this))
+        if(this.owner.isGlobalListener(this) && this.watches.size() == 0)
         {
         	Log.d(TAG, "Stopping global listener");
         	this.stop();
@@ -65,16 +70,17 @@ public class CordovaLocationListener implements LocationListener {
 
         Iterator<CallbackContext> it = this.watches.values().iterator();
         while (it.hasNext()) {
-            this.owner.fail(code, message, it.next());
+            this.owner.fail(code, message, it.next(), true);
         }
     }
 
     private void win(Location loc) {
+    	this.cancelTimer();
         for (CallbackContext callbackContext: this.callbacks)
         {
-            this.owner.win(loc, callbackContext);
+            this.owner.win(loc, callbackContext, false);
         }
-        if(this.owner.isGlobalListener(this))
+        if(this.owner.isGlobalListener(this) && this.watches.size() == 0)
         {
         	Log.d(TAG, "Stopping global listener");
         	this.stop();
@@ -83,7 +89,7 @@ public class CordovaLocationListener implements LocationListener {
 
         Iterator<CallbackContext> it = this.watches.values().iterator();
         while (it.hasNext()) {
-            this.owner.win(loc, it.next());
+            this.owner.win(loc, it.next(), true);
         }
     }
 
@@ -155,8 +161,12 @@ public class CordovaLocationListener implements LocationListener {
             this.start();
         }
     }
-    public void addCallback(CallbackContext callbackContext) {
-        this.callbacks.add(callbackContext);
+    public void addCallback(CallbackContext callbackContext, int timeout) {
+    	if(this.timer == null) {
+    		this.timer = new Timer();
+    	}
+    	this.timer.schedule(new LocationTimeoutTask(callbackContext, this), timeout);
+        this.callbacks.add(callbackContext);        
         if (this.size() == 1) {
             this.start();
         }
@@ -173,7 +183,7 @@ public class CordovaLocationListener implements LocationListener {
     /**
      * Destroy listener.
      */
-    public void destroy() {
+    public void destroy() {    	
         this.stop();
     }
 
@@ -199,9 +209,43 @@ public class CordovaLocationListener implements LocationListener {
      * Stop receiving location updates.
      */
     private void stop() {
+    	this.cancelTimer();
         if (this.running) {
             this.locationManager.removeUpdates(this);
             this.running = false;
         }
     }
+    
+    private void cancelTimer() {
+    	if(this.timer != null) {
+    		this.timer.cancel();
+        	this.timer.purge();
+        	this.timer = null;
+    	}
+    }
+    
+    private class LocationTimeoutTask extends TimerTask {
+    	
+    	private CallbackContext callbackContext = null;
+    	private CordovaLocationListener listener = null;
+    	
+    	public LocationTimeoutTask(CallbackContext callbackContext, CordovaLocationListener listener) {
+    		this.callbackContext = callbackContext;
+    		this.listener = listener;
+    	}
+
+		@Override
+		public void run() {
+			for (CallbackContext callbackContext: listener.callbacks) {
+				if(this.callbackContext == callbackContext) {
+					listener.callbacks.remove(callbackContext);
+					break;
+				}
+			}
+			
+			if(listener.size() == 0) {
+				listener.stop();
+			}
+		}    	
+    }
 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebView.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebView.java b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebView.java
index e653a95..5dd061e 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebView.java
@@ -24,6 +24,7 @@ import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Stack;
+import java.util.regex.Pattern;
 
 import org.apache.cordova.Config;
 import org.apache.cordova.api.CordovaInterface;
@@ -237,7 +238,11 @@ public class CordovaWebView extends WebView {
         // Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
         try {
             Method gingerbread_getMethod =  WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
-            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
+            
+            String manufacturer = android.os.Build.MANUFACTURER;
+            Log.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
+            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB &&
+                    android.os.Build.MANUFACTURER.contains("HTC"))
             {
                 gingerbread_getMethod.invoke(settings, true);
             }
@@ -262,11 +267,8 @@ public class CordovaWebView extends WebView {
         // Enable database
         // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
         String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
-        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
-        {
-            settings.setDatabaseEnabled(true);
-            settings.setDatabasePath(databasePath);
-        }
+        settings.setDatabaseEnabled(true);
+        settings.setDatabasePath(databasePath);
         
         settings.setGeolocationDatabasePath(databasePath);
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
index 4751fc3..4b00615 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
@@ -314,15 +314,6 @@ public class CordovaWebViewClient extends WebViewClient {
         // Clear timeout flag
         this.appView.loadUrlTimeout++;
 
-        // Try firing the onNativeReady event in JS. If it fails because the JS is
-        // not loaded yet then just set a flag so that the onNativeReady can be fired
-        // from the JS side when the JS gets to that code.
-        if (!url.equals("about:blank")) {
-            LOG.d(TAG, "Trying to fire onNativeReady");
-            this.appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}");
-            this.appView.postMessage("onNativeReady", null);
-        }
-
         // Broadcast message that page has loaded
         this.appView.postMessage("onPageFinished", url);
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/Device.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Device.java b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
index 0f828a1..aa316c5 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/Device.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
@@ -77,7 +77,6 @@ public class Device extends CordovaPlugin {
             r.put("uuid", Device.uuid);
             r.put("version", this.getOSVersion());
             r.put("platform", Device.platform);
-            r.put("name", this.getProductName());
             r.put("cordova", Device.cordovaVersion);
             r.put("model", this.getModel());
             callbackContext.success(r);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java b/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
index d4296cb..bb895e2 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
@@ -51,6 +51,7 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
+import android.widget.ImageView;
 import android.webkit.ValueCallback;
 import android.webkit.WebViewClient;
 import android.widget.LinearLayout;
@@ -717,7 +718,7 @@ public class DroidGap extends Activity implements CordovaInterface {
             appView.handleDestroy();
         }
         else {
-            this.endActivity();
+            this.activityState = ACTIVITY_EXITING; 
         }
     }
 
@@ -1031,7 +1032,13 @@ public class DroidGap extends Activity implements CordovaInterface {
                 root.setBackgroundColor(that.getIntegerProperty("backgroundColor", Color.BLACK));
                 root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                         ViewGroup.LayoutParams.FILL_PARENT, 0.0F));
-                root.setBackgroundResource(that.splashscreen);
+                // We want the splashscreen to keep its ratio, 
+                // for this we need to use an ImageView and not simply the background of the LinearLayout
+                ImageView splashscreenView = new ImageView(that.getActivity());
+                splashscreenView.setImageResource(that.splashscreen);
+                splashscreenView.setScaleType(ImageView.ScaleType.CENTER_CROP); // similar to the background-size:cover CSS property
+                splashscreenView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
+                root.addView(splashscreenView);
 
                 // Create and show the dialog
                 splashDialog = new Dialog(that, android.R.style.Theme_Translucent_NoTitleBar);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/ExposedJsApi.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/ExposedJsApi.java b/lib/cordova-android/framework/src/org/apache/cordova/ExposedJsApi.java
index 48e7102..7702d35 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/ExposedJsApi.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/ExposedJsApi.java
@@ -20,6 +20,7 @@ package org.apache.cordova;
 
 import android.webkit.JavascriptInterface;
 import org.apache.cordova.api.PluginManager;
+import org.apache.cordova.api.PluginResult;
 import org.json.JSONException;
 
 /**
@@ -39,6 +40,12 @@ import org.json.JSONException;
 
     @JavascriptInterface
     public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
+        // If the arguments weren't received, send a message back to JS.  It will switch bridge modes and try again.  See CB-2666.
+        // We send a message meant specifically for this case.  It starts with "@" so no other message can be encoded into the same string.
+        if (arguments == null) {
+            return "@Null arguments.";
+        }
+
         jsMessageQueue.setPaused(true);
         try {
             boolean wasSync = pluginManager.exec(service, action, callbackId, arguments);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java b/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
index c10ed96..8b446b0 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
@@ -28,6 +28,8 @@ import org.apache.cordova.api.LOG;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URLConnection;
+import java.util.Locale;
 
 public class FileHelper {
     private static final String LOG_TAG = "FileUtils";
@@ -92,7 +94,8 @@ public class FileHelper {
             Uri uri = Uri.parse(uriString);
             return cordova.getActivity().getContentResolver().openInputStream(uri);
         } else if (uriString.startsWith("file:///android_asset/")) {
-            String relativePath = uriString.substring(22);
+            Uri uri = Uri.parse(uriString);
+            String relativePath = uri.getPath().substring(15);
             return cordova.getActivity().getAssets().open(relativePath);
         } else {
             return new FileInputStream(getRealPath(uriString, cordova));
@@ -122,14 +125,18 @@ public class FileHelper {
     public static String getMimeType(String uriString, CordovaInterface cordova) {
         String mimeType = null;
 
+        Uri uri = Uri.parse(uriString);
         if (uriString.startsWith("content://")) {
-            Uri uri = Uri.parse(uriString);
             mimeType = cordova.getActivity().getContentResolver().getType(uri);
         } else {
-            // MimeTypeMap.getFileExtensionFromUrl has a bug that occurs when the filename has a space, so we encode it.
-            // We also convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
-            String encodedUriString = uriString.replace(" ", "%20").toLowerCase();
-            String extension = MimeTypeMap.getFileExtensionFromUrl(encodedUriString);
+            // MimeTypeMap.getFileExtensionFromUrl() fails when there are query parameters.
+            String extension = uri.getPath();
+            int lastDot = extension.lastIndexOf('.');
+            if (lastDot != -1) {
+                extension = extension.substring(lastDot + 1);
+            }
+            // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
+            extension = extension.toLowerCase();
             if (extension.equals("3ga")) {
                 mimeType = "audio/3gpp";
             } else {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
index dba29af..c1ca15c 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
@@ -41,6 +41,8 @@ import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.Inflater;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
@@ -100,10 +102,83 @@ public class FileTransfer extends CordovaPlugin {
     }
 
     /**
+     * Adds an interface method to an InputStream to return the number of bytes
+     * read from the raw stream. This is used to track total progress against
+     * the HTTP Content-Length header value from the server.
+     */
+    private static abstract class TrackingInputStream extends FilterInputStream {
+    	public TrackingInputStream(final InputStream in) {
+    		super(in);
+    	}
+        public abstract long getTotalRawBytesRead();
+	}
+
+    private static class ExposedGZIPInputStream extends GZIPInputStream {
+	    public ExposedGZIPInputStream(final InputStream in) throws IOException {
+	    	super(in);
+	    }
+	    public Inflater getInflater() {
+	    	return inf;
+	    }
+	}
+
+    /**
+     * Provides raw bytes-read tracking for a GZIP input stream. Reports the
+     * total number of compressed bytes read from the input, rather than the
+     * number of uncompressed bytes.
+     */
+    private static class TrackingGZIPInputStream extends TrackingInputStream {
+    	private ExposedGZIPInputStream gzin;
+	    public TrackingGZIPInputStream(final ExposedGZIPInputStream gzin) throws IOException {
+	    	super(gzin);
+	    	this.gzin = gzin;
+	    }
+	    public long getTotalRawBytesRead() {
+	    	return gzin.getInflater().getBytesRead();
+	    }
+	}
+
+    /**
+     * Provides simple total-bytes-read tracking for an existing InputStream
+     */
+    private static class TrackingHTTPInputStream extends TrackingInputStream {
+        private long bytesRead = 0;
+        public TrackingHTTPInputStream(InputStream stream) {
+            super(stream);
+        }
+
+        private int updateBytesRead(int newBytesRead) {
+        	if (newBytesRead != -1) {
+        		bytesRead += newBytesRead;
+        	}
+        	return newBytesRead;
+        }
+
+        @Override
+        public int read() throws IOException {
+            return updateBytesRead(super.read());
+        }
+
+        @Override
+        public int read(byte[] buffer) throws IOException {
+            return updateBytesRead(super.read(buffer));
+        }
+
+        @Override
+        public int read(byte[] bytes, int offset, int count) throws IOException {
+            return updateBytesRead(super.read(bytes, offset, count));
+        }
+
+        public long getTotalRawBytesRead() {
+        	return bytesRead;
+        }
+    }
+
+    /**
      * Works around a bug on Android 2.3.
      * http://code.google.com/p/android/issues/detail?id=14562
      */
-    private static final class DoneHandlerInputStream extends FilterInputStream {
+    private static final class DoneHandlerInputStream extends TrackingHTTPInputStream {
         private boolean done;
         
         public DoneHandlerInputStream(InputStream stream) {
@@ -204,6 +279,7 @@ public class FileTransfer extends CordovaPlugin {
         // Look for headers on the params map for backwards compatibility with older Cordova versions.
         final JSONObject headers = args.optJSONObject(8) == null ? params.optJSONObject("headers") : args.optJSONObject(8);
         final String objectId = args.getString(9);
+        final String httpMethod = getArgument(args, 10, "POST");
 
         Log.d(LOG_TAG, "fileKey: " + fileKey);
         Log.d(LOG_TAG, "fileName: " + fileName);
@@ -213,6 +289,7 @@ public class FileTransfer extends CordovaPlugin {
         Log.d(LOG_TAG, "chunkedMode: " + chunkedMode);
         Log.d(LOG_TAG, "headers: " + headers);
         Log.d(LOG_TAG, "objectId: " + objectId);
+        Log.d(LOG_TAG, "httpMethod: " + httpMethod);
         
         final URL url;
         try {
@@ -280,7 +357,7 @@ public class FileTransfer extends CordovaPlugin {
                     conn.setUseCaches(false);
 
                     // Use a post method.
-                    conn.setRequestMethod("POST");
+                    conn.setRequestMethod(httpMethod);
                     conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
 
                     // Set the cookies on the response
@@ -407,7 +484,7 @@ public class FileTransfer extends CordovaPlugin {
                     int responseCode = conn.getResponseCode();
                     Log.d(LOG_TAG, "response code: " + responseCode);
                     Log.d(LOG_TAG, "response headers: " + conn.getHeaderFields());
-                    InputStream inStream = null;
+                    TrackingInputStream inStream = null;
                     try {
                         inStream = getInputStream(conn);
                         synchronized (context) {
@@ -483,11 +560,15 @@ public class FileTransfer extends CordovaPlugin {
         }
     }
 
-    private static InputStream getInputStream(URLConnection conn) throws IOException {
+    private static TrackingInputStream getInputStream(URLConnection conn) throws IOException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
             return new DoneHandlerInputStream(conn.getInputStream());
         }
-        return conn.getInputStream();
+        String encoding = conn.getContentEncoding();
+        if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
+        	return new TrackingGZIPInputStream(new ExposedGZIPInputStream(conn.getInputStream()));
+        }
+        return new TrackingHTTPInputStream(conn.getInputStream());
     }
 
     // always verify the host - don't check for certificate
@@ -698,6 +779,9 @@ public class FileTransfer extends CordovaPlugin {
                     {
                         connection.setRequestProperty("cookie", cookie);
                     }
+                    
+                    // This must be explicitly set for gzip progress tracking to work.
+                    connection.setRequestProperty("Accept-Encoding", "gzip");
 
                     // Handle the other headers
                     if (headers != null) {
@@ -709,14 +793,15 @@ public class FileTransfer extends CordovaPlugin {
                     Log.d(LOG_TAG, "Download file:" + url);
 
                     FileProgressResult progress = new FileProgressResult();
-                    if (connection.getContentEncoding() == null) {
-                        // Only trust content-length header if no gzip etc
+                    if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) {
+                        // Only trust content-length header if we understand
+                        // the encoding -- identity or gzip
                         progress.setLengthComputable(true);
                         progress.setTotal(connection.getContentLength());
                     }
                     
                     FileOutputStream outputStream = null;
-                    InputStream inputStream = null;
+                    TrackingInputStream inputStream = null;
                     
                     try {
                         inputStream = getInputStream(connection);
@@ -731,12 +816,10 @@ public class FileTransfer extends CordovaPlugin {
                         // write bytes to file
                         byte[] buffer = new byte[MAX_BUFFER_SIZE];
                         int bytesRead = 0;
-                        long totalBytes = 0;
                         while ((bytesRead = inputStream.read(buffer)) > 0) {
                             outputStream.write(buffer, 0, bytesRead);
-                            totalBytes += bytesRead;
                             // Send a progress event.
-                            progress.setLoaded(totalBytes);
+                            progress.setLoaded(inputStream.getTotalRawBytesRead());
                             PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
                             progressResult.setKeepCallback(true);
                             context.sendPluginResult(progressResult);

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java b/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
old mode 100755
new mode 100644
index e7cdce0..4a07b73
--- a/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
@@ -38,7 +38,7 @@ import android.location.LocationManager;
 public class GeoBroker extends CordovaPlugin {
     private GPSListener gpsListener;
     private NetworkListener networkListener;
-    private LocationManager locationManager;
+    private LocationManager locationManager;    
 
     /**
      * Constructor.
@@ -73,7 +73,7 @@ public class GeoBroker extends CordovaPlugin {
                     PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(last));
                     callbackContext.sendPluginResult(result);
                 } else {
-                    this.getCurrentLocation(callbackContext, enableHighAccuracy);
+                    this.getCurrentLocation(callbackContext, enableHighAccuracy, args.optInt(2, 60000));
                 }
             }
             else if (action.equals("addWatch")) {
@@ -102,11 +102,11 @@ public class GeoBroker extends CordovaPlugin {
         this.networkListener.clearWatch(id);
     }
 
-    private void getCurrentLocation(CallbackContext callbackContext, boolean enableHighAccuracy) {
+    private void getCurrentLocation(CallbackContext callbackContext, boolean enableHighAccuracy, int timeout) {
         if (enableHighAccuracy) {
-            this.gpsListener.addCallback(callbackContext);
+            this.gpsListener.addCallback(callbackContext, timeout);
         } else {
-            this.networkListener.addCallback(callbackContext);
+            this.networkListener.addCallback(callbackContext, timeout);
         }
     }
 
@@ -160,8 +160,9 @@ public class GeoBroker extends CordovaPlugin {
         return o;
     }
 
-    public void win(Location loc, CallbackContext callbackContext) {
-        PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc));
+    public void win(Location loc, CallbackContext callbackContext, boolean keepCallback) {
+    	PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc));
+    	result.setKeepCallback(keepCallback);
         callbackContext.sendPluginResult(result);
     }
 
@@ -172,7 +173,7 @@ public class GeoBroker extends CordovaPlugin {
      * @param msg			The error message
      * @throws JSONException 
      */
-    public void fail(int code, String msg, CallbackContext callbackContext) {
+    public void fail(int code, String msg, CallbackContext callbackContext, boolean keepCallback) {
         JSONObject obj = new JSONObject();
         String backup = null;
         try {
@@ -189,6 +190,7 @@ public class GeoBroker extends CordovaPlugin {
             result = new PluginResult(PluginResult.Status.ERROR, backup);
         }
 
+        result.setKeepCallback(keepCallback);
         callbackContext.sendPluginResult(result);
     }
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/71fb3725/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
index 2142714..375282e 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
@@ -24,11 +24,12 @@ import java.io.InputStream;
 import org.apache.cordova.api.CordovaInterface;
 import org.apache.cordova.api.LOG;
 
-import android.content.res.AssetManager;
-import android.net.Uri;
+import android.annotation.TargetApi;
+import android.os.Build;
 import android.webkit.WebResourceResponse;
 import android.webkit.WebView;
 
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
 public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
 
 
@@ -43,34 +44,20 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
     @Override
     public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
         if(url.contains("?") || url.contains("#") || needsIceCreamSpaceInAssetUrlFix(url)){
-            return generateWebResourceResponse(url);
-        } else {
-            return super.shouldInterceptRequest(view, url);
+            WebResourceResponse ret = generateWebResourceResponse(url);
+            if (ret != null) {
+                return ret;
+            }
         }
+        return super.shouldInterceptRequest(view, url);
     }
 
     private WebResourceResponse generateWebResourceResponse(String url) {
-        final String ANDROID_ASSET = "file:///android_asset/";
-        if (url.startsWith(ANDROID_ASSET)) {
-            String niceUrl = url;
-            niceUrl = url.replaceFirst(ANDROID_ASSET, "");
-            if(niceUrl.contains("?")){
-                niceUrl = niceUrl.split("\\?")[0];
-            }
-            else if(niceUrl.contains("#"))
-            {
-                niceUrl = niceUrl.split("#")[0];
-            }
-
-            String mimetype = null;
-            if(niceUrl.endsWith(".html")){
-                mimetype = "text/html";
-            }
+        if (url.startsWith("file:///android_asset/")) {
+            String mimetype = FileHelper.getMimeType(url, cordova);
 
             try {
-                AssetManager assets = cordova.getActivity().getAssets();
-                Uri uri = Uri.parse(niceUrl);
-                InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING);
+                InputStream stream = FileHelper.getInputStreamFromUriString(url, cordova);
                 WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream);
                 return response;
             } catch (IOException e) {