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 D165A10E59 for ; Fri, 14 Jun 2013 22:31:34 +0000 (UTC) Received: (qmail 60542 invoked by uid 500); 14 Jun 2013 22:31:34 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 60510 invoked by uid 500); 14 Jun 2013 22:31:34 -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 60430 invoked by uid 99); 14 Jun 2013 22:31:34 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Jun 2013 22:31:34 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 745868817E5; Fri, 14 Jun 2013 22:31:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: bowserj@apache.org To: commits@cordova.apache.org Date: Fri, 14 Jun 2013 22:31:34 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [1/2] android commit: Updating the JS used in the tests Updated Branches: refs/heads/master d2a7d1806 -> 668982727 Updating the JS used in the tests Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/86a24ebd Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/86a24ebd Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/86a24ebd Branch: refs/heads/master Commit: 86a24ebd0f4801df14a73530ff165a7c3c26bf9c Parents: d2a7d18 Author: Joe Bowser Authored: Fri Jun 14 15:31:03 2013 -0700 Committer: Joe Bowser Committed: Fri Jun 14 15:31:03 2013 -0700 ---------------------------------------------------------------------- test/assets/www/cordova.android.js | 1555 +++++++++++++++++++------------ 1 file changed, 950 insertions(+), 605 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-android/blob/86a24ebd/test/assets/www/cordova.android.js ---------------------------------------------------------------------- diff --git a/test/assets/www/cordova.android.js b/test/assets/www/cordova.android.js index a2c90ce..5e460e4 100644 --- a/test/assets/www/cordova.android.js +++ b/test/assets/www/cordova.android.js @@ -1,7 +1,5 @@ -// commit 71223711fb1591b1255d871140d959fd9095f0c3 - -// File generated at :: Mon Jan 21 2013 13:45:08 GMT-0800 (PST) - +// Platform: android +// 2.8.0-0-g6208c95 /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -20,26 +18,36 @@ specific language governing permissions and limitations under the License. */ - ;(function() { - +var CORDOVA_JS_BUILD_LABEL = '2.8.0-0-g6208c95'; // file: lib/scripts/require.js var require, define; (function () { - var modules = {}; + var modules = {}, // Stack of moduleIds currently being built. - var requireStack = []; + requireStack = [], // Map of module ID -> index into requireStack of modules currently being built. - var inProgressModules = {}; + inProgressModules = {}, + SEPERATOR = "."; + + function build(module) { - var factory = module.factory; + var factory = module.factory, + localRequire = function (id) { + var resultantId = id; + //Its a relative path, so lop off the last portion and add the id (minus "./") + if (id.charAt(0) === ".") { + resultantId = module.id.slice(0, module.id.lastIndexOf(SEPERATOR)) + SEPERATOR + id.slice(2); + } + return require(resultantId); + }; module.exports = {}; delete module.factory; - factory(require, module.exports, module); + factory(localRequire, module.exports, module); return module.exports; } @@ -217,6 +225,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); } @@ -260,7 +272,7 @@ var cordova = { */ callbackSuccess: function(callbackId, args) { try { - cordova.callbackFromNative(callbackId, true, args.status, args.message, args.keepCallback); + cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback); } catch (e) { console.log("Error in error callback: " + callbackId + " = "+e); } @@ -273,7 +285,7 @@ var cordova = { // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative. // Derive success from status. try { - cordova.callbackFromNative(callbackId, false, args.status, args.message, args.keepCallback); + cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback); } catch (e) { console.log("Error in error callback: " + callbackId + " = "+e); } @@ -282,13 +294,13 @@ var cordova = { /** * Called by native code when returning the result from an action. */ - callbackFromNative: function(callbackId, success, status, message, keepCallback) { + callbackFromNative: function(callbackId, success, status, args, keepCallback) { var callback = cordova.callbacks[callbackId]; if (callback) { if (success && status == cordova.callbackStatus.OK) { - callback.success && callback.success(message); + callback.success && callback.success.apply(null, args); } else if (!success) { - callback.fail && callback.fail(message); + callback.fail && callback.fail.apply(null, args); } // Clear callback if not expecting any more results @@ -397,6 +409,7 @@ function each(objects, func, context) { } function clobber(obj, key, value) { + exports.replaceHookForTesting(obj, key); obj[key] = value; // Getters can only be overridden by getters. if (obj[key] !== value) { @@ -480,19 +493,18 @@ function recursiveMerge(target, src) { } } -module.exports = { - buildIntoButDoNotClobber: function(objects, target) { - include(target, objects, false, false); - }, - buildIntoAndClobber: function(objects, target) { - include(target, objects, true, false); - }, - buildIntoAndMerge: function(objects, target) { - include(target, objects, true, true); - }, - recursiveMerge: recursiveMerge, - assignOrWrapInDeprecateGetter: assignOrWrapInDeprecateGetter +exports.buildIntoButDoNotClobber = function(objects, target) { + include(target, objects, false, false); +}; +exports.buildIntoAndClobber = function(objects, target) { + include(target, objects, true, false); }; +exports.buildIntoAndMerge = function(objects, target) { + include(target, objects, true, true); +}; +exports.recursiveMerge = recursiveMerge; +exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter; +exports.replaceHookForTesting = function() {}; }); @@ -722,6 +734,9 @@ channel.createSticky('onCordovaInfoReady'); // Event to indicate that the connection property has been set. channel.createSticky('onCordovaConnectionReady'); +// Event to indicate that all automatically loaded JS plugins are loaded and ready. +channel.createSticky('onPluginsReady'); + // Event to indicate that Cordova is ready channel.createSticky('onDeviceReady'); @@ -737,6 +752,7 @@ channel.createSticky('onDestroy'); // Channels that must fire before "deviceready" is fired. channel.waitForInitialization('onCordovaReady'); channel.waitForInitialization('onCordovaConnectionReady'); +channel.waitForInitialization('onDOMContentLoaded'); module.exports = channel; @@ -772,176 +788,6 @@ module.exports = { }; }); -// file: lib/common/common.js -define("cordova/common", function(require, exports, module) { - -module.exports = { - defaults: { - cordova: { - path: 'cordova', - children: { - exec: { - path: 'cordova/exec' - }, - logger: { - path: 'cordova/plugin/logger' - } - } - }, - Cordova: { - children: { - exec: { - path: 'cordova/exec' - } - } - }, - open : { - path: 'cordova/plugin/InAppBrowser' - }, - navigator: { - children: { - notification: { - path: 'cordova/plugin/notification' - }, - accelerometer: { - path: 'cordova/plugin/accelerometer' - }, - battery: { - path: 'cordova/plugin/battery' - }, - camera:{ - path: 'cordova/plugin/Camera' - }, - compass:{ - path: 'cordova/plugin/compass' - }, - contacts: { - path: 'cordova/plugin/contacts' - }, - device:{ - children:{ - capture: { - path: 'cordova/plugin/capture' - } - } - }, - geolocation: { - path: 'cordova/plugin/geolocation' - }, - globalization: { - path: 'cordova/plugin/globalization' - }, - network: { - children: { - connection: { - path: 'cordova/plugin/network', - deprecated: 'navigator.network.connection is deprecated. Use navigator.connection instead.' - } - } - }, - splashscreen: { - path: 'cordova/plugin/splashscreen' - } - } - }, - Acceleration: { - path: 'cordova/plugin/Acceleration' - }, - Camera:{ - path: 'cordova/plugin/CameraConstants' - }, - CameraPopoverOptions: { - path: 'cordova/plugin/CameraPopoverOptions' - }, - CaptureError: { - path: 'cordova/plugin/CaptureError' - }, - CaptureAudioOptions:{ - path: 'cordova/plugin/CaptureAudioOptions' - }, - CaptureImageOptions: { - path: 'cordova/plugin/CaptureImageOptions' - }, - CaptureVideoOptions: { - path: 'cordova/plugin/CaptureVideoOptions' - }, - CompassHeading:{ - path: 'cordova/plugin/CompassHeading' - }, - CompassError:{ - path: 'cordova/plugin/CompassError' - }, - ConfigurationData: { - path: 'cordova/plugin/ConfigurationData' - }, - Connection: { - path: 'cordova/plugin/Connection' - }, - Contact: { - path: 'cordova/plugin/Contact' - }, - ContactAddress: { - path: 'cordova/plugin/ContactAddress' - }, - ContactError: { - path: 'cordova/plugin/ContactError' - }, - ContactField: { - path: 'cordova/plugin/ContactField' - }, - ContactFindOptions: { - path: 'cordova/plugin/ContactFindOptions' - }, - ContactName: { - path: 'cordova/plugin/ContactName' - }, - ContactOrganization: { - path: 'cordova/plugin/ContactOrganization' - }, - Coordinates: { - path: 'cordova/plugin/Coordinates' - }, - device: { - path: 'cordova/plugin/device' - }, - GlobalizationError: { - path: 'cordova/plugin/GlobalizationError' - }, - Media: { - path: 'cordova/plugin/Media' - }, - MediaError: { - path: 'cordova/plugin/MediaError' - }, - MediaFile: { - path: 'cordova/plugin/MediaFile' - }, - MediaFileData:{ - path: 'cordova/plugin/MediaFileData' - }, - Position: { - path: 'cordova/plugin/Position' - }, - PositionError: { - path: 'cordova/plugin/PositionError' - }, - ProgressEvent: { - path: 'cordova/plugin/ProgressEvent' - } - }, - clobbers: { - navigator: { - children: { - connection: { - path: 'cordova/plugin/network' - } - } - } - } -}; - -}); - // file: lib/android/exec.js define("cordova/exec", function(require, exports, module) { @@ -1005,32 +851,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() { @@ -1068,7 +909,7 @@ androidExec.nativeToJsModes = nativeToJsModes; androidExec.setJsToNativeBridgeMode = function(mode) { if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) { - console.log('Falling back on PROMPT mode since _cordovaNative is missing.'); + console.log('Falling back on PROMPT mode since _cordovaNative is missing. Expected for Android 3.2 and lower only.'); mode = jsToNativeModes.PROMPT; } nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT); @@ -1126,10 +967,12 @@ function processMessage(message) { arraybuffer[i] = bytes.charCodeAt(i); } payload = arraybuffer.buffer; + } else if (payloadKind == 'S') { + payload = window.atob(message.slice(nextSpaceIdx + 2)); } else { payload = JSON.parse(message.slice(nextSpaceIdx + 1)); } - cordova.callbackFromNative(callbackId, success, status, payload, keepCallback); + cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback); } else { console.log("processMessage failed: invalid message:" + message); } @@ -1144,30 +987,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(); } } } @@ -1220,9 +1063,9 @@ function prepareNamespace(symbolPath, context) { var parts = symbolPath.split('.'); var cur = context; for (var i = 0, part; part = parts[i]; ++i) { - cur[part] = cur[part] || {}; + cur = cur[part] = cur[part] || {}; } - return cur[parts[i-1]]; + return cur; } exports.mapModules = function(context) { @@ -1244,7 +1087,7 @@ exports.mapModules = function(context) { if (strategy == 'm' && target) { builder.recursiveMerge(target, module); } else if ((strategy == 'd' && !target) || (strategy != 'd')) { - if (target) { + if (!(symbolPath in origSymbols)) { origSymbols[symbolPath] = target; } builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg); @@ -1290,6 +1133,8 @@ module.exports = { modulemapper = require('cordova/modulemapper'); modulemapper.loadMatchingModules(/cordova.*\/symbols$/); + modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app'); + modulemapper.mapModules(window); // Inject a listener for the backbutton on the document. @@ -1304,88 +1149,11 @@ module.exports = { cordova.addDocumentEventHandler('menubutton'); cordova.addDocumentEventHandler('searchbutton'); - // Figure out if we need to shim-in localStorage and WebSQL - // support from the native side. - var storage = require('cordova/plugin/android/storage'); - - // First patch WebSQL if necessary - if (typeof window.openDatabase == 'undefined') { - // Not defined, create an openDatabase function for all to use! - window.openDatabase = storage.openDatabase; - } else { - // Defined, but some Android devices will throw a SECURITY_ERR - - // so we wrap the whole thing in a try-catch and shim in our own - // if the device has Android bug 16175. - var originalOpenDatabase = window.openDatabase; - window.openDatabase = function(name, version, desc, size) { - var db = null; - try { - db = originalOpenDatabase(name, version, desc, size); - } - catch (ex) { - if (ex.code === 18) { - db = null; - } else { - throw ex; - } - } - - if (db === null) { - return storage.openDatabase(name, version, desc, size); - } - else { - return db; - } - - }; - } - - // Patch localStorage if necessary - if (typeof window.localStorage == 'undefined' || window.localStorage === null) { - window.localStorage = new storage.CupcakeLocalStorage(); - } - // Let native code know we are all done on the JS side. // Native code will then un-hide the WebView. channel.join(function() { exec(null, null, "App", "show", []); }, [channel.onCordovaReady]); - }, - clobbers: { - navigator: { - children: { - app:{ - path: "cordova/plugin/android/app" - } - } - }, - File: { // exists natively on Android WebView, override - path: "cordova/plugin/File" - }, - FileReader: { // exists natively on Android WebView, override - path: "cordova/plugin/FileReader" - }, - FileError: { //exists natively on Android WebView on Android 4.x - path: "cordova/plugin/FileError" - }, - MediaError: { // exists natively on Android WebView on Android 4.x - path: "cordova/plugin/MediaError" - }, - open: { - path: "cordova/plugin/InAppBrowser" - } - }, - merges: { - device: { - path: 'cordova/plugin/android/device' - }, - navigator: { - children: { - notification: { - path: 'cordova/plugin/android/notification' - } - } - } } }; @@ -1410,7 +1178,8 @@ define("cordova/plugin/Camera", function(require, exports, module) { var argscheck = require('cordova/argscheck'), exec = require('cordova/exec'), - Camera = require('cordova/plugin/CameraConstants'); + Camera = require('cordova/plugin/CameraConstants'), + CameraPopoverHandle = require('cordova/plugin/CameraPopoverHandle'); var cameraExport = {}; @@ -1445,11 +1214,13 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) { var correctOrientation = !!options.correctOrientation; var saveToPhotoAlbum = !!options.saveToPhotoAlbum; var popoverOptions = getValue(options.popoverOptions, null); + var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK); var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType, - mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions]; + mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection]; exec(successCallback, errorCallback, "Camera", "takePicture", args); + return new CameraPopoverHandle(); }; cameraExport.cleanup = function(successCallback, errorCallback) { @@ -1489,11 +1260,33 @@ module.exports = { ARROW_LEFT : 4, ARROW_RIGHT : 8, ARROW_ANY : 15 + }, + Direction:{ + BACK: 0, + FRONT: 1 } }; }); +// file: lib/common/plugin/CameraPopoverHandle.js +define("cordova/plugin/CameraPopoverHandle", function(require, exports, module) { + +var exec = require('cordova/exec'); + +/** + * A handle to an image picker popover. + */ +var CameraPopoverHandle = function() { + this.setPosition = function(popoverOptions) { + console.log('CameraPopoverHandle.setPosition is only supported on iOS.'); + }; +}; + +module.exports = CameraPopoverHandle; + +}); + // file: lib/common/plugin/CameraPopoverOptions.js define("cordova/plugin/CameraPopoverOptions", function(require, exports, module) { @@ -1527,8 +1320,6 @@ var CaptureAudioOptions = function(){ this.limit = 1; // Maximum duration of a single sound clip in seconds. this.duration = 0; - // The selected audio mode. Must match with one of the elements in supportedAudioModes array. - this.mode = null; }; module.exports = CaptureAudioOptions; @@ -1569,8 +1360,6 @@ define("cordova/plugin/CaptureImageOptions", function(require, exports, module) var CaptureImageOptions = function(){ // Upper limit of images user can take. Value must be equal or greater than 1. this.limit = 1; - // The selected image mode. Must match with one of the elements in supportedImageModes array. - this.mode = null; }; module.exports = CaptureImageOptions; @@ -1588,8 +1377,6 @@ var CaptureVideoOptions = function(){ this.limit = 1; // Maximum duration of a single video clip in seconds. this.duration = 0; - // The selected video mode. Must match with one of the elements in supportedVideoModes array. - this.mode = null; }; module.exports = CaptureVideoOptions; @@ -1619,9 +1406,9 @@ module.exports = CompassError; define("cordova/plugin/CompassHeading", function(require, exports, module) { var CompassHeading = function(magneticHeading, trueHeading, headingAccuracy, timestamp) { - this.magneticHeading = magneticHeading || null; - this.trueHeading = trueHeading || null; - this.headingAccuracy = headingAccuracy || null; + this.magneticHeading = magneticHeading; + this.trueHeading = trueHeading; + this.headingAccuracy = headingAccuracy; this.timestamp = timestamp || new Date().getTime(); }; @@ -1663,6 +1450,7 @@ module.exports = { CELL_2G: "2g", CELL_3G: "3g", CELL_4G: "4g", + CELL:"cellular", NONE: "none" }; @@ -2608,11 +2396,7 @@ function initRead(reader, file) { reader._error = null; reader._readyState = FileReader.LOADING; - if (typeof file == 'string') { - // Deprecated in Cordova 2.4. - console.warning('Using a string argument with FileReader.readAs functions is deprecated.'); - reader._fileName = file; - } else if (typeof file.fullPath == 'string') { + if (typeof file.fullPath == 'string') { reader._fileName = file.fullPath; } else { reader._fileName = ''; @@ -2661,14 +2445,7 @@ FileReader.prototype.readAsText = function(file, encoding) { // Default encoding is UTF-8 var enc = encoding ? encoding : "UTF-8"; var me = this; - var execArgs = [this._fileName, enc]; - - // Maybe add slice parameters. - if (file.end < file.size) { - execArgs.push(file.start, file.end); - } else if (file.start > 0) { - execArgs.push(file.start); - } + var execArgs = [this._fileName, enc, file.start, file.end]; // Read file exec( @@ -2737,14 +2514,7 @@ FileReader.prototype.readAsDataURL = function(file) { } var me = this; - var execArgs = [this._fileName]; - - // Maybe add slice parameters. - if (file.end < file.size) { - execArgs.push(file.start, file.end); - } else if (file.start > 0) { - execArgs.push(file.start); - } + var execArgs = [this._fileName, file.start, file.end]; // Read file exec( @@ -2807,9 +2577,59 @@ FileReader.prototype.readAsBinaryString = function(file) { if (initRead(this, file)) { return this._realReader.readAsBinaryString(file); } - // TODO - Can't return binary data to browser. - console.log('method "readAsBinaryString" is not supported at this time.'); - this.abort(); + + var me = this; + var execArgs = [this._fileName, file.start, file.end]; + + // Read file + exec( + // Success callback + function(r) { + // If DONE (cancelled), then don't do anything + if (me._readyState === FileReader.DONE) { + return; + } + + // DONE state + me._readyState = FileReader.DONE; + + me._result = r; + + // If onload callback + if (typeof me.onload === "function") { + me.onload(new ProgressEvent("load", {target:me})); + } + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend(new ProgressEvent("loadend", {target:me})); + } + }, + // Error callback + function(e) { + // If DONE (cancelled), then don't do anything + if (me._readyState === FileReader.DONE) { + return; + } + + // DONE state + me._readyState = FileReader.DONE; + + me._result = null; + + // Save error + me._error = new FileError(e); + + // If onerror callback + if (typeof me.onerror === "function") { + me.onerror(new ProgressEvent("error", {target:me})); + } + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend(new ProgressEvent("loadend", {target:me})); + } + }, "File", "readAsBinaryString", execArgs); }; /** @@ -2821,9 +2641,59 @@ FileReader.prototype.readAsArrayBuffer = function(file) { if (initRead(this, file)) { return this._realReader.readAsArrayBuffer(file); } - // TODO - Can't return binary data to browser. - console.log('This method is not supported at this time.'); - this.abort(); + + var me = this; + var execArgs = [this._fileName, file.start, file.end]; + + // Read file + exec( + // Success callback + function(r) { + // If DONE (cancelled), then don't do anything + if (me._readyState === FileReader.DONE) { + return; + } + + // DONE state + me._readyState = FileReader.DONE; + + me._result = r; + + // If onload callback + if (typeof me.onload === "function") { + me.onload(new ProgressEvent("load", {target:me})); + } + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend(new ProgressEvent("loadend", {target:me})); + } + }, + // Error callback + function(e) { + // If DONE (cancelled), then don't do anything + if (me._readyState === FileReader.DONE) { + return; + } + + // DONE state + me._readyState = FileReader.DONE; + + me._result = null; + + // Save error + me._error = new FileError(e); + + // If onerror callback + if (typeof me.onerror === "function") { + me.onerror(new ProgressEvent("error", {target:me})); + } + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend(new ProgressEvent("loadend", {target:me})); + } + }, "File", "readAsArrayBuffer", execArgs); }; module.exports = FileReader; @@ -2869,6 +2739,38 @@ function newProgressEvent(result) { return pe; } +function getBasicAuthHeader(urlString) { + var header = null; + + if (window.btoa) { + // parse the url using the Location object + var url = document.createElement('a'); + url.href = urlString; + + var credentials = null; + var protocol = url.protocol + "//"; + var origin = protocol + url.host; + + // check whether there are the username:password credentials in the url + if (url.href.indexOf(origin) !== 0) { // credentials found + var atIndex = url.href.indexOf("@"); + credentials = url.href.substring(protocol.length, atIndex); + } + + if (credentials) { + var authHeader = "Authorization"; + var authHeaderValue = "Basic " + window.btoa(credentials); + + header = { + name : authHeader, + value : authHeaderValue + }; + } + } + + return header; +} + var idCounter = 0; /** @@ -2899,11 +2801,25 @@ 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) { + options = options || {}; + options.headers = options.headers || {}; + options.headers[basicAuthHeader.name] = basicAuthHeader.value; + } + if (options) { fileKey = options.fileKey; 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; } @@ -2916,7 +2832,7 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro } var fail = errorCallback && function(e) { - var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body); errorCallback(error); }; @@ -2930,7 +2846,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]); }; /** @@ -2940,16 +2856,30 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro * @param successCallback (Function} Callback to be invoked when upload has completed * @param errorCallback {Function} Callback to be invoked upon error * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false + * @param options {FileDownloadOptions} Optional parameters such as headers */ -FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts) { +FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts, options) { argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments); var self = this; - var win = function(result) { - if (typeof result.lengthComputable != "undefined") { - if (self.onprogress) { - return self.onprogress(newProgressEvent(result)); - } - } else if (successCallback) { + + var basicAuthHeader = getBasicAuthHeader(source); + if (basicAuthHeader) { + options = options || {}; + options.headers = options.headers || {}; + options.headers[basicAuthHeader.name] = basicAuthHeader.value; + } + + var headers = null; + if (options) { + headers = options.headers || null; + } + + var win = function(result) { + if (typeof result.lengthComputable != "undefined") { + if (self.onprogress) { + return self.onprogress(newProgressEvent(result)); + } + } else if (successCallback) { var entry = null; if (result.isDirectory) { entry = new (require('cordova/plugin/DirectoryEntry'))(); @@ -2966,20 +2896,19 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro }; var fail = errorCallback && function(e) { - var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body); errorCallback(error); }; - exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id]); + exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id, headers]); }; /** - * 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; @@ -2993,11 +2922,12 @@ define("cordova/plugin/FileTransferError", function(require, exports, module) { * FileTransferError * @constructor */ -var FileTransferError = function(code, source, target, status) { +var FileTransferError = function(code, source, target, status, body) { this.code = code || null; this.source = source || null; this.target = target || null; this.http_status = status || null; + this.body = body || null; }; FileTransferError.FILE_NOT_FOUND_ERR = 1; @@ -3022,12 +2952,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; @@ -3362,11 +3293,13 @@ 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 = { 'loadstart': channel.create('loadstart'), 'loadstop' : channel.create('loadstop'), + 'loaderror' : channel.create('loaderror'), 'exit' : channel.create('exit') }; } @@ -3389,6 +3322,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'); + } } }; @@ -3397,12 +3350,17 @@ module.exports = function(strUrl, strWindowName, strWindowFeatures) { var cb = function(eventname) { iab._eventHandler(eventname); }; - exec(cb, null, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]); + + // 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; }; -//Export the original open so it can be used if needed -module.exports._orig = window.open; }); @@ -3973,6 +3931,17 @@ module.exports = accelerometer; }); +// file: lib/common/plugin/accelerometer/symbols.js +define("cordova/plugin/accelerometer/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.defaults('cordova/plugin/Acceleration', 'Acceleration'); +modulemapper.defaults('cordova/plugin/accelerometer', 'navigator.accelerometer'); + +}); + // file: lib/android/plugin/android/app.js define("cordova/plugin/android/app", function(require, exports, module) { @@ -4098,6 +4067,10 @@ module.exports = { // file: lib/android/plugin/android/nativeapiprovider.js define("cordova/plugin/android/nativeapiprovider", function(require, exports, module) { +/** + * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi. + */ + var nativeApi = this._cordovaNative || require('cordova/plugin/android/promptbasednativeapi'); var currentApi = nativeApi; @@ -4176,6 +4149,11 @@ module.exports = { // file: lib/android/plugin/android/promptbasednativeapi.js define("cordova/plugin/android/promptbasednativeapi", function(require, exports, module) { +/** + * Implements the API of ExposedJsApi.java, but uses prompt() to communicate. + * This is used only on the 2.3 simulator, where addJavascriptInterface() is broken. + */ + module.exports = { exec: function(service, action, callbackId, argsJson) { return prompt(argsJson, 'gap:'+JSON.stringify([service, action, callbackId])); @@ -4477,100 +4455,57 @@ var DroidDB_openDatabase = function(name, version, display_name, size) { return db; }; -/** - * For browsers with no localStorage we emulate it with SQLite. Follows the w3c api. - * TODO: Do similar for sessionStorage. - * @constructor - */ -var CupcakeLocalStorage = function() { - channel.waitForInitialization("cupcakeStorage"); - try { +module.exports = { + openDatabase:DroidDB_openDatabase, + failQuery:failQuery, + completeQuery:completeQuery +}; - this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440); - var storage = {}; - this.length = 0; - function setLength (length) { - this.length = length; - localStorage.length = length; - } - this.db.transaction( - function (transaction) { - var i; - transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))'); - transaction.executeSql('SELECT * FROM storage', [], function(tx, result) { - for(var i = 0; i < result.rows.length; i++) { - storage[result.rows.item(i).id] = result.rows.item(i).body; - } - setLength(result.rows.length); - channel.initializationComplete("cupcakeStorage"); - }); +}); - }, - function (err) { - utils.alert(err.message); - } - ); - this.setItem = function(key, val) { - if (typeof(storage[key])=='undefined') { - this.length++; - } - storage[key] = val; - this.db.transaction( - function (transaction) { - transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))'); - transaction.executeSql('REPLACE INTO storage (id, body) values(?,?)', [key,val]); - } - ); - }; - this.getItem = function(key) { - return storage[key]; - }; - this.removeItem = function(key) { - delete storage[key]; - this.length--; - this.db.transaction( - function (transaction) { - transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))'); - transaction.executeSql('DELETE FROM storage where id=?', [key]); - } - ); - }; - this.clear = function() { - storage = {}; - this.length = 0; - this.db.transaction( - function (transaction) { - transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))'); - transaction.executeSql('DELETE FROM storage', []); - } - ); - }; - this.key = function(index) { - var i = 0; - for (var j in storage) { - if (i==index) { - return j; - } else { - i++; - } - } - return null; - }; +// file: lib/android/plugin/android/storage/openDatabase.js +define("cordova/plugin/android/storage/openDatabase", function(require, exports, module) { - } catch(e) { - utils.alert("Database error "+e+"."); - return; + +var modulemapper = require('cordova/modulemapper'), + storage = require('cordova/plugin/android/storage'); + +var originalOpenDatabase = modulemapper.getOriginalSymbol(window, 'openDatabase'); + +module.exports = function(name, version, desc, size) { + // First patch WebSQL if necessary + if (!originalOpenDatabase) { + // Not defined, create an openDatabase function for all to use! + return storage.openDatabase.apply(this, arguments); } -}; -module.exports = { - openDatabase:DroidDB_openDatabase, - CupcakeLocalStorage:CupcakeLocalStorage, - failQuery:failQuery, - completeQuery:completeQuery + // Defined, but some Android devices will throw a SECURITY_ERR - + // so we wrap the whole thing in a try-catch and shim in our own + // if the device has Android bug 16175. + try { + return originalOpenDatabase(name, version, desc, size); + } catch (ex) { + if (ex.code !== 18) { + throw ex; + } + } + return storage.openDatabase(name, version, desc, size); }; + + +}); + +// file: lib/android/plugin/android/storage/symbols.js +define("cordova/plugin/android/storage/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/android/storage/openDatabase', 'openDatabase'); + + }); // file: lib/common/plugin/battery.js @@ -4657,6 +4592,28 @@ module.exports = battery; }); +// file: lib/common/plugin/battery/symbols.js +define("cordova/plugin/battery/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.defaults('cordova/plugin/battery', 'navigator.battery'); + +}); + +// file: lib/common/plugin/camera/symbols.js +define("cordova/plugin/camera/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.defaults('cordova/plugin/Camera', 'navigator.camera'); +modulemapper.defaults('cordova/plugin/CameraConstants', 'Camera'); +modulemapper.defaults('cordova/plugin/CameraPopoverOptions', 'CameraPopoverOptions'); + +}); + // file: lib/common/plugin/capture.js define("cordova/plugin/capture", function(require, exports, module) { @@ -4735,6 +4692,22 @@ module.exports = new Capture(); }); +// file: lib/common/plugin/capture/symbols.js +define("cordova/plugin/capture/symbols", function(require, exports, module) { + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/CaptureError', 'CaptureError'); +modulemapper.clobbers('cordova/plugin/CaptureAudioOptions', 'CaptureAudioOptions'); +modulemapper.clobbers('cordova/plugin/CaptureImageOptions', 'CaptureImageOptions'); +modulemapper.clobbers('cordova/plugin/CaptureVideoOptions', 'CaptureVideoOptions'); +modulemapper.clobbers('cordova/plugin/ConfigurationData', 'ConfigurationData'); +modulemapper.clobbers('cordova/plugin/MediaFile', 'MediaFile'); +modulemapper.clobbers('cordova/plugin/MediaFileData', 'MediaFileData'); +modulemapper.clobbers('cordova/plugin/capture', 'navigator.device.capture'); + +}); + // file: lib/common/plugin/compass.js define("cordova/plugin/compass", function(require, exports, module) { @@ -4822,6 +4795,18 @@ module.exports = compass; }); +// file: lib/common/plugin/compass/symbols.js +define("cordova/plugin/compass/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/CompassHeading', 'CompassHeading'); +modulemapper.clobbers('cordova/plugin/CompassError', 'CompassError'); +modulemapper.clobbers('cordova/plugin/compass', 'navigator.compass'); + +}); + // file: lib/common/plugin/console-via-logger.js define("cordova/plugin/console-via-logger", function(require, exports, module) { @@ -4904,7 +4889,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); }; @@ -5055,6 +5040,23 @@ module.exports = contacts; }); +// file: lib/common/plugin/contacts/symbols.js +define("cordova/plugin/contacts/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/contacts', 'navigator.contacts'); +modulemapper.clobbers('cordova/plugin/Contact', 'Contact'); +modulemapper.clobbers('cordova/plugin/ContactAddress', 'ContactAddress'); +modulemapper.clobbers('cordova/plugin/ContactError', 'ContactError'); +modulemapper.clobbers('cordova/plugin/ContactField', 'ContactField'); +modulemapper.clobbers('cordova/plugin/ContactFindOptions', 'ContactFindOptions'); +modulemapper.clobbers('cordova/plugin/ContactName', 'ContactName'); +modulemapper.clobbers('cordova/plugin/ContactOrganization', 'ContactOrganization'); + +}); + // file: lib/common/plugin/device.js define("cordova/plugin/device", function(require, exports, module) { @@ -5075,7 +5077,6 @@ function Device() { this.available = false; this.platform = null; this.version = null; - this.name = null; this.uuid = null; this.cordova = null; this.model = null; @@ -5084,12 +5085,15 @@ function Device() { channel.onCordovaReady.subscribe(function() { me.getInfo(function(info) { + var buildLabel = info.cordova; + if (buildLabel != CORDOVA_JS_BUILD_LABEL) { + buildLabel += ' JS=' + CORDOVA_JS_BUILD_LABEL; + } me.available = true; me.platform = info.platform; me.version = info.version; - me.name = info.name; me.uuid = info.uuid; - me.cordova = info.cordova; + me.cordova = buildLabel; me.model = info.model; channel.onCordovaInfoReady.fire(); },function(e) { @@ -5114,10 +5118,22 @@ module.exports = new Device(); }); +// file: lib/android/plugin/device/symbols.js +define("cordova/plugin/device/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/device', 'device'); +modulemapper.merges('cordova/plugin/android/device', 'device'); + +}); + // file: lib/common/plugin/echo.js define("cordova/plugin/echo", function(require, exports, module) { -var exec = require('cordova/exec'); +var exec = require('cordova/exec'), + utils = require('cordova/utils'); /** * Sends the given message through exec() to the Echo plugin, which sends it back to the successCallback. @@ -5127,11 +5143,25 @@ var exec = require('cordova/exec'); * @param forceAsync Whether to force an async return value (for testing native->js bridge). */ module.exports = function(successCallback, errorCallback, message, forceAsync) { - var action = forceAsync ? 'echoAsync' : 'echo'; - if (!forceAsync && message.constructor == ArrayBuffer) { - action = 'echoArrayBuffer'; + var action = 'echo'; + var messageIsMultipart = (utils.typeName(message) == "Array"); + var args = messageIsMultipart ? message : [message]; + + if (utils.typeName(message) == 'ArrayBuffer') { + if (forceAsync) { + console.warn('Cannot echo ArrayBuffer with forced async, falling back to sync.'); + } + action += 'ArrayBuffer'; + } else if (messageIsMultipart) { + if (forceAsync) { + console.warn('Cannot echo MultiPart Array with forced async, falling back to sync.'); + } + action += 'MultiPart'; + } else if (forceAsync) { + action += 'Async'; } - exec(successCallback, errorCallback, "Echo", action, [message]); + + exec(successCallback, errorCallback, "Echo", action, args); }; @@ -5160,20 +5190,30 @@ module.exports = function(exportFunc) { exportFunc('cordova/plugin/FileError', 'FileError'); exportFunc('cordova/plugin/FileReader', 'FileReader'); exportFunc('cordova/plugin/FileSystem', 'FileSystem'); - exportFunc('cordova/plugin/FileTransfer', 'FileTransfer'); - exportFunc('cordova/plugin/FileTransferError', 'FileTransferError'); exportFunc('cordova/plugin/FileUploadOptions', 'FileUploadOptions'); exportFunc('cordova/plugin/FileUploadResult', 'FileUploadResult'); exportFunc('cordova/plugin/FileWriter', 'FileWriter'); exportFunc('cordova/plugin/Flags', 'Flags'); exportFunc('cordova/plugin/LocalFileSystem', 'LocalFileSystem'); exportFunc('cordova/plugin/Metadata', 'Metadata'); + exportFunc('cordova/plugin/ProgressEvent', 'ProgressEvent'); exportFunc('cordova/plugin/requestFileSystem', 'requestFileSystem'); exportFunc('cordova/plugin/resolveLocalFileSystemURI', 'resolveLocalFileSystemURI'); }; }); +// file: lib/common/plugin/filetransfer/symbols.js +define("cordova/plugin/filetransfer/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/FileTransfer', 'FileTransfer'); +modulemapper.clobbers('cordova/plugin/FileTransferError', 'FileTransferError'); + +}); + // file: lib/common/plugin/geolocation.js define("cordova/plugin/geolocation", function(require, exports, module) { @@ -5370,6 +5410,19 @@ module.exports = geolocation; }); +// file: lib/common/plugin/geolocation/symbols.js +define("cordova/plugin/geolocation/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.defaults('cordova/plugin/geolocation', 'navigator.geolocation'); +modulemapper.clobbers('cordova/plugin/PositionError', 'PositionError'); +modulemapper.clobbers('cordova/plugin/Position', 'Position'); +modulemapper.clobbers('cordova/plugin/Coordinates', 'Coordinates'); + +}); + // file: lib/common/plugin/globalization.js define("cordova/plugin/globalization", function(require, exports, module) { @@ -5746,6 +5799,27 @@ module.exports = globalization; }); +// file: lib/common/plugin/globalization/symbols.js +define("cordova/plugin/globalization/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/globalization', 'navigator.globalization'); +modulemapper.clobbers('cordova/plugin/GlobalizationError', 'GlobalizationError'); + +}); + +// file: lib/android/plugin/inappbrowser/symbols.js +define("cordova/plugin/inappbrowser/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/InAppBrowser', 'open'); + +}); + // file: lib/common/plugin/logger.js define("cordova/plugin/logger", function(require, exports, module) { @@ -5776,10 +5850,13 @@ var exec = require('cordova/exec'); var utils = require('cordova/utils'); var UseConsole = true; +var UseLogger = true; var Queued = []; var DeviceReady = false; var CurrentLevel; +var originalConsole = console; + /** * Logging levels */ @@ -5840,8 +5917,7 @@ logger.level = function (value) { * Getter/Setter for the useConsole functionality * * When useConsole is true, the logger will log via the - * browser 'console' object. Otherwise, it will use the - * native Logger plugin. + * browser 'console' object. */ logger.useConsole = function (value) { if (arguments.length) UseConsole = !!value; @@ -5866,6 +5942,18 @@ logger.useConsole = function (value) { }; /** + * Getter/Setter for the useLogger functionality + * + * When useLogger is true, the logger will log via the + * native Logger plugin. + */ +logger.useLogger = function (value) { + // Enforce boolean + if (arguments.length) UseLogger = !!value; + return UseLogger; +}; + +/** * Logs a message at the LOG level. * * Parameters passed after message are used applied to @@ -5917,10 +6005,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); @@ -5934,27 +6022,115 @@ logger.logLevel = function(level, message /* , ... */) { return; } - // if not using the console, use the native logger - if (!UseConsole) { + // Log using the native logger if that is enabled + if (UseLogger) { exec(null, null, "Logger", "logLevel", [level, message]); - return; } - // make sure console is not using logger - if (console.__usingCordovaLogger) { - throw new Error("console and logger are too intertwingly"); - } + // Log using the console if that is enabled + if (UseConsole) { + // make sure console is not using logger + if (console.__usingCordovaLogger) { + throw new Error("console and logger are too intertwingly"); + } - // log to the console - switch (level) { - case logger.LOG: console.log(message); break; - case logger.ERROR: console.log("ERROR: " + message); break; - case logger.WARN: console.log("WARN: " + message); break; - case logger.INFO: console.log("INFO: " + message); break; - case logger.DEBUG: console.log("DEBUG: " + message); break; + // log to the console + switch (level) { + case logger.LOG: originalConsole.log(message); break; + case logger.ERROR: originalConsole.log("ERROR: " + message); break; + case logger.WARN: originalConsole.log("WARN: " + message); break; + case logger.INFO: originalConsole.log("INFO: " + message); break; + case logger.DEBUG: originalConsole.log("DEBUG: " + message); break; + } } }; + +/** + * 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; @@ -5974,6 +6150,27 @@ document.addEventListener("deviceready", logger.__onDeviceReady, false); }); +// file: lib/common/plugin/logger/symbols.js +define("cordova/plugin/logger/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/logger', 'cordova.logger'); + +}); + +// file: lib/android/plugin/media/symbols.js +define("cordova/plugin/media/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.defaults('cordova/plugin/Media', 'Media'); +modulemapper.clobbers('cordova/plugin/MediaError', 'MediaError'); + +}); + // file: lib/common/plugin/network.js define("cordova/plugin/network", function(require, exports, module) { @@ -6046,10 +6243,23 @@ module.exports = me; }); +// file: lib/common/plugin/networkstatus/symbols.js +define("cordova/plugin/networkstatus/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/network', 'navigator.network.connection', 'navigator.network.connection is deprecated. Use navigator.connection instead.'); +modulemapper.clobbers('cordova/plugin/network', 'navigator.connection'); +modulemapper.defaults('cordova/plugin/Connection', 'Connection'); + +}); + // file: lib/common/plugin/notification.js define("cordova/plugin/notification", function(require, exports, module) { var exec = require('cordova/exec'); +var platform = require('cordova/platform'); /** * Provides access to notifications on the device. @@ -6078,15 +6288,55 @@ module.exports = { * @param {String} message Message to print in the body of the alert * @param {Function} resultCallback The callback that is called when user clicks on a button. * @param {String} title Title of the alert dialog (default: Confirm) - * @param {String} buttonLabels Comma separated list of the labels of the buttons (default: 'OK,Cancel') + * @param {Array} buttonLabels Array of the labels of the buttons (default: ['OK', 'Cancel']) */ confirm: function(message, resultCallback, title, buttonLabels) { var _title = (title || "Confirm"); - var _buttonLabels = (buttonLabels || "OK,Cancel"); + var _buttonLabels = (buttonLabels || ["OK", "Cancel"]); + + // Strings are deprecated! + if (typeof _buttonLabels === 'string') { + console.log("Notification.confirm(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array)."); + } + + // 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" || platform.id == "windowsphone" || platform.id == "blackberry10") { + if (typeof _buttonLabels === 'string') { + var buttonLabelString = _buttonLabels; + _buttonLabels = _buttonLabels.split(","); // not crazy about changing the var type here + } + } else { + if (Array.isArray(_buttonLabels)) { + var buttonLabelArray = _buttonLabels; + _buttonLabels = buttonLabelArray.toString(); + } + } exec(resultCallback, null, "Notification", "confirm", [message, _title, _buttonLabels]); }, /** + * Open a native prompt dialog, with a customizable title and button text. + * The following results are returned to the result callback: + * buttonIndex Index number of the button selected. + * input1 The text entered in the prompt dialog box. + * + * @param {String} message Dialog message to display (default: "Prompt message") + * @param {Function} resultCallback The callback that is called when user clicks on a button. + * @param {String} title Title of the dialog (default: "Prompt") + * @param {Array} buttonLabels Array of strings for the button labels (default: ["OK","Cancel"]) + * @param {String} defaultText Textbox input value (default: "Default text") + */ + prompt: function(message, resultCallback, title, buttonLabels, defaultText) { + var _message = (message || "Prompt message"); + var _title = (title || "Prompt"); + var _buttonLabels = (buttonLabels || ["OK","Cancel"]); + var _defaultText = (defaultText || "Default text"); + exec(resultCallback, null, "Notification", "prompt", [_message, _title, _buttonLabels, _defaultText]); + }, + + /** * Causes the device to vibrate. * * @param {Integer} mills The number of milliseconds to vibrate for. @@ -6108,6 +6358,17 @@ module.exports = { }); +// file: lib/android/plugin/notification/symbols.js +define("cordova/plugin/notification/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/notification', 'navigator.notification'); +modulemapper.merges('cordova/plugin/android/notification', 'navigator.notification'); + +}); + // file: lib/common/plugin/requestFileSystem.js define("cordova/plugin/requestFileSystem", function(require, exports, module) { @@ -6221,6 +6482,29 @@ module.exports = splashscreen; }); +// file: lib/common/plugin/splashscreen/symbols.js +define("cordova/plugin/splashscreen/symbols", function(require, exports, module) { + + +var modulemapper = require('cordova/modulemapper'); + +modulemapper.clobbers('cordova/plugin/splashscreen', 'navigator.splashscreen'); + +}); + +// file: lib/common/symbols.js +define("cordova/symbols", function(require, exports, module) { + +var modulemapper = require('cordova/modulemapper'); + +// Use merges here in case others symbols files depend on this running first, +// but fail to declare the dependency with a require(). +modulemapper.merges('cordova', 'cordova'); +modulemapper.clobbers('cordova/exec', 'cordova.exec'); +modulemapper.clobbers('cordova/exec', 'Cordova.exec'); + +}); + // file: lib/common/utils.js define("cordova/utils", function(require, exports, module) { @@ -6374,62 +6658,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) { @@ -6444,81 +6672,57 @@ 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(); -} }); - window.cordova = require('cordova'); - // file: lib/scripts/bootstrap.js (function (context) { + if (context._cordovaJsLoaded) { + throw new Error('cordova.js included multiple times.'); + } + context._cordovaJsLoaded = true; + + 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. - if (context.navigator) { + function replaceNavigator(origNavigator) { var CordovaNavigator = function() {}; - CordovaNavigator.prototype = context.navigator; - context.navigator = new CordovaNavigator(); - } - - var channel = require("cordova/channel"), - _self = { - boot: function () { - /** - * Create all cordova objects once page has fully loaded and native side is ready. - */ - channel.join(function() { - var builder = require('cordova/builder'), - base = require('cordova/common'), - platform = require('cordova/platform'); - - // Drop the common globals into the window object, but be nice and don't overwrite anything. - builder.buildIntoButDoNotClobber(base.defaults, context); - builder.buildIntoAndClobber(base.clobbers, context); - builder.buildIntoAndMerge(base.merges, context); - - builder.buildIntoButDoNotClobber(platform.defaults, context); - builder.buildIntoAndClobber(platform.clobbers, context); - builder.buildIntoAndMerge(platform.merges, context); - - // Call the platform-specific initialization - 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. - channel.join(function() { - require('cordova').fireDocumentEvent('deviceready'); - }, channel.deviceReadyChannelsArray); - - }, [ channel.onDOMContentLoaded, channel.onNativeReady ]); + CordovaNavigator.prototype = origNavigator; + var newNavigator = new CordovaNavigator(); + // This work-around really only applies to new APIs that are newer than Function.bind. + // Without it, APIs such as getGamepads() break. + if (CordovaNavigator.bind) { + for (var key in origNavigator) { + if (typeof origNavigator[key] == 'function') { + newNavigator[key] = origNavigator[key].bind(origNavigator); + } } - }; - - // boot up once native side is ready - channel.onNativeReady.subscribe(_self.boot); + } + return newNavigator; + } + if (context.navigator) { + context.navigator = replaceNavigator(context.navigator); + } // _nativeReady is global variable that the native side can set // to signify that the native code is ready. It is a global since @@ -6527,6 +6731,147 @@ window.cordova = require('cordova'); channel.onNativeReady.fire(); } + /** + * Create all cordova objects once native side is ready. + */ + channel.join(function() { + // Call the platform-specific initialization + require('cordova/platform').initialize(); + + // Fire event to notify that all objects are created + channel.onCordovaReady.fire(); + + // 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); + + }, 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. +// This is an async process, but onDeviceReady is blocked on onPluginsReady. +// onPluginsReady is fired when there are no plugins to load, or they are all done. +(function (context) { + // To be populated with the handler by handlePluginsObject. + var onScriptLoadingComplete; + + var scriptCounter = 0; + function scriptLoadedCallback() { + scriptCounter--; + if (scriptCounter === 0) { + onScriptLoadingComplete && onScriptLoadingComplete(); + } + } + + // Helper function to inject a