From a705b727400665aa03716e87995994877d60a15e Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 10 May 2012 15:50:02 -0700 Subject: [PATCH] CB-481 refactored prompt() call in JS to exec, moved showing of webview out of chrome client and into app plugin (so we can invoke via exec) --- framework/assets/js/cordova.android.js | 450 +++++++++++++----- framework/src/org/apache/cordova/App.java | 10 + .../apache/cordova/CordovaChromeClient.java | 8 - 3 files changed, 351 insertions(+), 117 deletions(-) diff --git a/framework/assets/js/cordova.android.js b/framework/assets/js/cordova.android.js index abd2a0d9..f4a3478e 100644 --- a/framework/assets/js/cordova.android.js +++ b/framework/assets/js/cordova.android.js @@ -1,6 +1,6 @@ -// commit 1c9ac3578a369dcb35b168c3e2d7ce2e89d45d12 +// commit 9a080cc2704171a4169739b2c94ca55427b92f93 -// File generated at :: Tue May 01 2012 13:42:28 GMT-0700 (PDT) +// File generated at :: Thu May 10 2012 15:48:14 GMT-0700 (PDT) /* Licensed to the Apache Software Foundation (ASF) under one @@ -349,10 +349,10 @@ function deprecateFunctions(obj, objLabel) { * TODO: remove in 2.0. */ if (!window.PhoneGap) { - window.PhoneGap = cordova; + window.PhoneGap = deprecateFunctions(cordova, 'PhoneGap'); } if (!window.Cordova) { - window.Cordova = cordova; + window.Cordova = deprecateFunctions(cordova, 'Cordova'); } /** @@ -645,10 +645,13 @@ Channel.prototype.unsubscribe = function(g) { if (g === null || g === undefined) { throw "You must pass _something_ into Channel.unsubscribe"; } if (typeof g == 'function') { g = g.observer_guid; } - this.handlers[g] = null; - delete this.handlers[g]; - this.numHandlers--; - if (this.events.onUnsubscribe) this.events.onUnsubscribe.call(this); + var handler = this.handlers[g]; + if (handler) { + this.handlers[g] = null; + delete this.handlers[g]; + this.numHandlers--; + if (this.events.onUnsubscribe) this.events.onUnsubscribe.call(this); + } }; /** @@ -721,6 +724,20 @@ module.exports = { } } }, + Cordova: { + children: { + exec: { + path: 'cordova/exec' + } + } + }, + PhoneGap:{ + children: { + exec: { + path: 'cordova/exec' + } + } + }, navigator: { children: { notification: { @@ -757,6 +774,9 @@ module.exports = { path: 'cordova/plugin/network' } } + }, + splashscreen: { + path: 'cordova/plugin/splashscreen' } } }, @@ -891,6 +911,7 @@ module.exports = { } } }; + }); // file: lib/android/exec.js @@ -1080,7 +1101,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(function(){}, function(){}, 'App', 'show', []); }, [channel.onCordovaReady]); }, objects: { @@ -1127,6 +1148,7 @@ module.exports = { } } }; + }); // file: lib/common/plugin/Acceleration.js @@ -1763,15 +1785,20 @@ var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { /** * The altitude of the position. */ - this.altitude = alt; + this.altitude = (alt !== undefined ? alt : null); /** * The direction the device is moving at the position. */ - this.heading = head; + this.heading = (head !== undefined ? head : null); /** * The velocity with which the device is moving at the position. */ - this.speed = vel; + this.speed = (vel !== undefined ? vel : null); + + if (this.speed === 0 || this.speed === null) { + this.heading = NaN; + } + /** * The altitude accuracy of the position. */ @@ -1779,6 +1806,7 @@ var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { }; module.exports = Coordinates; + }); // file: lib/common/plugin/DirectoryEntry.js @@ -1962,6 +1990,21 @@ Entry.prototype.getMetadata = function(successCallback, errorCallback) { exec(success, fail, "File", "getMetadata", [this.fullPath]); }; +/** + * Set the metadata of the entry. + * + * @param successCallback + * {Function} is called with a Metadata object + * @param errorCallback + * {Function} is called with a FileError + * @param metadataObject + * {Object} keys and values to set + */ +Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) { + + exec(successCallback, errorCallback, "File", "setMetadata", [this.fullPath, metadataObject]); +}; + /** * Move a file or directory to a new location. * @@ -3246,11 +3289,16 @@ define("cordova/plugin/Position", function(require, exports, module) { var Coordinates = require('cordova/plugin/Coordinates'); var Position = function(coords, timestamp) { - this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy); + if (coords) { + this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy); + } else { + this.coords = new Coordinates(); + } this.timestamp = (timestamp !== undefined) ? timestamp : new Date().getTime(); }; module.exports = Position; + }); // file: lib/common/plugin/PositionError.js @@ -4508,27 +4556,45 @@ var timers = {}; // list of timers in use // Returns default params, overrides if provided with values function parseParameters(options) { var opt = { - maximumAge: 10000, + maximumAge: 0, enableHighAccuracy: false, - timeout: 10000 + timeout: Infinity }; if (options) { - if (options.maximumAge !== undefined) { + if (options.maximumAge !== undefined && !isNaN(options.maximumAge) && options.maximumAge > 0) { opt.maximumAge = options.maximumAge; } if (options.enableHighAccuracy !== undefined) { opt.enableHighAccuracy = options.enableHighAccuracy; } - if (options.timeout !== undefined) { - opt.timeout = options.timeout; + if (options.timeout !== undefined && !isNaN(options.timeout)) { + if (options.timeout < 0) { + opt.timeout = 0; + } else { + opt.timeout = options.timeout; + } } } return opt; } +// Returns a timeout failure, closed over a specified timeout value and error callback. +function createTimeout(errorCallback, timeout) { + var t = setTimeout(function() { + clearTimeout(t); + t = null; + errorCallback({ + code:PositionError.TIMEOUT, + message:"Position retrieval timed out." + }); + }, timeout); + return t; +} + var geolocation = { + lastPosition:null, // reference to last known (cached) position returned /** * Asynchronously aquires the current position. * @@ -4537,10 +4603,24 @@ var geolocation = { * @param {PositionOptions} options The options for getting the position data. (OPTIONAL) */ getCurrentPosition:function(successCallback, errorCallback, options) { + if (arguments.length === 0) { + throw new Error("getCurrentPosition must be called with at least one argument."); + } options = parseParameters(options); + // Timer var that will fire an error callback if no position is retrieved from native + // before the "timeout" param provided expires + var timeoutTimer = null; + var win = function(p) { - successCallback(new Position( + clearTimeout(timeoutTimer); + if (!timeoutTimer) { + // Timeout already happened, or native fired error callback for + // this geo request. + // Don't continue with success callback. + return; + } + var pos = new Position( { latitude:p.latitude, longitude:p.longitude, @@ -4551,13 +4631,45 @@ var geolocation = { altitudeAccuracy:p.altitudeAccuracy }, p.timestamp || new Date() - )); + ); + geolocation.lastPosition = pos; + successCallback(pos); }; var fail = function(e) { - errorCallback(new PositionError(e.code, e.message)); + clearTimeout(timeoutTimer); + timeoutTimer = null; + var err = new PositionError(e.code, e.message); + if (errorCallback) { + errorCallback(err); + } }; - exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]); + // Check our cached position, if its timestamp difference with current time is less than the maximumAge, then just + // fire the success callback with the cached position. + if (geolocation.lastPosition && options.maximumAge && (((new Date()).getTime() - geolocation.lastPosition.timestamp.getTime()) <= options.maximumAge)) { + successCallback(geolocation.lastPosition); + // If the cached position check failed and the timeout was set to 0, error out with a TIMEOUT error object. + } 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." + }); + // Otherwise we have to call into native to retrieve a position. + } else { + if (options.timeout !== Infinity) { + // If the timeout value was not set to Infinity (default), then + // set up a timeout function that will fire the error callback + // if no successful position was retrieved before timeout expired. + timeoutTimer = createTimeout(fail, options.timeout); + } else { + // This is here so the check in the win function doesn't mess stuff up + // may seem weird but this guarantees timeoutTimer is + // always truthy before we call into native + timeoutTimer = true; + } + exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.maximumAge]); + } + return timeoutTimer; }, /** * Asynchronously watches the geolocation for changes to geolocation. When a change occurs, @@ -4569,12 +4681,46 @@ var geolocation = { * @return String The watch id that must be passed to #clearWatch to stop watching. */ watchPosition:function(successCallback, errorCallback, options) { + if (arguments.length === 0) { + throw new Error("watchPosition must be called with at least one argument."); + } options = parseParameters(options); var id = utils.createUUID(); - timers[id] = window.setInterval(function() { - geolocation.getCurrentPosition(successCallback, errorCallback, options); - }, options.timeout); + + // Tell device to get a position ASAP, and also retrieve a reference to the timeout timer generated in getCurrentPosition + timers[id] = geolocation.getCurrentPosition(successCallback, errorCallback, options); + + var fail = function(e) { + clearTimeout(timers[id]); + var err = new PositionError(e.code, e.message); + if (errorCallback) { + errorCallback(err); + } + }; + + var win = function(p) { + clearTimeout(timers[id]); + if (options.timeout !== Infinity) { + timers[id] = createTimeout(fail, options.timeout); + } + var pos = new Position( + { + latitude:p.latitude, + longitude:p.longitude, + altitude:p.altitude, + accuracy:p.accuracy, + heading:p.heading, + velocity:p.velocity, + altitudeAccuracy:p.altitudeAccuracy + }, + p.timestamp || new Date() + ); + geolocation.lastPosition = pos; + successCallback(pos); + }; + + exec(win, fail, "Geolocation", "addWatch", [id, options.enableHighAccuracy]); return id; }, @@ -4585,13 +4731,15 @@ var geolocation = { */ clearWatch:function(id) { if (id && timers[id] !== undefined) { - window.clearInterval(timers[id]); + clearTimeout(timers[id]); delete timers[id]; + exec(null, null, "Geolocation", "clearWatch", [id]); } } }; module.exports = geolocation; + }); // file: lib/common/plugin/network.js @@ -4809,8 +4957,165 @@ module.exports = function(uri, successCallback, errorCallback) { }); +// file: lib/common/plugin/splashscreen.js +define("cordova/plugin/splashscreen", function(require, exports, module) { +var exec = require('cordova/exec'); + +var splashscreen = { + hide:function() { + exec(null, null, "SplashScreen", "hide", []); + } +}; + +module.exports = splashscreen; +}); + // file: lib/common/utils.js define("cordova/utils", function(require, exports, module) { +var utils = exports; + +/** + * Returns an indication of whether the argument is an array or not + */ +utils.isArray = function(a) { + return Object.prototype.toString.call(a) == '[object Array]'; +}; + +/** + * Returns an indication of whether the argument is a Date or not + */ +utils.isDate = function(d) { + return Object.prototype.toString.call(d) == '[object Date]'; +}; + +/** + * Does a deep clone of the object. + */ +utils.clone = function(obj) { + if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') { + return obj; + } + + var retVal, i; + + if(utils.isArray(obj)){ + retVal = []; + for(i = 0; i < obj.length; ++i){ + retVal.push(utils.clone(obj[i])); + } + return retVal; + } + + retVal = {}; + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = utils.clone(obj[i]); + } + } + return retVal; +}; + +/** + * Returns a wrappered version of the function + */ +utils.close = function(context, func, params) { + if (typeof params == 'undefined') { + return function() { + return func.apply(context, arguments); + }; + } else { + return function() { + return func.apply(context, params); + }; + } +}; + +/** + * Create a UUID + */ +utils.createUUID = function() { + return UUIDcreatePart(4) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(2) + '-' + + UUIDcreatePart(6); +}; + +/** + * Extends a child object from a parent object using classical inheritance + * pattern. + */ +utils.extend = (function() { + // proxy used to establish prototype chain + var F = function() {}; + // extend Child from Parent + return function(Child, Parent) { + F.prototype = Parent.prototype; + Child.prototype = new F(); + Child.__super__ = Parent.prototype; + Child.prototype.constructor = Child; + }; +}()); + +/** + * Alerts a message in any available way: alert or console.log. + */ +utils.alert = function(msg) { + if (alert) { + alert(msg); + } else if (console && console.log) { + console.log(msg); + } +}; + +/** + * Formats a string and arguments following it ala sprintf() + * + * 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.format = function(formatString /* ,... */) { + if (formatString === null || formatString === undefined) return ""; + if (arguments.length == 1) return formatString.toString(); + + var pattern = /(.*?)%(.)(.*)/; + var rest = formatString.toString(); + var result = []; + var args = [].slice.call(arguments,1); + + 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) { var uuidpart = ""; for (var i=0; i