Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1C12CF4D9 for ; Thu, 9 May 2013 23:00:11 +0000 (UTC) Received: (qmail 18100 invoked by uid 500); 9 May 2013 23:00:06 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 18037 invoked by uid 500); 9 May 2013 23:00:06 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 16409 invoked by uid 99); 9 May 2013 23:00:04 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 May 2013 23:00:04 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 72FEF88AC89; Thu, 9 May 2013 23:00:04 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: anis@apache.org To: commits@cordova.apache.org Date: Thu, 09 May 2013 23:00:37 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [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 watches = new HashMap(); private List callbacks = new ArrayList(); + + 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 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 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) {