diff options
Diffstat (limited to 'phonegap/android_cordova.js')
-rwxr-xr-x | phonegap/android_cordova.js | 974 |
1 files changed, 531 insertions, 443 deletions
diff --git a/phonegap/android_cordova.js b/phonegap/android_cordova.js index 3e59432ed..9e7fa8ec2 100755 --- a/phonegap/android_cordova.js +++ b/phonegap/android_cordova.js @@ -1,6 +1,6 @@ -// commit ac0a3990438f4a89faa993316fb5614f61cf3be6 +// commit 143f5221a6251c9cbccdedc57005c61551b97f12 -// File generated at :: Tue Jun 05 2012 14:14:16 GMT-0700 (PDT) +// File generated at :: Wed Sep 12 2012 12:51:58 GMT-0700 (PDT) /* Licensed to the Apache Software Foundation (ASF) under one @@ -186,11 +186,19 @@ var cordova = { }, /** * Method to fire event from native code + * bNoDetach is required for events which cause an exception which needs to be caught in native code */ - fireDocumentEvent: function(type, data) { + fireDocumentEvent: function(type, data, bNoDetach) { var evt = createEvent(type, data); if (typeof documentEventHandlers[type] != 'undefined') { - documentEventHandlers[type].fire(evt); + if( bNoDetach ) { + documentEventHandlers[type].fire(evt); + } + else { + setTimeout(function() { + documentEventHandlers[type].fire(evt); + }, 0); + } } else { document.dispatchEvent(evt); } @@ -198,15 +206,13 @@ var cordova = { fireWindowEvent: function(type, data) { var evt = createEvent(type,data); if (typeof windowEventHandlers[type] != 'undefined') { - windowEventHandlers[type].fire(evt); + setTimeout(function() { + windowEventHandlers[type].fire(evt); + }, 0); } else { window.dispatchEvent(evt); } }, - // TODO: this is Android only; think about how to do this better - shuttingDown:false, - UsePolling:false, - // END TODO // TODO: iOS only // This queue holds the currently executing command and all pending @@ -285,17 +291,6 @@ var cordova = { } } }, - // TODO: remove in 2.0. - addPlugin: function(name, obj) { - console.log("[DEPRECATION NOTICE] window.addPlugin and window.plugins will be removed in version 2.0."); - if (!window.plugins[name]) { - window.plugins[name] = obj; - } - else { - console.log("Error: Plugin "+name+" already exists."); - } - }, - addConstructor: function(func) { channel.onCordovaReady.subscribeOnce(function() { try { @@ -312,51 +307,6 @@ channel.onPause = cordova.addDocumentEventHandler('pause'); channel.onResume = cordova.addDocumentEventHandler('resume'); channel.onDeviceReady = cordova.addDocumentEventHandler('deviceready'); -// Adds deprecation warnings to functions of an object (but only logs a message once) -function deprecateFunctions(obj, objLabel) { - var newObj = {}; - var logHash = {}; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - if (typeof obj[i] == 'function') { - newObj[i] = (function(prop){ - var oldFunk = obj[prop]; - var funkId = objLabel + '_' + prop; - return function() { - if (!logHash[funkId]) { - console.log('[DEPRECATION NOTICE] The "' + objLabel + '" global will be removed in version 2.0, please use lowercase "cordova".'); - logHash[funkId] = true; - } - oldFunk.apply(obj, arguments); - }; - })(i); - } else { - newObj[i] = (function(prop) { return obj[prop]; })(i); - } - } - } - return newObj; -} - -/** - * Legacy variable for plugin support - * TODO: remove in 2.0. - */ -if (!window.PhoneGap) { - window.PhoneGap = deprecateFunctions(cordova, 'PhoneGap'); -} -if (!window.Cordova) { - window.Cordova = deprecateFunctions(cordova, 'Cordova'); -} - -/** - * Plugins object - * TODO: remove in 2.0. - */ -if (!window.plugins) { - window.plugins = {}; -} - module.exports = cordova; }); @@ -456,7 +406,8 @@ module.exports = { // file: lib/common/channel.js define("cordova/channel", function(require, exports, module) { -var utils = require('cordova/utils'); +var utils = require('cordova/utils'), + nextGuid = 1; /** * Custom pub-sub "channel" that can have functions subscribed to it @@ -508,7 +459,6 @@ var Channel = function(type, opts) { this.type = type; this.handlers = {}; this.numHandlers = 0; - this.guid = 1; this.fired = false; this.enabled = true; this.events = { @@ -601,19 +551,19 @@ Channel.prototype.subscribe = function(f, c, g) { g = g || func.observer_guid || f.observer_guid; if (!g) { - // first time we've seen this subscriber - g = this.guid++; - } - else { - // subscriber already handled; dont set it twice - return g; + // first time any channel has seen this subscriber + g = nextGuid++; } func.observer_guid = g; f.observer_guid = g; - this.handlers[g] = func; - this.numHandlers++; - if (this.events.onSubscribe) this.events.onSubscribe.call(this); - if (this.fired) func.call(this); + + // Don't add the same handler more than once. + if (!this.handlers[g]) { + this.handlers[g] = func; + this.numHandlers++; + if (this.events.onSubscribe) this.events.onSubscribe.call(this); + if (this.fired) func.apply(this, this.fireArgs); + } return g; }; @@ -627,15 +577,14 @@ Channel.prototype.subscribeOnce = function(f, c) { var g = null; var _this = this; - var m = function() { - f.apply(c || null, arguments); - _this.unsubscribe(g); - }; if (this.fired) { - if (typeof c == "object") { f = utils.close(c, f); } - f.apply(this, this.fireArgs); + f.apply(c || null, this.fireArgs); } else { - g = this.subscribe(m); + g = this.subscribe(function() { + _this.unsubscribe(g); + f.apply(c || null, arguments); + }); + f.observer_guid = g; } return g; }; @@ -651,7 +600,6 @@ Channel.prototype.unsubscribe = function(g) { var handler = this.handlers[g]; if (handler) { if (handler.observer_guid) handler.observer_guid=null; - this.handlers[g] = null; delete this.handlers[g]; this.numHandlers--; if (this.events.onUnsubscribe) this.events.onUnsubscribe.call(this); @@ -665,14 +613,17 @@ Channel.prototype.fire = function(e) { if (this.enabled) { var fail = false; this.fired = true; + this.fireArgs = arguments; + // Copy the values first so that it is safe to modify it from within + // callbacks. + var toCall = []; for (var item in this.handlers) { - var handler = this.handlers[item]; - if (typeof handler == 'function') { - var rv = (handler.apply(this, arguments)===false); - fail = fail || rv; - } + toCall.push(this.handlers[item]); + } + for (var i = 0; i < toCall.length; ++i) { + var rv = (toCall[i].apply(this, arguments)===false); + fail = fail || rv; } - this.fireArgs = arguments; return !fail; } return true; @@ -709,7 +660,6 @@ channel.create('onDestroy'); // Channels that must fire before "deviceready" is fired. channel.waitForInitialization('onCordovaReady'); -channel.waitForInitialization('onCordovaInfoReady'); channel.waitForInitialization('onCordovaConnectionReady'); module.exports = channel; @@ -738,13 +688,6 @@ module.exports = { } } }, - PhoneGap:{ - children: { - exec: { - path: 'cordova/exec' - } - } - }, navigator: { children: { notification: { @@ -844,6 +787,9 @@ module.exports = { Coordinates: { path: 'cordova/plugin/Coordinates' }, + device: { + path: 'cordova/plugin/device' + }, DirectoryEntry: { path: 'cordova/plugin/DirectoryEntry' }, @@ -940,76 +886,170 @@ define("cordova/exec", function(require, exports, module) { * @param {String} action Action to be run in cordova * @param {String[]} [args] Zero or more arguments to pass to the method */ -var cordova = require('cordova'); +var cordova = require('cordova'), + callback = require('cordova/plugin/android/callback'), + polling = require('cordova/plugin/android/polling'), + jsToNativeBridgeMode, + nativeToJsBridgeMode, + jsToNativeModes = { + PROMPT: 0, + JS_OBJECT: 1, + // This mode is currently for benchmarking purposes only. It must be enabled + // on the native side through the ENABLE_LOCATION_CHANGE_EXEC_MODE + // constant within CordovaWebViewClient.java before it will work. + LOCATION_CHANGE: 2 + }, + nativeToJsModes = { + // Polls for messages using the prompt() bridge. + POLLING: 0, + // Does an XHR to a local server, which will send back messages. This is + // broken on ICS when a proxy server is configured. + HANGING_GET: 1, + // For LOAD_URL to be viable, it would need to have a work-around for + // the bug where the soft-keyboard gets dismissed when a message is sent. + LOAD_URL: 2, + // For the ONLINE_EVENT to be viable, it would need to intercept all event + // listeners (both through addEventListener and window.ononline) as well + // as set the navigator property itself. + ONLINE_EVENT: 3, + // Uses reflection to access private APIs of the WebView that can send JS + // to be executed. + // Requires Android 3.2.4 or above. + PRIVATE_API: 4 + }; -module.exports = function(success, fail, service, action, args) { - try { - var callbackId = service + cordova.callbackId++; - if (success || fail) { - cordova.callbacks[callbackId] = {success:success, fail:fail}; +function androidExec(success, fail, service, action, args) { + // Set default bridge modes if they have not already been set. + if (jsToNativeBridgeMode === undefined) { + androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT); + } + if (nativeToJsBridgeMode === undefined) { + if (callback.isAvailable()) { + androidExec.setNativeToJsBridgeMode(nativeToJsModes.HANGING_GET); + } else { + androidExec.setNativeToJsBridgeMode(nativeToJsModes.POLLING); + } } + try { + var callbackId = service + cordova.callbackId++, + argsJson = JSON.stringify(args), + result; + if (success || fail) { + cordova.callbacks[callbackId] = {success:success, fail:fail}; + } - var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, action, callbackId, true])); + if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) { + window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson; + } else if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT) { + // Explicit cast to string is required on Android 2.1 to convert from + // a Java string to a JS string. + result = '' + _cordovaExec.exec(service, action, callbackId, argsJson); + } else { + result = prompt(argsJson, "gap:"+JSON.stringify([service, action, callbackId, true])); + } - // If a result was returned - if (r.length > 0) { - var v; - eval("v="+r+";"); + // If a result was returned + if (result) { + var v = JSON.parse(result); + + // If status is OK, then return value back to caller + if (v.status === cordova.callbackStatus.OK) { + + // If there is a success callback, then call it now with + // returned value + if (success) { + try { + success(v.message); + } catch (e) { + console.log("Error in success callback: " + callbackId + " = " + e); + } - // If status is OK, then return value back to caller - if (v.status === cordova.callbackStatus.OK) { + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete cordova.callbacks[callbackId]; + } + } + return v.message; + } - // If there is a success callback, then call it now with - // returned value - if (success) { - try { - success(v.message); - } catch (e) { - console.log("Error in success callback: " + callbackId + " = " + e); - } + // If no result + else if (v.status === cordova.callbackStatus.NO_RESULT) { + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete cordova.callbacks[callbackId]; + } + } - // Clear callback if not expecting any more results - if (!v.keepCallback) { - delete cordova.callbacks[callbackId]; - } - } - return v.message; - } + // If error, then display error + else { + console.log("Error: Status="+v.status+" Message="+v.message); - // If no result - else if (v.status === cordova.callbackStatus.NO_RESULT) { - // Clear callback if not expecting any more results - if (!v.keepCallback) { - delete cordova.callbacks[callbackId]; - } - } + // If there is a fail callback, then call it now with returned value + if (fail) { + try { + fail(v.message); + } + catch (e1) { + console.log("Error in error callback: "+callbackId+" = "+e1); + } - // If error, then display error - else { - console.log("Error: Status="+v.status+" Message="+v.message); + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete cordova.callbacks[callbackId]; + } + } + return null; + } + } + } catch (e2) { + console.log("Error: "+e2); + } +} - // If there is a fail callback, then call it now with returned value - if (fail) { - try { - fail(v.message); - } - catch (e1) { - console.log("Error in error callback: "+callbackId+" = "+e1); - } +function onOnLineEvent(e) { + while (polling.pollOnce()); +} - // Clear callback if not expecting any more results - if (!v.keepCallback) { - delete cordova.callbacks[callbackId]; - } - } - return null; - } +androidExec.jsToNativeModes = jsToNativeModes; +androidExec.nativeToJsModes = nativeToJsModes; + +androidExec.setJsToNativeBridgeMode = function(mode) { + if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaExec) { + console.log('Falling back on PROMPT mode since _cordovaExec is missing.'); + mode = jsToNativeModes.PROMPT; } - } catch (e2) { - console.log("Error: "+e2); - } + jsToNativeBridgeMode = mode; }; +androidExec.setNativeToJsBridgeMode = function(mode) { + if (mode == nativeToJsBridgeMode) { + return; + } + if (nativeToJsBridgeMode == nativeToJsModes.POLLING) { + polling.stop(); + } else if (nativeToJsBridgeMode == nativeToJsModes.HANGING_GET) { + callback.stop(); + } else if (nativeToJsBridgeMode == nativeToJsModes.ONLINE_EVENT) { + window.removeEventListener('online', onOnLineEvent, false); + window.removeEventListener('offline', onOnLineEvent, false); + } + + nativeToJsBridgeMode = mode; + // Tell the native side to switch modes. + prompt(mode, "gap_bridge_mode:"); + + if (mode == nativeToJsModes.POLLING) { + polling.start(); + } else if (mode == nativeToJsModes.HANGING_GET) { + callback.start(); + } else if (mode == nativeToJsModes.ONLINE_EVENT) { + window.addEventListener('online', onOnLineEvent, false); + window.addEventListener('offline', onOnLineEvent, false); + } +}; + +module.exports = androidExec; + }); // file: lib/android/platform.js @@ -1019,34 +1059,8 @@ module.exports = { initialize:function() { var channel = require("cordova/channel"), cordova = require('cordova'), - callback = require('cordova/plugin/android/callback'), - polling = require('cordova/plugin/android/polling'), exec = require('cordova/exec'); - channel.onDestroy.subscribe(function() { - cordova.shuttingDown = true; - }); - - // Start listening for XHR callbacks - // Figure out which bridge approach will work on this Android - // device: polling or XHR-based callbacks - setTimeout(function() { - if (cordova.UsePolling) { - polling(); - } - else { - var isPolling = prompt("usePolling", "gap_callbackServer:"); - cordova.UsePolling = isPolling; - if (isPolling == "true") { - cordova.UsePolling = true; - polling(); - } else { - cordova.UsePolling = false; - callback(); - } - } - }, 1); - // Inject a listener for the backbutton on the document. var backButtonChannel = cordova.addDocumentEventHandler('backbutton', { onSubscribe:function() { @@ -1111,7 +1125,7 @@ module.exports = { // Let native code know we are all done on the JS side. // Native code will then un-hide the WebView. channel.join(function() { - prompt("", "gap_init:"); + exec(null, null, "App", "show", []); }, [channel.onCordovaReady]); }, objects: { @@ -1132,9 +1146,6 @@ module.exports = { } } }, - device:{ - path: "cordova/plugin/android/device" - }, File: { // exists natively on Android WebView, override path: "cordova/plugin/File" }, @@ -1149,6 +1160,9 @@ module.exports = { } }, merges: { + device: { + path: 'cordova/plugin/android/device' + }, navigator: { children: { notification: { @@ -1281,7 +1295,14 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) { popoverOptions = options.popoverOptions; } - exec(successCallback, errorCallback, "Camera", "takePicture", [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType, mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions]); + var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType, + mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions]; + + exec(successCallback, errorCallback, "Camera", "takePicture", args); +}; + +cameraExport.cleanup = function(successCallback, errorCallback) { + exec(successCallback, errorCallback, "Camera", "cleanup", []); }; module.exports = cameraExport; @@ -1866,7 +1887,7 @@ var utils = require('cordova/utils'), * {boolean} isDirectory always true (readonly) * {DOMString} name of the directory, excluding the path leading to it (readonly) * {DOMString} fullPath the absolute full path to the directory (readonly) - * {FileSystem} filesystem on which the directory resides (readonly) + * TODO: implement this!!! {FileSystem} filesystem on which the directory resides (readonly) */ var DirectoryEntry = function(name, fullPath) { DirectoryEntry.__super__.constructor.apply(this, [false, true, name, fullPath]); @@ -2596,11 +2617,13 @@ var FileSystem = function(name, root) { }; module.exports = FileSystem; + }); // file: lib/common/plugin/FileTransfer.js define("cordova/plugin/FileTransfer", function(require, exports, module) { -var exec = require('cordova/exec'); +var exec = require('cordova/exec'), + FileTransferError = require('cordova/plugin/FileTransferError'); /** * FileTransfer uploads a file to a remote server. @@ -2619,16 +2642,20 @@ var FileTransfer = function() {}; * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false */ FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) { + // sanity parameter checking + if (!filePath || !server) throw new Error("FileTransfer.upload requires filePath and server URL parameters at the minimum."); // check for options var fileKey = null; var fileName = null; var mimeType = null; var params = null; var chunkedMode = true; + var headers = null; if (options) { fileKey = options.fileKey; fileName = options.fileName; mimeType = options.mimeType; + headers = options.headers; if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") { chunkedMode = options.chunkedMode; } @@ -2640,7 +2667,12 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro } } - exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode]); + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + + exec(successCallback, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers]); }; /** @@ -2651,6 +2683,8 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro * @param errorCallback {Function} Callback to be invoked upon error */ FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) { + // sanity parameter checking + if (!source || !target) throw new Error("FileTransfer.download requires source URI and target URI parameters at the minimum."); var win = function(result) { var entry = null; if (result.isDirectory) { @@ -2665,6 +2699,12 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro entry.fullPath = result.fullPath; successCallback(entry); }; + + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + exec(win, errorCallback, 'FileTransfer', 'download', [source, target]); }; @@ -2678,8 +2718,11 @@ define("cordova/plugin/FileTransferError", function(require, exports, module) { * FileTransferError * @constructor */ -var FileTransferError = function(code) { +var FileTransferError = function(code, source, target, status) { this.code = code || null; + this.source = source || null; + this.target = target || null; + this.http_status = status || null; }; FileTransferError.FILE_NOT_FOUND_ERR = 1; @@ -2687,6 +2730,7 @@ FileTransferError.INVALID_URL_ERR = 2; FileTransferError.CONNECTION_ERR = 3; module.exports = FileTransferError; + }); // file: lib/common/plugin/FileUploadOptions.js @@ -2698,15 +2742,19 @@ define("cordova/plugin/FileUploadOptions", function(require, exports, module) { * @param fileName {String} Filename to be used by the server. Defaults to image.jpg. * @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg. * @param params {Object} Object with key: value params to send to the server. + * @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) { +var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers) { this.fileKey = fileKey || null; this.fileName = fileName || null; this.mimeType = mimeType || null; this.params = params || null; + this.headers = headers || null; }; module.exports = FileUploadOptions; + }); // file: lib/common/plugin/FileUploadResult.js @@ -2894,7 +2942,7 @@ FileWriter.prototype.seek = function(offset) { if (offset < 0) { this.position = Math.max(offset + this.length, 0); } - // Offset is bigger then file size so set position + // Offset is bigger than file size so set position // to the end of the file. else if (offset > this.length) { this.position = this.length; @@ -3101,7 +3149,6 @@ Media.prototype.stop = function() { var me = this; exec(function() { me._position = 0; - me.successCallback(); }, this.errorCallback, "Media", "stopPlayingAudio", [this.id]); }; @@ -3147,14 +3194,14 @@ Media.prototype.getCurrentPosition = function(success, fail) { * Start recording audio file. */ Media.prototype.startRecord = function() { - exec(this.successCallback, this.errorCallback, "Media", "startRecordingAudio", [this.id, this.src]); + exec(null, this.errorCallback, "Media", "startRecordingAudio", [this.id, this.src]); }; /** * Stop recording audio file. */ Media.prototype.stopRecord = function() { - exec(this.successCallback, this.errorCallback, "Media", "stopRecordingAudio", [this.id]); + exec(null, this.errorCallback, "Media", "stopRecordingAudio", [this.id]); }; /** @@ -3176,34 +3223,39 @@ Media.prototype.setVolume = function(volume) { * PRIVATE * * @param id The media object id (string) - * @param status The status code (int) - * @param msg The status message (string) + * @param msgType The 'type' of update this is + * @param value Use of value is determined by the msgType */ -Media.onStatus = function(id, msg, value) { +Media.onStatus = function(id, msgType, value) { + var media = mediaObjects[id]; - // If state update - if (msg === Media.MEDIA_STATE) { - if (value === Media.MEDIA_STOPPED) { - if (media.successCallback) { - media.successCallback(); - } - } - if (media.statusCallback) { - media.statusCallback(value); - } - } - else if (msg === Media.MEDIA_DURATION) { - media._duration = value; - } - else if (msg === Media.MEDIA_ERROR) { - if (media.errorCallback) { - // value should be a MediaError object when msg == MEDIA_ERROR - media.errorCallback(value); + + if(media) { + switch(msgType) { + case Media.MEDIA_STATE : + media.statusCallback && media.statusCallback(value); + if(value == Media.MEDIA_STOPPED) { + media.successCallback && media.successCallback(); + } + break; + case Media.MEDIA_DURATION : + media._duration = value; + break; + case Media.MEDIA_ERROR : + media.errorCallback && media.errorCallback(value); + break; + case Media.MEDIA_POSITION : + media._position = Number(value); + break; + default : + console && console.error && console.error("Unhandled Media.onStatus :: " + msgType); + break; } } - else if (msg === Media.MEDIA_POSITION) { - media._position = value; + else { + console && console.error && console.error("Received Media.onStatus callback for unknown media :: " + id); } + }; module.exports = Media; @@ -3213,20 +3265,36 @@ module.exports = Media; define("cordova/plugin/MediaError", function(require, exports, module) { /** * This class contains information about any Media errors. - * @constructor +*/ +/* + According to :: http://dev.w3.org/html5/spec-author-view/video.html#mediaerror + We should never be creating these objects, we should just implement the interface + which has 1 property for an instance, 'code' + + instead of doing : + errorCallbackFunction( new MediaError(3,'msg') ); +we should simply use a literal : + errorCallbackFunction( {'code':3} ); */ -var MediaError = function(code, msg) { - this.code = (code !== undefined ? code : null); - this.message = msg || ""; -}; -MediaError.MEDIA_ERR_NONE_ACTIVE = 0; -MediaError.MEDIA_ERR_ABORTED = 1; -MediaError.MEDIA_ERR_NETWORK = 2; -MediaError.MEDIA_ERR_DECODE = 3; -MediaError.MEDIA_ERR_NONE_SUPPORTED = 4; +if(!MediaError) { + var MediaError = function(code, msg) { + this.code = (typeof code != 'undefined') ? code : null; + this.message = msg || ""; // message is NON-standard! do not use! + }; +} + +MediaError.MEDIA_ERR_NONE_ACTIVE = MediaError.MEDIA_ERR_NONE_ACTIVE || 0; +MediaError.MEDIA_ERR_ABORTED = MediaError.MEDIA_ERR_ABORTED || 1; +MediaError.MEDIA_ERR_NETWORK = MediaError.MEDIA_ERR_NETWORK || 2; +MediaError.MEDIA_ERR_DECODE = MediaError.MEDIA_ERR_DECODE || 3; +MediaError.MEDIA_ERR_NONE_SUPPORTED = MediaError.MEDIA_ERR_NONE_SUPPORTED || 4; +// TODO: MediaError.MEDIA_ERR_NONE_SUPPORTED is legacy, the W3 spec now defines it as below. +// as defined by http://dev.w3.org/html5/spec-author-view/video.html#error-codes +MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED || 4; module.exports = MediaError; + }); // file: lib/common/plugin/MediaFile.js @@ -3264,28 +3332,6 @@ MediaFile.prototype.getFormatData = function(successCallback, errorCallback) { } }; -// TODO: can we axe this? -/** - * Casts a PluginResult message property (array of objects) to an array of MediaFile objects - * (used in Objective-C and Android) - * - * @param {PluginResult} pluginResult - */ -MediaFile.cast = function(pluginResult) { - var mediaFiles = []; - for (var i=0; i<pluginResult.message.length; i++) { - var mediaFile = new MediaFile(); - mediaFile.name = pluginResult.message[i].name; - mediaFile.fullPath = pluginResult.message[i].fullPath; - mediaFile.type = pluginResult.message[i].type; - mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate; - mediaFile.size = pluginResult.message[i].size; - mediaFiles.push(mediaFile); - } - pluginResult.message = mediaFiles; - return pluginResult; -}; - module.exports = MediaFile; }); @@ -3491,12 +3537,12 @@ var accelerometer = { var p; var win = function(a) { - successCallback(a); removeListeners(p); + successCallback(a); }; var fail = function(e) { - errorCallback(e); removeListeners(p); + errorCallback(e); }; p = createCallbackPair(win, fail); @@ -3528,8 +3574,8 @@ var accelerometer = { var id = utils.createUUID(); var p = createCallbackPair(function(){}, function(e) { - errorCallback(e); removeListeners(p); + errorCallback(e); }); listeners.push(p); @@ -3544,7 +3590,10 @@ var accelerometer = { if (running) { // If we're already running then immediately invoke the success callback - successCallback(accel); + // but only if we have retrieved a value, sample code does not check for null ... + if(accel) { + successCallback(accel); + } } else { start(); } @@ -3650,186 +3699,126 @@ module.exports = { define("cordova/plugin/android/callback", function(require, exports, module) { var port = null, token = null, - cordova = require('cordova'), - polling = require('cordova/plugin/android/polling'), - callback = function() { - // Exit if shutting down app - if (cordova.shuttingDown) { - return; - } - - // If polling flag was changed, start using polling from now on - if (cordova.UsePolling) { - polling(); - return; - } + xmlhttp; - var xmlhttp = new XMLHttpRequest(); +function startXhr() { + // cordova/exec depends on this module, so we can't require cordova/exec on the module level. + var exec = require('cordova/exec'), + xmlhttp = new XMLHttpRequest(); - // Callback function when XMLHttpRequest is ready - xmlhttp.onreadystatechange=function(){ - if(xmlhttp.readyState === 4){ - - // Exit if shutting down app - if (cordova.shuttingDown) { - return; - } + // Callback function when XMLHttpRequest is ready + xmlhttp.onreadystatechange=function(){ + if (!xmlhttp) { + return; + } + if (xmlhttp.readyState === 4){ + // If callback has JavaScript statement to execute + if (xmlhttp.status === 200) { - // If callback has JavaScript statement to execute - if (xmlhttp.status === 200) { - - // Need to url decode the response - var msg = decodeURIComponent(xmlhttp.responseText); - setTimeout(function() { - try { - var t = eval(msg); - } - catch (e) { - // If we're getting an error here, seeing the message will help in debugging - console.log("JSCallback: Message from Server: " + msg); - console.log("JSCallback Error: "+e); - } - }, 1); - setTimeout(callback, 1); - } + // Need to url decode the response + var msg = decodeURIComponent(xmlhttp.responseText); + setTimeout(function() { + try { + var t = eval(msg); + } + catch (e) { + // If we're getting an error here, seeing the message will help in debugging + console.log("JSCallback: Message from Server: " + msg); + console.log("JSCallback Error: "+e); + } + }, 1); + setTimeout(startXhr, 1); + } - // If callback ping (used to keep XHR request from timing out) - else if (xmlhttp.status === 404) { - setTimeout(callback, 10); - } + // If callback ping (used to keep XHR request from timing out) + else if (xmlhttp.status === 404) { + setTimeout(startXhr, 10); + } - // If security error - else if (xmlhttp.status === 403) { - console.log("JSCallback Error: Invalid token. Stopping callbacks."); - } + // 0 == Page is unloading. + // 400 == Bad request. + // 403 == invalid token. + // 503 == server stopped. + else { + console.log("JSCallback Error: Request failed with status " + xmlhttp.status); + exec.setNativeToJsBridgeMode(exec.nativeToJsModes.POLLING); + } + } + }; - // If server is stopping - else if (xmlhttp.status === 503) { - console.log("JSCallback Server Closed: Stopping callbacks."); - } + if (port === null) { + port = prompt("getPort", "gap_callbackServer:"); + } + if (token === null) { + token = prompt("getToken", "gap_callbackServer:"); + } + xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true); + xmlhttp.send(); +} - // If request wasn't GET - else if (xmlhttp.status === 400) { - console.log("JSCallback Error: Bad request. Stopping callbacks."); - } +module.exports = { + start: function() { + startXhr(); + }, - // If error, revert to polling - else { - console.log("JSCallback Error: Request failed."); - cordova.UsePolling = true; - polling(); - } - } - }; + stop: function() { + if (xmlhttp) { + var tmp = xmlhttp; + xmlhttp = null; + tmp.abort(); + } + }, - if (port === null) { - port = prompt("getPort", "gap_callbackServer:"); - } - if (token === null) { - token = prompt("getToken", "gap_callbackServer:"); - } - xmlhttp.open("GET", "http://127.0.0.1:"+port+"/"+token , true); - xmlhttp.send(); + isAvailable: function() { + return ("true" != prompt("usePolling", "gap_callbackServer:")); + } }; -module.exports = callback; + }); // file: lib/android/plugin/android/device.js define("cordova/plugin/android/device", function(require, exports, module) { var channel = require('cordova/channel'), utils = require('cordova/utils'), - exec = require('cordova/exec'); - -/** - * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the - * phone, etc. - * @constructor - */ -function Device() { - this.available = false; - this.platform = null; - this.version = null; - this.name = null; - this.uuid = null; - this.cordova = null; - - var me = this; - - channel.onCordovaReady.subscribeOnce(function() { - me.getInfo(function(info) { - me.available = true; - me.platform = info.platform; - me.version = info.version; - me.name = info.name; - me.uuid = info.uuid; - me.cordova = info.cordova; - channel.onCordovaInfoReady.fire(); - },function(e) { - me.available = false; - utils.alert("[ERROR] Error initializing Cordova: " + e); - }); - }); -} + exec = require('cordova/exec'), + app = require('cordova/plugin/android/app'); -/** - * Get device info - * - * @param {Function} successCallback The function to call when the heading data is available - * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) - */ -Device.prototype.getInfo = function(successCallback, errorCallback) { +module.exports = { + /* + * DEPRECATED + * This is only for Android. + * + * You must explicitly override the back button. + */ + overrideBackButton:function() { + console.log("Device.overrideBackButton() is deprecated. Use App.overrideBackbutton(true)."); + app.overrideBackbutton(true); + }, - // successCallback required - if (typeof successCallback !== "function") { - console.log("Device Error: successCallback is not a function"); - return; - } + /* + * DEPRECATED + * This is only for Android. + * + * This resets the back button to the default behaviour + */ + resetBackButton:function() { + console.log("Device.resetBackButton() is deprecated. Use App.overrideBackbutton(false)."); + app.overrideBackbutton(false); + }, - // errorCallback optional - if (errorCallback && (typeof errorCallback !== "function")) { - console.log("Device Error: errorCallback is not a function"); - return; + /* + * DEPRECATED + * This is only for Android. + * + * This terminates the activity! + */ + exitApp:function() { + console.log("Device.exitApp() is deprecated. Use App.exitApp()."); + app.exitApp(); } - - // Get info - exec(successCallback, errorCallback, "Device", "getDeviceInfo", []); }; -/* - * DEPRECATED - * This is only for Android. - * - * You must explicitly override the back button. - */ -Device.prototype.overrideBackButton = function() { - console.log("Device.overrideBackButton() is deprecated. Use App.overrideBackbutton(true)."); - navigator.app.overrideBackbutton(true); -}; - -/* - * DEPRECATED - * This is only for Android. - * - * This resets the back button to the default behaviour - */ -Device.prototype.resetBackButton = function() { - console.log("Device.resetBackButton() is deprecated. Use App.overrideBackbutton(false)."); - navigator.app.overrideBackbutton(false); -}; - -/* - * DEPRECATED - * This is only for Android. - * - * This terminates the activity! - */ -Device.prototype.exitApp = function() { - console.log("Device.exitApp() is deprecated. Use App.exitApp()."); - navigator.app.exitApp(); -}; - -module.exports = new Device(); }); // file: lib/android/plugin/android/notification.js @@ -3892,38 +3881,47 @@ module.exports = { // file: lib/android/plugin/android/polling.js define("cordova/plugin/android/polling", function(require, exports, module) { var cordova = require('cordova'), - period = 50, - polling = function() { - // Exit if shutting down app - if (cordova.shuttingDown) { - return; - } + POLL_INTERVAL = 50, + enabled = false; - // If polling flag was changed, stop using polling from now on and switch to XHR server / callback - if (!cordova.UsePolling) { - require('cordova/plugin/android/callback')(); - return; - } +function pollOnce() { + var msg = prompt("", "gap_poll:"); + if (msg) { + try { + eval(""+msg); + } + catch (e) { + console.log("JSCallbackPolling: Message from Server: " + msg); + console.log("JSCallbackPolling Error: "+e); + } + return true; + } + return false; +} - var msg = prompt("", "gap_poll:"); - if (msg) { - setTimeout(function() { - try { - var t = eval(""+msg); - } - catch (e) { - console.log("JSCallbackPolling: Message from Server: " + msg); - console.log("JSCallbackPolling Error: "+e); - } - }, 1); - setTimeout(polling, 1); - } - else { - setTimeout(polling, period); - } +function doPoll() { + if (!enabled) { + return; + } + var nextDelay = POLL_INTERVAL; + if (pollOnce()) { + nextDelay = 0; + } + setTimeout(doPoll, nextDelay); +} + +module.exports = { + start: function() { + enabled = true; + setTimeout(doPoll, 1); + }, + stop: function() { + enabled = false; + }, + pollOnce: pollOnce }; -module.exports = polling; + }); // file: lib/android/plugin/android/storage.js @@ -4796,7 +4794,7 @@ var contacts = { * This function creates a new contact, but it does not persist the contact * to device storage. To persist the contact to device storage, invoke * contact.save(). - * @param properties an object who's properties will be examined to create a new Contact + * @param properties an object whose properties will be examined to create a new Contact * @returns new Contact object */ create:function(properties) { @@ -4815,6 +4813,93 @@ module.exports = contacts; }); +// file: lib/common/plugin/device.js +define("cordova/plugin/device", function(require, exports, module) { +var channel = require('cordova/channel'), + utils = require('cordova/utils'), + exec = require('cordova/exec'); + +// Tell cordova channel to wait on the CordovaInfoReady event +channel.waitForInitialization('onCordovaInfoReady'); + +/** + * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * phone, etc. + * @constructor + */ +function Device() { + this.available = false; + this.platform = null; + this.version = null; + this.name = null; + this.uuid = null; + this.cordova = null; + + var me = this; + + channel.onCordovaReady.subscribeOnce(function() { + me.getInfo(function(info) { + me.available = true; + me.platform = info.platform; + me.version = info.version; + me.name = info.name; + me.uuid = info.uuid; + me.cordova = info.cordova; + channel.onCordovaInfoReady.fire(); + },function(e) { + me.available = false; + utils.alert("[ERROR] Error initializing Cordova: " + e); + }); + }); +} + +/** + * Get device info + * + * @param {Function} successCallback The function to call when the heading data is available + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + */ +Device.prototype.getInfo = function(successCallback, errorCallback) { + + // successCallback required + if (typeof successCallback !== "function") { + console.log("Device Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback !== "function")) { + console.log("Device Error: errorCallback is not a function"); + return; + } + + // Get info + exec(successCallback, errorCallback, "Device", "getDeviceInfo", []); +}; + +module.exports = new Device(); + +}); + +// file: lib/common/plugin/echo.js +define("cordova/plugin/echo", function(require, exports, module) { +var exec = require('cordova/exec'); + +/** + * Sends the given message through exec() to the Echo plugink, which sends it back to the successCallback. + * @param successCallback invoked with a FileSystem object + * @param errorCallback invoked if error occurs retrieving file system + * @param message The string to be echoed. + * @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'; + exec(successCallback, errorCallback, "Echo", action, [message]); +}; + + +}); + // file: lib/common/plugin/geolocation.js define("cordova/plugin/geolocation", function(require, exports, module) { var utils = require('cordova/utils'), @@ -4923,7 +5008,7 @@ var geolocation = { } else if (options.timeout === 0) { fail({ code:PositionError.TIMEOUT, - message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceed's provided PositionOptions' maximumAge parameter." + message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceeds provided PositionOptions' maximumAge parameter." }); // Otherwise we have to call into native to retrieve a position. } else { @@ -5087,7 +5172,7 @@ CurrentLevel = LevelsMap.WARN; * * The value used determines which messages get printed. The logging * values above are in order, and only messages logged at the logging - * level or above will actually be displayed to the user. Eg, the + * level or above will actually be displayed to the user. E.g., the * default level is WARN, so only messages logged with LOG, ERROR, or * WARN will be displayed; INFO and DEBUG messages will be ignored. */ @@ -5466,6 +5551,9 @@ define("cordova/plugin/splashscreen", function(require, exports, module) { var exec = require('cordova/exec'); var splashscreen = { + show:function() { + exec(null, null, "SplashScreen", "show", []); + }, hide:function() { exec(null, null, "SplashScreen", "hide", []); } @@ -5723,4 +5811,4 @@ window.cordova = require('cordova'); }(window)); -})();
\ No newline at end of file +})();var PhoneGap = cordova; |