You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2012/10/03 19:40:24 UTC
ios commit: Tweaks to iOS XHR bridge:
Updated Branches:
refs/heads/master e7b16f4b0 -> a07ed8dad
Tweaks to iOS XHR bridge:
Call [[self client] didReceiveResponse] when simulating a response
- This fixes the CFNetwork log message.
When XHR bundles payload, do not handle the request.
When XHR does *not* bundle payload, use the new "rc" field to only check
for messages once instead of multiple times.
This fixes https://issues.apache.org/jira/browse/CB-1576
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/a07ed8da
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/a07ed8da
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/a07ed8da
Branch: refs/heads/master
Commit: a07ed8dad7360b3f995a376f36710ca9396a057f
Parents: e7b16f4
Author: Andrew Grieve <ag...@chromium.org>
Authored: Wed Oct 3 13:33:33 2012 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Wed Oct 3 13:39:43 2012 -0400
----------------------------------------------------------------------
CordovaLib/Classes/CDVURLProtocol.h | 6 -
CordovaLib/Classes/CDVURLProtocol.m | 74 ++-
CordovaLib/Classes/CDVViewController.h | 6 +-
CordovaLib/Classes/CDVViewController.m | 12 +
bin/templates/project/www/cordova-2.1.0.js | 751 +++++++++++++++++++++--
5 files changed, 755 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a07ed8da/CordovaLib/Classes/CDVURLProtocol.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVURLProtocol.h b/CordovaLib/Classes/CDVURLProtocol.h
index 055b88c..705667a 100644
--- a/CordovaLib/Classes/CDVURLProtocol.h
+++ b/CordovaLib/Classes/CDVURLProtocol.h
@@ -40,9 +40,3 @@
+ (void)registerViewController:(CDVViewController*)viewController;
+ (void)unregisterViewController:(CDVViewController*)viewController;
@end
-
-@interface CDVHTTPURLResponse : NSHTTPURLResponse {}
-
-- (CDVHTTPURLResponse*)initWithUnauthorizedURL:(NSURL*)url;
-
-@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a07ed8da/CordovaLib/Classes/CDVURLProtocol.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVURLProtocol.m b/CordovaLib/Classes/CDVURLProtocol.m
index d14b087..e515a8c 100644
--- a/CordovaLib/Classes/CDVURLProtocol.m
+++ b/CordovaLib/Classes/CDVURLProtocol.m
@@ -21,7 +21,13 @@
#import "CDVWhitelist.h"
#import "CDVViewController.h"
-static CDVWhitelist* gWhitelist = nil;
+@interface CDVHTTPURLResponse : NSHTTPURLResponse
+- (id)initWithUnauthorizedURL:(NSURL*)url;
+- (id)initWithBlankResponse:(NSURL*)url;
+@property (nonatomic) NSInteger statusCode;
+@end
+
+static CDVWhitelist * gWhitelist = nil;
// Contains a set of NSNumbers of addresses of controllers. It doesn't store
// the actual pointer to avoid retaining.
static NSMutableSet* gRegisteredControllers = nil;
@@ -73,22 +79,33 @@ static NSMutableSet* gRegisteredControllers = nil;
}
long long viewControllerAddress = [viewControllerAddressStr longLongValue];
// Ensure that the CDVViewController has not been dealloc'ed.
+ CDVViewController* viewController = nil;
@synchronized(gRegisteredControllers) {
if (![gRegisteredControllers containsObject:[NSNumber numberWithLongLong:viewControllerAddress]]) {
return NO;
}
- CDVViewController* viewController = (__bridge CDVViewController*)(void*)viewControllerAddress;
+ viewController = (__bridge CDVViewController*)(void*)viewControllerAddress;
+ }
- NSString* queuedCommandsJSON = [theRequest valueForHTTPHeaderField:@"cmds"];
- if ([queuedCommandsJSON length] > 0) {
- [viewController performSelectorOnMainThread:@selector(executeCommandsFromJson:) withObject:queuedCommandsJSON waitUntilDone:NO];
- } else {
- [viewController performSelectorOnMainThread:@selector(flushCommandQueue) withObject:nil waitUntilDone:NO];
- }
+ NSString* queuedCommandsJSON = [theRequest valueForHTTPHeaderField:@"cmds"];
+ NSString* requestId = [theRequest valueForHTTPHeaderField:@"rc"];
+ if (requestId == nil) {
+ NSLog(@"!cordova request missing rc header");
+ return NO;
+ }
+ BOOL hasCmds = [queuedCommandsJSON length] > 0;
+ if (hasCmds) {
+ SEL sel = @selector(executeCommandsFromJson:);
+ [viewController performSelectorOnMainThread:sel withObject:queuedCommandsJSON waitUntilDone:NO];
+ } else {
+ SEL sel = @selector(maybeFlushCommandQueue:);
+ [viewController performSelectorOnMainThread:sel withObject:[NSNumber numberWithInteger:[requestId integerValue]] waitUntilDone:NO];
}
// Returning NO here would be 20% faster, but it spams WebInspector's console with failure messages.
// If JS->Native bridge speed is really important for an app, they should use the iframe bridge.
- return YES;
+ // Returning YES here causes the request to come through canInitWithRequest two more times.
+ // For this reason, we return NO when cmds exist.
+ return !hasCmds;
}
// we only care about http and https connections
@@ -112,6 +129,8 @@ static NSMutableSet* gRegisteredControllers = nil;
NSURL* url = [[self request] URL];
if ([[url path] isEqualToString:@"/!gap_exec"]) {
+ CDVHTTPURLResponse* response = [[CDVHTTPURLResponse alloc] initWithBlankResponse:url];
+ [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[[self client] URLProtocolDidFinishLoading:self];
return;
}
@@ -140,28 +159,29 @@ static NSMutableSet* gRegisteredControllers = nil;
@end
@implementation CDVHTTPURLResponse
+@synthesize statusCode;
-- (id)initWithUnauthorizedURL:(__unsafe_unretained NSURL*)url
+- (id)initWithUnauthorizedURL:(NSURL*)url
{
- NSInteger statusCode = 401;
- NSDictionary* __unsafe_unretained headerFields = [NSDictionary dictionaryWithObject:@"Digest realm = \"Cordova.plist/ExternalHosts\"" forKey:@"WWW-Authenticate"];
- double requestTime = 1;
-
- SEL selector = NSSelectorFromString(@"initWithURL:statusCode:headerFields:requestTime:");
- NSMethodSignature* signature = [self methodSignatureForSelector:selector];
-
- NSInvocation* inv = [NSInvocation invocationWithMethodSignature:signature];
-
- [inv setTarget:self];
- [inv setSelector:selector];
- [inv setArgument:&url atIndex:2];
- [inv setArgument:&statusCode atIndex:3];
- [inv setArgument:&headerFields atIndex:4];
- [inv setArgument:&requestTime atIndex:5];
-
- [inv invoke];
+ self = [super initWithURL:url MIMEType:@"text/plain" expectedContentLength:-1 textEncodingName:@"UTF-8"];
+ if (self) {
+ self.statusCode = 401;
+ }
+ return self;
+}
+- (id)initWithBlankResponse:(NSURL*)url
+{
+ self = [super initWithURL:url MIMEType:@"text/plain" expectedContentLength:-1 textEncodingName:@"UTF-8"];
+ if (self) {
+ self.statusCode = 200;
+ }
return self;
}
+- (NSDictionary*)allHeaderFields
+{
+ return nil;
+}
+
@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a07ed8da/CordovaLib/Classes/CDVViewController.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.h b/CordovaLib/Classes/CDVViewController.h
index c867814..fed48aa 100644
--- a/CordovaLib/Classes/CDVViewController.h
+++ b/CordovaLib/Classes/CDVViewController.h
@@ -24,7 +24,10 @@
#import "CDVCommandDelegate.h"
#import "CDVWhitelist.h"
-@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVCommandDelegate>{}
+@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVCommandDelegate>{
+ @private
+ NSInteger _lastCommandQueueFlushRequestId;
+}
@property (nonatomic, strong) IBOutlet CDVCordovaView* webView;
@@ -51,6 +54,7 @@
- (void)createGapView;
- (CDVCordovaView*)newCordovaViewWithFrame:(CGRect)bounds;
+- (void)maybeFlushCommandQueue:(NSNumber*)requestId;
- (int)executeCommandsFromJson:(NSString*)queuedCommandsJSON;
- (void)flushCommandQueue;
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a07ed8da/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index a0a29f0..003059b 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -485,6 +485,7 @@
*/
- (void)webViewDidStartLoad:(UIWebView*)theWebView
{
+ _lastCommandQueueFlushRequestId = 0;
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:nil]];
}
@@ -825,6 +826,17 @@ BOOL gSplashScreenShown = NO;
return [queuedCommands count];
}
+- (void)maybeFlushCommandQueue:(NSNumber*)requestId
+{
+ // Use the request ID to determine if we've already flushed for this request.
+ // This is required only because the NSURLProtocol enqueues the same request
+ // multiple times.
+ if ([requestId integerValue] > _lastCommandQueueFlushRequestId) {
+ _lastCommandQueueFlushRequestId = [requestId integerValue];
+ [self flushCommandQueue];
+ }
+}
+
/**
* Repeatedly fetches and executes the command queue until it is empty.
*/
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/a07ed8da/bin/templates/project/www/cordova-2.1.0.js
----------------------------------------------------------------------
diff --git a/bin/templates/project/www/cordova-2.1.0.js b/bin/templates/project/www/cordova-2.1.0.js
index cce90a9..8d02a6c 100644
--- a/bin/templates/project/www/cordova-2.1.0.js
+++ b/bin/templates/project/www/cordova-2.1.0.js
@@ -1,6 +1,6 @@
-// commit d30179b30152b9383a80637e609cf2d785e1aa3e
+// commit 27d9aedd5bf520f305e20fcf350da2eef244d53d
-// File generated at :: Tue Sep 18 2012 11:34:26 GMT-0400 (EDT)
+// File generated at :: Wed Oct 03 2012 13:16:23 GMT-0400 (EDT)
/*
Licensed to the Apache Software Foundation (ASF) under one
@@ -137,7 +137,7 @@ window.addEventListener = function(evt, handler, capture) {
document.removeEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
- // If unsubcribing from an event that is handled by a plugin
+ // If unsubscribing from an event that is handled by a plugin
if (typeof documentEventHandlers[e] != "undefined") {
documentEventHandlers[e].unsubscribe(handler);
} else {
@@ -147,7 +147,7 @@ document.removeEventListener = function(evt, handler, capture) {
window.removeEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
- // If unsubcribing from an event that is handled by a plugin
+ // If unsubscribing from an event that is handled by a plugin
if (typeof windowEventHandlers[e] != "undefined") {
windowEventHandlers[e].unsubscribe(handler);
} else {
@@ -196,7 +196,7 @@ var cordova = {
delete documentEventHandlers[event];
},
/**
- * Retreive original event handlers that were replaced by Cordova
+ * Retrieve original event handlers that were replaced by Cordova
*
* @return object
*/
@@ -245,7 +245,9 @@ var cordova = {
/**
* Plugin callback mechanism.
*/
- callbackId: 0,
+ // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+ // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+ callbackId: Math.floor(Math.random() * 2000000000),
callbacks: {},
callbackStatus: {
NO_RESULT: 0,
@@ -412,7 +414,7 @@ function recursiveMerge(target, src) {
module.exports = {
build: function (objects) {
return {
- intoButDontClobber: function (target) {
+ intoButDoNotClobber: function (target) {
include(target, objects, false, false);
},
intoAndClobber: function(target) {
@@ -729,6 +731,9 @@ module.exports = {
geolocation: {
path: 'cordova/plugin/geolocation'
},
+ globalization: {
+ path: 'cordova/plugin/globalization'
+ },
network: {
children: {
connection: {
@@ -844,6 +849,9 @@ module.exports = {
Flags: {
path: 'cordova/plugin/Flags'
},
+ GlobalizationError: {
+ path: 'cordova/plugin/GlobalizationError'
+ },
LocalFileSystem: {
path: 'cordova/plugin/LocalFileSystem'
},
@@ -906,7 +914,8 @@ var cordova = require('cordova'),
// doesn't exist in 4.X devices anyways.
bridgeMode = navigator.userAgent.indexOf(' 4_') == -1 ? jsToNativeModes.XHR_NO_PAYLOAD : jsToNativeModes.IFRAME_NAV,
execIframe,
- execXhr;
+ execXhr,
+ requestCount = 0;
function createExecIframe() {
var iframe = document.createElement("iframe");
@@ -916,10 +925,10 @@ function createExecIframe() {
}
function shouldBundleCommandJson() {
- if (bridgeMode == 2) {
+ if (bridgeMode == jsToNativeModes.XHR_WITH_PAYLOAD) {
return true;
}
- if (bridgeMode == 3) {
+ if (bridgeMode == jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
var payloadLength = 0;
for (var i = 0; i < cordova.commandQueue.length; ++i) {
payloadLength += cordova.commandQueue[i].length;
@@ -975,17 +984,22 @@ function iOSExec() {
// the command is executed.
cordova.commandQueue.push(JSON.stringify(command));
- // If the queue length is 1, then that means it was empty before we queued
- // the given command, so let the native side know that we have some
- // commands to execute, unless the queue is currently being flushed, in
- // which case the command will be picked up without notification.
- if (cordova.commandQueue.length == 1 && !cordova.commandQueueFlushing) {
- if (bridgeMode) {
+ if (!cordova.commandQueueFlushing) {
+ if (bridgeMode != jsToNativeModes.IFRAME_NAV) {
+ // Re-using the XHR improves exec() performance by about 10%.
+ // It is possible for a native stringByEvaluatingJavascriptFromString call
+ // to cause us to reach this point when a request is already in progress,
+ // so we check the readyState to guard agains re-using an inprogress XHR.
+ // Refer to CB-1404.
+ if (execXhr && execXhr.readyState != 4) {
+ execXhr = null;
+ }
execXhr = execXhr || new XMLHttpRequest();
- // Changeing this to a GET will make the XHR reach the URIProtocol on 4.2.
+ // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
// For some reason it still doesn't work though...
- execXhr.open('HEAD', "file:///!gap_exec", true);
+ execXhr.open('HEAD', "/!gap_exec", true);
execXhr.setRequestHeader('vc', cordova.iOSVCAddr);
+ execXhr.setRequestHeader('rc', ++requestCount);
if (shouldBundleCommandJson()) {
execXhr.setRequestHeader('cmds', nativecomm());
}
@@ -1109,6 +1123,7 @@ for (var key in Camera) {
* @param {Object} options
*/
cameraExport.getPicture = function(successCallback, errorCallback, options) {
+ options = options || {};
// successCallback required
if (typeof successCallback != "function") {
console.log("Camera Error: successCallback is not a function");
@@ -1122,9 +1137,9 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) {
}
var quality = 50;
- if (options && typeof options.quality == "number") {
+ if (typeof options.quality == "number") {
quality = options.quality;
- } else if (options && typeof options.quality == "string") {
+ } else if (typeof options.quality == "string") {
var qlity = parseInt(options.quality, 10);
if (isNaN(qlity) === false) {
quality = qlity.valueOf();
@@ -1347,7 +1362,7 @@ define("cordova/plugin/CompassError", function(require, exports, module) {
/**
* CompassError.
- * An error code assigned by an implementation when an error has occured
+ * An error code assigned by an implementation when an error has occurred
* @constructor
*/
var CompassError = function(err) {
@@ -1633,7 +1648,7 @@ define("cordova/plugin/ContactError", function(require, exports, module) {
/**
* ContactError.
- * An error code assigned by an implementation when an error has occured
+ * An error code assigned by an implementation when an error has occurred
* @constructor
*/
var ContactError = function(err) {
@@ -1840,7 +1855,7 @@ DirectoryEntry.prototype.createReader = function() {
* Creates or looks up a directory
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
- * @param {Flags} options to create or excluively create the directory
+ * @param {Flags} options to create or exclusively create the directory
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
@@ -1872,7 +1887,7 @@ DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCall
* Creates or looks up a file
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
- * @param {Flags} options to create or excluively create the file
+ * @param {Flags} options to create or exclusively create the file
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
@@ -2316,7 +2331,7 @@ var FileReader = function() {
// Event handlers
this.onloadstart = null; // When the read starts.
- this.onprogress = null; // While reading (and decoding) file or fileBlob data, and reporting partial file data (progess.loaded/progress.total)
+ this.onprogress = null; // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
this.onload = null; // When the read has successfully completed.
this.onerror = null; // When the read has failed (see errors).
this.onloadend = null; // When the request has completed (either in success or failure).
@@ -2570,13 +2585,27 @@ module.exports = FileSystem;
define("cordova/plugin/FileTransfer", function(require, exports, module) {
var exec = require('cordova/exec'),
- FileTransferError = require('cordova/plugin/FileTransferError');
+ FileTransferError = require('cordova/plugin/FileTransferError'),
+ ProgressEvent = require('cordova/plugin/ProgressEvent');
+
+function newProgressEvent(result) {
+ var pe = new ProgressEvent();
+ pe.lengthComputable = result.lengthComputable;
+ pe.loaded = result.loaded;
+ pe.total = result.total;
+ return pe;
+}
+
+var idCounter = 0;
/**
* FileTransfer uploads a file to a remote server.
* @constructor
*/
-var FileTransfer = function() {};
+var FileTransfer = function() {
+ this._id = ++idCounter;
+ this.onprogress = null; // optional callback
+};
/**
* Given an absolute file path, uploads a file on the device to a remote server
@@ -2619,7 +2648,17 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
errorCallback(error);
};
- exec(successCallback, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers]);
+ var self = this;
+ var win = function(result) {
+ if (typeof result.lengthComputable != "undefined") {
+ if (self.onprogress) {
+ return self.onprogress(newProgressEvent(result));
+ }
+ } else {
+ return successCallback(result);
+ }
+ };
+ exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id]);
};
/**
@@ -2628,23 +2667,31 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
* @param target {String} Full path of the file on the device
* @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
*/
-FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) {
+FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts) {
// sanity parameter checking
if (!source || !target) throw new Error("FileTransfer.download requires source URI and target URI parameters at the minimum.");
+ var self = this;
var win = function(result) {
- var entry = null;
- if (result.isDirectory) {
- entry = new (require('cordova/plugin/DirectoryEntry'))();
- }
- else if (result.isFile) {
- entry = new (require('cordova/plugin/FileEntry'))();
+ if (typeof result.lengthComputable != "undefined") {
+ if (self.onprogress) {
+ return self.onprogress(newProgressEvent(result));
+ }
+ } else {
+ var entry = null;
+ if (result.isDirectory) {
+ entry = new (require('cordova/plugin/DirectoryEntry'))();
+ }
+ else if (result.isFile) {
+ entry = new (require('cordova/plugin/FileEntry'))();
+ }
+ entry.isDirectory = result.isDirectory;
+ entry.isFile = result.isFile;
+ entry.name = result.name;
+ entry.fullPath = result.fullPath;
+ successCallback(entry);
}
- entry.isDirectory = result.isDirectory;
- entry.isFile = result.isFile;
- entry.name = result.name;
- entry.fullPath = result.fullPath;
- successCallback(entry);
};
var fail = function(e) {
@@ -2652,9 +2699,18 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro
errorCallback(error);
};
- exec(win, errorCallback, 'FileTransfer', 'download', [source, target]);
+ exec(win, errorCallback, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id]);
};
+/**
+ * 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
+ */
+FileTransfer.prototype.abort = function(successCallback, errorCallback) {
+ exec(successCallback, errorCallback, 'FileTransfer', 'abort', [this._id]);
+}
+
module.exports = FileTransfer;
});
@@ -2676,6 +2732,7 @@ var FileTransferError = function(code, source, target, status) {
FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
+FileTransferError.ABORT_ERR = 4;
module.exports = FileTransferError;
@@ -3003,6 +3060,32 @@ module.exports = Flags;
});
+// file: lib/common/plugin/GlobalizationError.js
+define("cordova/plugin/GlobalizationError", function(require, exports, module) {
+
+
+/**
+ * Globalization error object
+ *
+ * @constructor
+ * @param code
+ * @param message
+ */
+var GlobalizationError = function(code, message) {
+ this.code = code || null;
+ this.message = message || '';
+};
+
+// Globalization error codes
+GlobalizationError.UNKNOWN_ERROR = 0;
+GlobalizationError.FORMATTING_ERROR = 1;
+GlobalizationError.PARSING_ERROR = 2;
+GlobalizationError.PATTERN_ERROR = 3;
+
+module.exports = GlobalizationError;
+
+});
+
// file: lib/common/plugin/LocalFileSystem.js
define("cordova/plugin/LocalFileSystem", function(require, exports, module) {
@@ -3493,7 +3576,7 @@ function removeListeners(l) {
var accelerometer = {
/**
- * Asynchronously aquires the current acceleration.
+ * Asynchronously acquires the current acceleration.
*
* @param {Function} successCallback The function to call when the acceleration data is available
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
@@ -3524,7 +3607,7 @@ var accelerometer = {
},
/**
- * Asynchronously aquires the acceleration repeatedly at a given interval.
+ * Asynchronously acquires the acceleration repeatedly at a given interval.
*
* @param {Function} successCallback The function to call each time the acceleration data is available
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
@@ -4011,7 +4094,7 @@ console.table = function(data, columns) {
//------------------------------------------------------------------------------
// return a new function that calls both functions passed as args
//------------------------------------------------------------------------------
-function wrapperedOrigCall(orgFunc, newFunc) {
+function wrappedOrigCall(orgFunc, newFunc) {
return function() {
var args = [].slice.call(arguments);
try { orgFunc.apply(WinConsole, args); } catch (e) {}
@@ -4026,7 +4109,7 @@ function wrapperedOrigCall(orgFunc, newFunc) {
//------------------------------------------------------------------------------
for (var key in console) {
if (typeof WinConsole[key] == "function") {
- console[key] = wrapperedOrigCall(WinConsole[key], console[key]);
+ console[key] = wrappedOrigCall(WinConsole[key], console[key]);
}
}
@@ -4171,7 +4254,7 @@ 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.
+ * Sends the given message through exec() to the Echo plugin, 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.
@@ -4238,7 +4321,7 @@ function createTimeout(errorCallback, timeout) {
var geolocation = {
lastPosition:null, // reference to last known (cached) position returned
/**
- * Asynchronously aquires the current position.
+ * Asynchronously acquires the current position.
*
* @param {Function} successCallback The function to call when the position data is available
* @param {Function} errorCallback The function to call when there is an error getting the heading position. (OPTIONAL)
@@ -4384,6 +4467,545 @@ module.exports = geolocation;
});
+// file: lib/common/plugin/globalization.js
+define("cordova/plugin/globalization", function(require, exports, module) {
+
+var exec = require('cordova/exec'),
+ GlobalizationError = require('cordova/plugin/GlobalizationError');
+
+var globalization = {
+
+/**
+* Returns the string identifier for the client's current language.
+* It returns the language identifier string to the successCB callback with a
+* properties object as a parameter. If there is an error getting the language,
+* then the errorCB callback is invoked.
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+*
+* @return Object.value {String}: The language identifier
+*
+* @error GlobalizationError.UNKNOWN_ERROR
+*
+* Example
+* globalization.getPreferredLanguage(function (language) {alert('language:' + language.value + '\n');},
+* function () {});
+*/
+getPreferredLanguage:function(successCB, failureCB) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getPreferredLanguage Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getPreferredLanguage Error: failureCB is not a function");
+ return;
+ }
+
+ exec(successCB, failureCB, "Globalization","getPreferredLanguage", []);
+},
+
+/**
+* Returns the string identifier for the client's current locale setting.
+* It returns the locale identifier string to the successCB callback with a
+* properties object as a parameter. If there is an error getting the locale,
+* then the errorCB callback is invoked.
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+*
+* @return Object.value {String}: The locale identifier
+*
+* @error GlobalizationError.UNKNOWN_ERROR
+*
+* Example
+* globalization.getLocaleName(function (locale) {alert('locale:' + locale.value + '\n');},
+* function () {});
+*/
+getLocaleName:function(successCB, failureCB) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getLocaleName Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getLocaleName Error: failureCB is not a function");
+ return;
+ }
+ exec(successCB, failureCB, "Globalization","getLocaleName", []);
+},
+
+
+/**
+* Returns a date formatted as a string according to the client's user preferences and
+* calendar using the time zone of the client. It returns the formatted date string to the
+* successCB callback with a properties object as a parameter. If there is an error
+* formatting the date, then the errorCB callback is invoked.
+*
+* The defaults are: formatLenght="short" and selector="date and time"
+*
+* @param {Date} date
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* formatLength {String}: 'short', 'medium', 'long', or 'full'
+* selector {String}: 'date', 'time', or 'date and time'
+*
+* @return Object.value {String}: The localized date string
+*
+* @error GlobalizationError.FORMATTING_ERROR
+*
+* Example
+* globalization.dateToString(new Date(),
+* function (date) {alert('date:' + date.value + '\n');},
+* function (errorCode) {alert(errorCode);},
+* {formatLength:'short'});
+*/
+dateToString:function(date, successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.dateToString Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.dateToString Error: failureCB is not a function");
+ return;
+ }
+
+
+ if (date instanceof Date){
+ var dateValue;
+ dateValue = date.valueOf();
+ exec(successCB, failureCB, "Globalization", "dateToString", [{"date": dateValue, "options": options}]);
+ }
+ else {
+ console.log("Globalization.dateToString Error: date is not a Date object");
+ }
+},
+
+
+/**
+* Parses a date formatted as a string according to the client's user
+* preferences and calendar using the time zone of the client and returns
+* the corresponding date object. It returns the date to the successCB
+* callback with a properties object as a parameter. If there is an error
+* parsing the date string, then the errorCB callback is invoked.
+*
+* The defaults are: formatLength="short" and selector="date and time"
+*
+* @param {String} dateString
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* formatLength {String}: 'short', 'medium', 'long', or 'full'
+* selector {String}: 'date', 'time', or 'date and time'
+*
+* @return Object.year {Number}: The four digit year
+* Object.month {Number}: The month from (0 - 11)
+* Object.day {Number}: The day from (1 - 31)
+* Object.hour {Number}: The hour from (0 - 23)
+* Object.minute {Number}: The minute from (0 - 59)
+* Object.second {Number}: The second from (0 - 59)
+* Object.millisecond {Number}: The milliseconds (from 0 - 999),
+* not available on all platforms
+*
+* @error GlobalizationError.PARSING_ERROR
+*
+* Example
+* globalization.stringToDate('4/11/2011',
+* function (date) { alert('Month:' + date.month + '\n' +
+* 'Day:' + date.day + '\n' +
+* 'Year:' + date.year + '\n');},
+* function (errorCode) {alert(errorCode);},
+* {selector:'date'});
+*/
+stringToDate:function(dateString, successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.stringToDate Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.stringToDate Error: failureCB is not a function");
+ return;
+ }
+ if (typeof dateString == "string"){
+ exec(successCB, failureCB, "Globalization", "stringToDate", [{"dateString": dateString, "options": options}]);
+ }
+ else {
+ console.log("Globalization.stringToDate Error: dateString is not a string");
+ }
+},
+
+
+/**
+* Returns a pattern string for formatting and parsing dates according to the client's
+* user preferences. It returns the pattern to the successCB callback with a
+* properties object as a parameter. If there is an error obtaining the pattern,
+* then the errorCB callback is invoked.
+*
+* The defaults are: formatLength="short" and selector="date and time"
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* formatLength {String}: 'short', 'medium', 'long', or 'full'
+* selector {String}: 'date', 'time', or 'date and time'
+*
+* @return Object.pattern {String}: The date and time pattern for formatting and parsing dates.
+* The patterns follow Unicode Technical Standard #35
+* http://unicode.org/reports/tr35/tr35-4.html
+* Object.timezone {String}: The abbreviated name of the time zone on the client
+* Object.utc_offset {Number}: The current difference in seconds between the client's
+* time zone and coordinated universal time.
+* Object.dst_offset {Number}: The current daylight saving time offset in seconds
+* between the client's non-daylight saving's time zone
+* and the client's daylight saving's time zone.
+*
+* @error GlobalizationError.PATTERN_ERROR
+*
+* Example
+* globalization.getDatePattern(
+* function (date) {alert('pattern:' + date.pattern + '\n');},
+* function () {},
+* {formatLength:'short'});
+*/
+getDatePattern:function(successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getDatePattern Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getDatePattern Error: failureCB is not a function");
+ return;
+ }
+
+ exec(successCB, failureCB, "Globalization", "getDatePattern", [{"options": options}]);
+},
+
+
+/**
+* Returns an array of either the names of the months or days of the week
+* according to the client's user preferences and calendar. It returns the array of names to the
+* successCB callback with a properties object as a parameter. If there is an error obtaining the
+* names, then the errorCB callback is invoked.
+*
+* The defaults are: type="wide" and item="months"
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* type {String}: 'narrow' or 'wide'
+* item {String}: 'months', or 'days'
+*
+* @return Object.value {Array{String}}: The array of names starting from either
+* the first month in the year or the
+* first day of the week.
+* @error GlobalizationError.UNKNOWN_ERROR
+*
+* Example
+* globalization.getDateNames(function (names) {
+* for(var i = 0; i < names.value.length; i++) {
+* alert('Month:' + names.value[i] + '\n');}},
+* function () {});
+*/
+getDateNames:function(successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getDateNames Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getDateNames Error: failureCB is not a function");
+ return;
+ }
+ exec(successCB, failureCB, "Globalization", "getDateNames", [{"options": options}]);
+},
+
+/**
+* Returns whether daylight savings time is in effect for a given date using the client's
+* time zone and calendar. It returns whether or not daylight savings time is in effect
+* to the successCB callback with a properties object as a parameter. If there is an error
+* reading the date, then the errorCB callback is invoked.
+*
+* @param {Date} date
+* @param {Function} successCB
+* @param {Function} errorCB
+*
+* @return Object.dst {Boolean}: The value "true" indicates that daylight savings time is
+* in effect for the given date and "false" indicate that it is not.
+*
+* @error GlobalizationError.UNKNOWN_ERROR
+*
+* Example
+* globalization.isDayLightSavingsTime(new Date(),
+* function (date) {alert('dst:' + date.dst + '\n');}
+* function () {});
+*/
+isDayLightSavingsTime:function(date, successCB, failureCB) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.isDayLightSavingsTime Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.isDayLightSavingsTime Error: failureCB is not a function");
+ return;
+ }
+
+
+ if (date instanceof Date){
+ var dateValue;
+ dateValue = date.valueOf();
+ exec(successCB, failureCB, "Globalization", "isDayLightSavingsTime", [{"date": dateValue}]);
+ }
+ else {
+ console.log("Globalization.isDayLightSavingsTime Error: date is not a Date object");
+ }
+
+},
+
+/**
+* Returns the first day of the week according to the client's user preferences and calendar.
+* The days of the week are numbered starting from 1 where 1 is considered to be Sunday.
+* It returns the day to the successCB callback with a properties object as a parameter.
+* If there is an error obtaining the pattern, then the errorCB callback is invoked.
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+*
+* @return Object.value {Number}: The number of the first day of the week.
+*
+* @error GlobalizationError.UNKNOWN_ERROR
+*
+* Example
+* globalization.getFirstDayOfWeek(function (day)
+* { alert('Day:' + day.value + '\n');},
+* function () {});
+*/
+getFirstDayOfWeek:function(successCB, failureCB) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getFirstDayOfWeek Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getFirstDayOfWeek Error: failureCB is not a function");
+ return;
+ }
+
+ exec(successCB, failureCB, "Globalization", "getFirstDayOfWeek", []);
+},
+
+
+/**
+* Returns a number formatted as a string according to the client's user preferences.
+* It returns the formatted number string to the successCB callback with a properties object as a
+* parameter. If there is an error formatting the number, then the errorCB callback is invoked.
+*
+* The defaults are: type="decimal"
+*
+* @param {Number} number
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* type {String}: 'decimal', "percent", or 'currency'
+*
+* @return Object.value {String}: The formatted number string.
+*
+* @error GlobalizationError.FORMATTING_ERROR
+*
+* Example
+* globalization.numberToString(3.25,
+* function (number) {alert('number:' + number.value + '\n');},
+* function () {},
+* {type:'decimal'});
+*/
+numberToString:function(number, successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.numberToString Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.numberToString Error: failureCB is not a function");
+ return;
+ }
+
+ if(typeof number == "number") {
+ exec(successCB, failureCB, "Globalization", "numberToString", [{"number": number, "options": options}]);
+ }
+ else {
+ console.log("Globalization.numberToString Error: number is not a number");
+ }
+},
+
+/**
+* Parses a number formatted as a string according to the client's user preferences and
+* returns the corresponding number. It returns the number to the successCB callback with a
+* properties object as a parameter. If there is an error parsing the number string, then
+* the errorCB callback is invoked.
+*
+* The defaults are: type="decimal"
+*
+* @param {String} numberString
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* type {String}: 'decimal', "percent", or 'currency'
+*
+* @return Object.value {Number}: The parsed number.
+*
+* @error GlobalizationError.PARSING_ERROR
+*
+* Example
+* globalization.stringToNumber('1234.56',
+* function (number) {alert('Number:' + number.value + '\n');},
+* function () { alert('Error parsing number');});
+*/
+stringToNumber:function(numberString, successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.stringToNumber Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.stringToNumber Error: failureCB is not a function");
+ return;
+ }
+
+ if(typeof numberString == "string") {
+ exec(successCB, failureCB, "Globalization", "stringToNumber", [{"numberString": numberString, "options": options}]);
+ }
+ else {
+ console.log("Globalization.stringToNumber Error: numberString is not a string");
+ }
+},
+
+/**
+* Returns a pattern string for formatting and parsing numbers according to the client's user
+* preferences. It returns the pattern to the successCB callback with a properties object as a
+* parameter. If there is an error obtaining the pattern, then the errorCB callback is invoked.
+*
+* The defaults are: type="decimal"
+*
+* @param {Function} successCB
+* @param {Function} errorCB
+* @param {Object} options {optional}
+* type {String}: 'decimal', "percent", or 'currency'
+*
+* @return Object.pattern {String}: The number pattern for formatting and parsing numbers.
+* The patterns follow Unicode Technical Standard #35.
+* http://unicode.org/reports/tr35/tr35-4.html
+* Object.symbol {String}: The symbol to be used when formatting and parsing
+* e.g., percent or currency symbol.
+* Object.fraction {Number}: The number of fractional digits to use when parsing and
+* formatting numbers.
+* Object.rounding {Number}: The rounding increment to use when parsing and formatting.
+* Object.positive {String}: The symbol to use for positive numbers when parsing and formatting.
+* Object.negative: {String}: The symbol to use for negative numbers when parsing and formatting.
+* Object.decimal: {String}: The decimal symbol to use for parsing and formatting.
+* Object.grouping: {String}: The grouping symbol to use for parsing and formatting.
+*
+* @error GlobalizationError.PATTERN_ERROR
+*
+* Example
+* globalization.getNumberPattern(
+* function (pattern) {alert('Pattern:' + pattern.pattern + '\n');},
+* function () {});
+*/
+getNumberPattern:function(successCB, failureCB, options) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getNumberPattern Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getNumberPattern Error: failureCB is not a function");
+ return;
+ }
+
+ exec(successCB, failureCB, "Globalization", "getNumberPattern", [{"options": options}]);
+},
+
+/**
+* Returns a pattern string for formatting and parsing currency values according to the client's
+* user preferences and ISO 4217 currency code. It returns the pattern to the successCB callback with a
+* properties object as a parameter. If there is an error obtaining the pattern, then the errorCB
+* callback is invoked.
+*
+* @param {String} currencyCode
+* @param {Function} successCB
+* @param {Function} errorCB
+*
+* @return Object.pattern {String}: The currency pattern for formatting and parsing currency values.
+* The patterns follow Unicode Technical Standard #35
+* http://unicode.org/reports/tr35/tr35-4.html
+* Object.code {String}: The ISO 4217 currency code for the pattern.
+* Object.fraction {Number}: The number of fractional digits to use when parsing and
+* formatting currency.
+* Object.rounding {Number}: The rounding increment to use when parsing and formatting.
+* Object.decimal: {String}: The decimal symbol to use for parsing and formatting.
+* Object.grouping: {String}: The grouping symbol to use for parsing and formatting.
+*
+* @error GlobalizationError.FORMATTING_ERROR
+*
+* Example
+* globalization.getCurrencyPattern('EUR',
+* function (currency) {alert('Pattern:' + currency.pattern + '\n');}
+* function () {});
+*/
+getCurrencyPattern:function(currencyCode, successCB, failureCB) {
+ // successCallback required
+ if (typeof successCB != "function") {
+ console.log("Globalization.getCurrencyPattern Error: successCB is not a function");
+ return;
+ }
+
+ // errorCallback required
+ if (typeof failureCB != "function") {
+ console.log("Globalization.getCurrencyPattern Error: failureCB is not a function");
+ return;
+ }
+
+ if(typeof currencyCode == "string") {
+ exec(successCB, failureCB, "Globalization", "getCurrencyPattern", [{"currencyCode": currencyCode}]);
+ }
+ else {
+ console.log("Globalization.getCurrencyPattern Error: currencyCode is not a currency code");
+ }
+}
+
+};
+
+module.exports = globalization;
+
+});
+
// file: lib/ios/plugin/ios/Contact.js
define("cordova/plugin/ios/Contact", function(require, exports, module) {
@@ -4540,7 +5162,6 @@ var exec = require('cordova/exec');
* @constructor
*/
var DebugConsole = function() {
- this.winConsole = window.console;
this.logLevel = DebugConsole.INFO_LEVEL;
};
@@ -4555,7 +5176,10 @@ DebugConsole.prototype.setLevel = function(level) {
this.logLevel = level;
};
-var stringify = function(message) {
+/**
+ * create a nice string for an object
+ */
+function stringify(message) {
try {
if (typeof message === "object" && JSON && JSON.stringify) {
try {
@@ -4573,16 +5197,25 @@ var stringify = function(message) {
};
/**
+ * remember the original console and it's methods
+ */
+var origConsole = window.console || {}
+
+var origConsole_log = origConsole.log || function(){}
+var origConsole_warn = origConsole.warn || function(){}
+var origConsole_error = origConsole.error || function(){}
+
+
+/**
* Print a normal log message to the console
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.log = function(message) {
+ origConsole_log.apply(origConsole, arguments)
+
if (this.logLevel <= DebugConsole.INFO_LEVEL) {
exec(null, null, 'Debug Console', 'log', [ stringify(message), { logLevel: 'INFO' } ]);
}
- else if (this.winConsole && this.winConsole.log) {
- this.winConsole.log(message);
- }
};
/**
@@ -4590,12 +5223,11 @@ DebugConsole.prototype.log = function(message) {
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.warn = function(message) {
+ origConsole_warn.apply(origConsole, arguments)
+
if (this.logLevel <= DebugConsole.WARN_LEVEL) {
exec(null, null, 'Debug Console', 'log', [ stringify(message), { logLevel: 'WARN' } ]);
}
- else if (this.winConsole && this.winConsole.warn) {
- this.winConsole.warn(message);
- }
};
/**
@@ -4603,12 +5235,11 @@ DebugConsole.prototype.warn = function(message) {
* @param {Object|String} message Message or object to print to the console
*/
DebugConsole.prototype.error = function(message) {
+ origConsole_error.apply(origConsole, arguments)
+
if (this.logLevel <= DebugConsole.ERROR_LEVEL) {
exec(null, null, 'Debug Console', 'log', [ stringify(message), { logLevel: 'ERROR' } ]);
}
- else if (this.winConsole && this.winConsole.error){
- this.winConsole.error(message);
- }
};
module.exports = new DebugConsole();
@@ -5234,7 +5865,7 @@ utils.clone = function(obj) {
};
/**
- * Returns a wrappered version of the function
+ * Returns a wrapped version of the function
*/
utils.close = function(context, func, params) {
if (typeof params == 'undefined') {
@@ -5405,7 +6036,7 @@ window.cordova = require('cordova');
platform = require('cordova/platform');
// Drop the common globals into the window object, but be nice and don't overwrite anything.
- builder.build(base.objects).intoButDontClobber(window);
+ builder.build(base.objects).intoButDoNotClobber(window);
// Drop the platform-specific globals into the window object
// and clobber any existing object.