Return-Path: X-Original-To: apmail-incubator-callback-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-callback-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CE0FA9A4F for ; Fri, 17 Feb 2012 01:39:50 +0000 (UTC) Received: (qmail 44744 invoked by uid 500); 17 Feb 2012 01:39:50 -0000 Delivered-To: apmail-incubator-callback-commits-archive@incubator.apache.org Received: (qmail 44722 invoked by uid 500); 17 Feb 2012 01:39:50 -0000 Mailing-List: contact callback-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: callback-dev@incubator.apache.org Delivered-To: mailing list callback-commits@incubator.apache.org Received: (qmail 44712 invoked by uid 99); 17 Feb 2012 01:39:50 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2012 01:39:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,NORMAL_HTTP_TO_IP X-Spam-Check-By: apache.org Received: from [140.211.11.114] (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2012 01:39:43 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id A78903207B0; Fri, 17 Feb 2012 01:38:49 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: shazron@apache.org To: callback-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: [12/27] Rename PhoneGap to Cordova. Message-Id: <20120217013849.A78903207B0@tyr.zones.apache.org> Date: Fri, 17 Feb 2012 01:38:49 +0000 (UTC) http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLibTests/CDVWhitelistTests.h ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLibTests/CDVWhitelistTests.h b/CordovaLib/CordovaLibTests/CDVWhitelistTests.h new file mode 100644 index 0000000..db2a85e --- /dev/null +++ b/CordovaLib/CordovaLibTests/CDVWhitelistTests.h @@ -0,0 +1,26 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#import + +@interface CDVWhitelistTests : SenTestCase { + +} + +@end http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLibTests/CDVWhitelistTests.m ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLibTests/CDVWhitelistTests.m b/CordovaLib/CordovaLibTests/CDVWhitelistTests.m new file mode 100644 index 0000000..55d8378 --- /dev/null +++ b/CordovaLib/CordovaLibTests/CDVWhitelistTests.m @@ -0,0 +1,255 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#import "CDVWhitelistTests.h" +#import "CDVWhitelist.h" + +@implementation CDVWhitelistTests + +- (void)setUp +{ + [super setUp]; + + // setup code here +} + +- (void)tearDown +{ + // Tear-down code here. + + [super tearDown]; +} + +- (void) testAllowedSchemes +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"*.apache.org", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist schemeIsAllowed:@"http"], nil); + STAssertTrue([whitelist schemeIsAllowed:@"https"], nil); + STAssertTrue([whitelist schemeIsAllowed:@"ftp"], nil); + STAssertTrue([whitelist schemeIsAllowed:@"ftps"], nil); + STAssertFalse([whitelist schemeIsAllowed:@"gopher"], nil); + + [whitelist release]; + +} + +- (void) testSubdomainWildcard +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"*.apache.org", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://sub1.sub0.build.apache.org"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org.ca"]], nil); + + [whitelist release]; +} + +- (void) testWildcardInTLD +{ + // NOTE: if the user chooses to do this (a wildcard in the TLD, not a wildcard as the TLD), we allow it because we assume they know what they are doing! We don't replace it with known TLDs + // This might be applicable for custom TLDs on a local network DNS + + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"apache.o*g", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.ogg"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.foo"]], nil); + + [whitelist release]; +} + +- (void) testTLDWildcard +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"apache.*", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + NSString* hostname = @"apache"; + + NSArray* knownTLDs = [NSArray arrayWithObjects: + @"aero", @"asia", @"arpa", @"biz", @"cat", + @"com", @"coop", @"edu", @"gov", @"info", + @"int", @"jobs", @"mil", @"mobi", @"museum", + @"name", @"net", @"org", @"pro", @"tel", + @"travel", @"xxx", + nil]; + + // 26*26 combos + NSMutableArray* twoCharCountryCodes = [NSMutableArray arrayWithCapacity:(26*26)]; + for (char c0 = 'a'; c0 <= 'z'; ++c0) + { + for (char c1 = 'a'; c1 <= 'z'; ++c1) + { + [twoCharCountryCodes addObject:[NSString stringWithFormat:@"%c%c", c0, c1]]; + } + } + + NSMutableArray* shouldPass = [NSMutableArray arrayWithCapacity:[knownTLDs count]+[twoCharCountryCodes count]]; + + NSEnumerator* knownTLDEnumerator = [knownTLDs objectEnumerator]; + NSString* tld = nil; + + while (tld = [knownTLDEnumerator nextObject]) + { + [shouldPass addObject:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, tld]]]; + } + + NSEnumerator* twoCharCountryCodesEnumerator = [twoCharCountryCodes objectEnumerator]; + NSString* cc = nil; + + while (cc = [twoCharCountryCodesEnumerator nextObject]) + { + [shouldPass addObject:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, cc]]]; + } + + NSEnumerator* shouldPassEnumerator = [shouldPass objectEnumerator]; + NSURL* url = nil; + + while (url = [shouldPassEnumerator nextObject]) + { + STAssertTrue([whitelist URLIsAllowed:url], @"Url tested :%@", [url description]); + } + + STAssertFalse(([whitelist URLIsAllowed:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, @"faketld"]]]), nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://unknownhostname.faketld"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://unknownhostname.com"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil); + + [whitelist release]; +} + +- (void) testCatchallWildcardOnly +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"*", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.prg"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://MyDangerousSite.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org.SuspiciousSite.com"]], nil); + + [whitelist release]; +} + +- (void) testWildcardInHostname +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"www.*apac*he.org", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apacMAChe.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.MACapache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.MACapacMAChe.org"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + + [whitelist release]; +} + +- (void) testExactMatch +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"www.apache.org", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.org"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + + [whitelist release]; +} + +- (void) testWildcardMix +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"*.apac*he.*", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apacMAChe.ca"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apacMAChe.museum"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://blahMAChe.museum"]], nil); + + [whitelist release]; +} + +- (void) testIpExactMatch +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"192.168.1.1", + @"192.168.2.1", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.1"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.1"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.3.1"]], nil); + + [whitelist release]; +} + +- (void) testIpWildcardMatch +{ + NSArray* allowedHosts = [NSArray arrayWithObjects: + @"192.168.1.*", + @"192.168.2.*", + nil]; + + CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts]; + + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.1"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.2"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.1"]], nil); + STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.2"]], nil); + STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.3.1"]], nil); + + [whitelist release]; +} + + + +@end http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLibTests/CordovaLibTests-Info.plist ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLibTests/CordovaLibTests-Info.plist b/CordovaLib/CordovaLibTests/CordovaLibTests-Info.plist new file mode 100644 index 0000000..2b819ff --- /dev/null +++ b/CordovaLib/CordovaLibTests/CordovaLibTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.apache.cordova.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLibTests/CordovaLibTests-Prefix.pch ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLibTests/CordovaLibTests-Prefix.pch b/CordovaLib/CordovaLibTests/CordovaLibTests-Prefix.pch new file mode 100644 index 0000000..059c8de --- /dev/null +++ b/CordovaLib/CordovaLibTests/CordovaLibTests-Prefix.pch @@ -0,0 +1,25 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +// +// Prefix header for all source files of the 'CordovaLibTests' target in the 'CordovaLibTests' project +// + +#ifdef __OBJC__ + #import +#endif http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLibTests/en.lproj/InfoPlist.strings ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLibTests/en.lproj/InfoPlist.strings b/CordovaLib/CordovaLibTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..01d5c8c --- /dev/null +++ b/CordovaLib/CordovaLibTests/en.lproj/InfoPlist.strings @@ -0,0 +1,20 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +/* Localized versions of Info.plist keys */ + http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/CordovaLib_Prefix.pch ---------------------------------------------------------------------- diff --git a/CordovaLib/CordovaLib_Prefix.pch b/CordovaLib/CordovaLib_Prefix.pch new file mode 100644 index 0000000..9545580 --- /dev/null +++ b/CordovaLib/CordovaLib_Prefix.pch @@ -0,0 +1,22 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#ifdef __OBJC__ + #import +#endif http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Makefile ---------------------------------------------------------------------- diff --git a/CordovaLib/Makefile b/CordovaLib/Makefile new file mode 100644 index 0000000..9b49ed5 --- /dev/null +++ b/CordovaLib/Makefile @@ -0,0 +1,70 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(SHELL) -c true +RM_F = rm -f +RM_IR = rm -iR +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = mkdir -p +CAT = cat +MAKE = make +OPEN = open +JAVA = java +ECHO = echo +ECHO_N = echo -n +CDV_JS_CORE = javascripts/core +CDV_VER = $(shell head -1 VERSION) + +all :: javascripts/cordova-$(CDV_VER).js + +javascripts/cordova-$(CDV_VER).js: clean $(CDV_JS_CORE)/license.js $(CDV_JS_CORE)/cordova.js.base $(CDV_JS_CORE)/acceleration.js $(CDV_JS_CORE)/accelerometer.js $(CDV_JS_CORE)/battery.js $(CDV_JS_CORE)/camera.js $(CDV_JS_CORE)/capture.js $(CDV_JS_CORE)/contact.js $(CDV_JS_CORE)/debugconsole.js $(CDV_JS_CORE)/device.js $(CDV_JS_CORE)/file.js $(CDV_JS_CORE)/filetransfer.js $(CDV_JS_CORE)/geolocation.js $(CDV_JS_CORE)/compass.js $(CDV_JS_CORE)/media.js $(CDV_JS_CORE)/notification.js $(CDV_JS_CORE)/orientation.js $(CDV_JS_CORE)/position.js $(CDV_JS_CORE)/sms.js $(CDV_JS_CORE)/telephony.js $(CDV_JS_CORE)/network.js $(CDV_JS_CORE)/splashscreen.js + $(RM_F) $@ + $(CAT) $(CDV_JS_CORE)/license.js | sed 's/{VERSION}/$(CDV_VER)/' >> $@ + $(CAT) $(CDV_JS_CORE)/cordova.js.base >> $@ + $(CAT) $(CDV_JS_CORE)/debugconsole.js >> $@ + $(CAT) $(CDV_JS_CORE)/position.js >> $@ + $(CAT) $(CDV_JS_CORE)/acceleration.js >> $@ + $(CAT) $(CDV_JS_CORE)/accelerometer.js >> $@ + $(CAT) $(CDV_JS_CORE)/battery.js >> $@ + $(CAT) $(CDV_JS_CORE)/camera.js >> $@ + $(CAT) $(CDV_JS_CORE)/device.js >> $@ + $(CAT) $(CDV_JS_CORE)/capture.js >> $@ + $(CAT) $(CDV_JS_CORE)/contact.js >> $@ + $(CAT) $(CDV_JS_CORE)/file.js >> $@ + $(CAT) $(CDV_JS_CORE)/filetransfer.js >> $@ + $(CAT) $(CDV_JS_CORE)/geolocation.js >> $@ + $(CAT) $(CDV_JS_CORE)/compass.js >> $@ + $(CAT) $(CDV_JS_CORE)/media.js >> $@ + $(CAT) $(CDV_JS_CORE)/notification.js >> $@ + $(CAT) $(CDV_JS_CORE)/orientation.js >> $@ + $(CAT) $(CDV_JS_CORE)/sms.js >> $@ + $(CAT) $(CDV_JS_CORE)/telephony.js >> $@ + $(CAT) $(CDV_JS_CORE)/network.js >> $@ + $(CAT) $(CDV_JS_CORE)/splashscreen.js >> $@ + +clean: + $(RM_F) javascripts/cordova-*.js \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/VERSION ---------------------------------------------------------------------- diff --git a/CordovaLib/VERSION b/CordovaLib/VERSION new file mode 100644 index 0000000..13175fd --- /dev/null +++ b/CordovaLib/VERSION @@ -0,0 +1 @@ +1.4.1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/javascripts/core/acceleration.js ---------------------------------------------------------------------- diff --git a/CordovaLib/javascripts/core/acceleration.js b/CordovaLib/javascripts/core/acceleration.js new file mode 100644 index 0000000..d2d29de --- /dev/null +++ b/CordovaLib/javascripts/core/acceleration.js @@ -0,0 +1,42 @@ +if (!Cordova.hasResource("acceleration")) { + Cordova.addResource("acceleration"); + + +/** + * This class contains acceleration information + * @constructor + * @param {Number} x The force applied by the device in the x-axis. + * @param {Number} y The force applied by the device in the y-axis. + * @param {Number} z The force applied by the device in the z-axis. + */ +Acceleration = function(x, y, z) { + /** + * The force applied by the device in the x-axis. + */ + this.x = x; + /** + * The force applied by the device in the y-axis. + */ + this.y = y; + /** + * The force applied by the device in the z-axis. + */ + this.z = z; + /** + * The time that the acceleration was obtained. + */ + this.timestamp = new Date().getTime(); +} + +/** + * This class specifies the options for requesting acceleration data. + * @constructor + */ +AccelerationOptions = function() { + /** + * The timeout after which if acceleration data cannot be obtained the errorCallback + * is called. + */ + this.timeout = 10000; +} +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/javascripts/core/accelerometer.js ---------------------------------------------------------------------- diff --git a/CordovaLib/javascripts/core/accelerometer.js b/CordovaLib/javascripts/core/accelerometer.js new file mode 100644 index 0000000..beb7ff6 --- /dev/null +++ b/CordovaLib/javascripts/core/accelerometer.js @@ -0,0 +1,160 @@ +if (!Cordova.hasResource("accelerometer")) { + Cordova.addResource("accelerometer"); + +/** + * This class provides access to device accelerometer data. + * @constructor + */ +Accelerometer = function() +{ + /** + * The last known acceleration. + */ + this.lastAcceleration = new Acceleration(0,0,0); +} + +/** + * Asynchronously aquires 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. + * @param {AccelerationOptions} options The options for getting the accelerometer data + * such as timeout. + */ +Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) { + // If the acceleration is available then call success + // If the acceleration is not available then call error + + // Created for iPhone, Iphone passes back _accel obj litteral + if (typeof successCallback == "function") { + successCallback(this.lastAcceleration); + } +}; + +// private callback called from Obj-C by name +Accelerometer.prototype._onAccelUpdate = function(x,y,z) +{ + this.lastAcceleration = new Acceleration(x,y,z); +}; + +/** + * Asynchronously aquires 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. + * @param {AccelerationOptions} options The options for getting the accelerometer data + * such as timeout. + */ + +Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) { + //this.getCurrentAcceleration(successCallback, errorCallback, options); + // TODO: add the interval id to a list so we can clear all watches + var frequency = (options != undefined && options.frequency != undefined) ? options.frequency : 10000; + var updatedOptions = { + desiredFrequency:frequency + } + Cordova.exec(null, null, "org.apache.cordova.accelerometer", "start", [options]); + + return setInterval(function() { + navigator.accelerometer.getCurrentAcceleration(successCallback, errorCallback, options); + }, frequency); +}; + +/** + * Clears the specified accelerometer watch. + * @param {String} watchId The ID of the watch returned from #watchAcceleration. + */ +Accelerometer.prototype.clearWatch = function(watchId) { + Cordova.exec(null, null, "org.apache.cordova.accelerometer", "stop", []); + clearInterval(watchId); +}; + +Accelerometer.install = function() +{ + if (typeof navigator.accelerometer == "undefined") { + navigator.accelerometer = new Accelerometer(); + } +}; + +Accelerometer.installDeviceMotionHandler = function() +{ + if (!(window.DeviceMotionEvent == undefined)) { + // supported natively, so we don't have to add support + return; + } + + var self = this; + var devicemotionEvent = 'devicemotion'; + self.deviceMotionWatchId = null; + self.deviceMotionListenerCount = 0; + self.deviceMotionLastEventTimestamp = 0; + + // backup original `window.addEventListener`, `window.removeEventListener` + var _addEventListener = window.addEventListener; + var _removeEventListener = window.removeEventListener; + + var windowDispatchAvailable = !(window.dispatchEvent === undefined); // undefined in iOS 3.x + + var accelWin = function(acceleration) { + var evt = document.createEvent('Events'); + evt.initEvent(devicemotionEvent); + + evt.acceleration = null; // not all devices have gyroscope, don't care for now if we actually have it. + evt.rotationRate = null; // not all devices have gyroscope, don't care for now if we actually have it: + evt.accelerationIncludingGravity = acceleration; // accelerometer, all iOS devices have it + + var currentTime = new Date().getTime(); + evt.interval = (self.deviceMotionLastEventTimestamp == 0) ? 0 : (currentTime - self.deviceMotionLastEventTimestamp); + self.deviceMotionLastEventTimestamp = currentTime; + + if (windowDispatchAvailable) { + window.dispatchEvent(evt); + } else { + document.dispatchEvent(evt); + } + }; + + var accelFail = function() { + + }; + + // override `window.addEventListener` + window.addEventListener = function() { + if (arguments[0] === devicemotionEvent) { + ++(self.deviceMotionListenerCount); + if (self.deviceMotionListenerCount == 1) { // start + self.deviceMotionWatchId = navigator.accelerometer.watchAcceleration(accelWin, accelFail, { frequency:500}); + } + } + + if (!windowDispatchAvailable) { + return document.addEventListener.apply(this, arguments); + } else { + return _addEventListener.apply(this, arguments); + } + }; + + // override `window.removeEventListener' + window.removeEventListener = function() { + if (arguments[0] === devicemotionEvent) { + --(self.deviceMotionListenerCount); + if (self.deviceMotionListenerCount == 0) { // stop + navigator.accelerometer.clearWatch(self.deviceMotionWatchId); + } + } + + if (!windowDispatchAvailable) { + return document.removeEventListener.apply(this, arguments); + } else { + return _removeEventListener.apply(this, arguments); + } + }; +}; + + +Cordova.addConstructor(Accelerometer.install); +Cordova.addConstructor(Accelerometer.installDeviceMotionHandler); + +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/javascripts/core/battery.js ---------------------------------------------------------------------- diff --git a/CordovaLib/javascripts/core/battery.js b/CordovaLib/javascripts/core/battery.js new file mode 100644 index 0000000..685a630 --- /dev/null +++ b/CordovaLib/javascripts/core/battery.js @@ -0,0 +1,123 @@ + +if (!Cordova.hasResource("battery")) { +Cordova.addResource("battery"); + +/** + * This class contains information about the current battery status. + * @constructor + */ +var Battery = function() { + this._level = null; + this._isPlugged = null; + this._batteryListener = []; + this._lowListener = []; + this._criticalListener = []; +}; + +/** + * Registers as an event producer for battery events. + * + * @param {Object} eventType + * @param {Object} handler + * @param {Object} add + */ +Battery.prototype.eventHandler = function(eventType, handler, add) { + var me = navigator.battery; + if (add) { + // If there are no current registered event listeners start the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + Cordova.exec(me._status, me._error, "org.apache.cordova.battery", "start", []); + } + + // Register the event listener in the proper array + if (eventType === "batterystatus") { + var pos = me._batteryListener.indexOf(handler); + if (pos === -1) { + me._batteryListener.push(handler); + } + } else if (eventType === "batterylow") { + var pos = me._lowListener.indexOf(handler); + if (pos === -1) { + me._lowListener.push(handler); + } + } else if (eventType === "batterycritical") { + var pos = me._criticalListener.indexOf(handler); + if (pos === -1) { + me._criticalListener.push(handler); + } + } + } else { + // Remove the event listener from the proper array + if (eventType === "batterystatus") { + var pos = me._batteryListener.indexOf(handler); + if (pos > -1) { + me._batteryListener.splice(pos, 1); + } + } else if (eventType === "batterylow") { + var pos = me._lowListener.indexOf(handler); + if (pos > -1) { + me._lowListener.splice(pos, 1); + } + } else if (eventType === "batterycritical") { + var pos = me._criticalListener.indexOf(handler); + if (pos > -1) { + me._criticalListener.splice(pos, 1); + } + } + + // If there are no more registered event listeners stop the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + Cordova.exec(null, null, "org.apache.cordova.battery", "stop", []); + } + } +}; + +/** + * Callback for battery status + * + * @param {Object} info keys: level, isPlugged + */ +Battery.prototype._status = function(info) { + if (info) { + var me = this; + if (me._level != info.level || me._isPlugged != info.isPlugged) { + // Fire batterystatus event + //Cordova.fireWindowEvent("batterystatus", info); + // use this workaround since iOS 3.x does have window.dispatchEvent + Cordova.fireEvent("batterystatus", window, info); + + // Fire low battery event + if (info.level == 20 || info.level == 5) { + if (info.level == 20) { + //Cordova.fireWindowEvent("batterylow", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + Cordova.fireEvent("batterylow", window, info); + } + else { + //Cordova.fireWindowEvent("batterycritical", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + Cordova.fireEvent("batterycritical", window, info); + } + } + } + me._level = info.level; + me._isPlugged = info.isPlugged; + } +}; + +/** + * Error callback for battery start + */ +Battery.prototype._error = function(e) { + console.log("Error initializing Battery: " + e); +}; + +Cordova.addConstructor(function() { + if (typeof navigator.battery === "undefined") { + navigator.battery = new Battery(); + Cordova.addWindowEventHandler("batterystatus", navigator.battery.eventHandler); + Cordova.addWindowEventHandler("batterylow", navigator.battery.eventHandler); + Cordova.addWindowEventHandler("batterycritical", navigator.battery.eventHandler); + } +}); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/javascripts/core/camera.js ---------------------------------------------------------------------- diff --git a/CordovaLib/javascripts/core/camera.js b/CordovaLib/javascripts/core/camera.js new file mode 100644 index 0000000..1cc5ebb --- /dev/null +++ b/CordovaLib/javascripts/core/camera.js @@ -0,0 +1,117 @@ +if (!Cordova.hasResource("camera")) { + Cordova.addResource("camera"); + + +/** + * This class provides access to the device camera. + * @constructor + */ +Camera = function() { + +} +/** + * Available Camera Options + * {boolean} allowEdit - true to allow editing image, default = false + * {number} quality 0-100 (low to high) default = 100 + * {Camera.DestinationType} destinationType default = DATA_URL + * {Camera.PictureSourceType} sourceType default = CAMERA + * {number} targetWidth - width in pixels to scale image default = 0 (no scaling) + * {number} targetHeight - height in pixels to scale image default = 0 (no scaling) + * {Camera.EncodingType} - encodingType default = JPEG + * {boolean} correctOrientation - Rotate the image to correct for the orientation of the device during capture (iOS only) + * {boolean} saveToPhotoAlbum - Save the image to the photo album on the device after capture (iOS only) + */ +/** + * Format of image that is returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.DestinationType = { + DATA_URL: 0, // Return base64 encoded string + FILE_URI: 1 // Return file uri +}; +Camera.prototype.DestinationType = Camera.DestinationType; + +/** + * Source to getPicture from. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.PictureSourceType = { + PHOTOLIBRARY : 0, // Choose image from picture library + CAMERA : 1, // Take picture from camera + SAVEDPHOTOALBUM : 2 // Choose image from picture library +}; +Camera.prototype.PictureSourceType = Camera.PictureSourceType; + +/** + * Encoding of image returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.CAMERA, + * encodingType: Camera.EncodingType.PNG}) + */ +Camera.EncodingType = { + JPEG: 0, // Return JPEG encoded image + PNG: 1 // Return PNG encoded image +}; +Camera.prototype.EncodingType = Camera.EncodingType; + +/** + * Type of pictures to select from. Only applicable when + * PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY, + * mediaType: Camera.MediaType.PICTURE}) + */ +Camera.MediaType = { + PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType + VIDEO: 1, // allow selection of video only, ONLY RETURNS URL + ALLMEDIA : 2 // allow selection from all media types +}; +Camera.prototype.MediaType = Camera.MediaType; + +/** + * Gets a picture from source defined by "options.sourceType", and returns the + * image as defined by the "options.destinationType" option. + + * The defaults are sourceType=CAMERA and destinationType=DATA_URL. + * + * @param {Function} successCallback + * @param {Function} errorCallback + * @param {Object} options + */ +Camera.prototype.getPicture = function(successCallback, errorCallback, options) { + // successCallback required + if (typeof successCallback != "function") { + console.log("Camera Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Camera Error: errorCallback is not a function"); + return; + } + + Cordova.exec(successCallback, errorCallback, "org.apache.cordova.camera","getPicture",[options]); +}; + + + +Cordova.addConstructor(function() { + if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); +}); +}; + http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/javascripts/core/capture.js ---------------------------------------------------------------------- diff --git a/CordovaLib/javascripts/core/capture.js b/CordovaLib/javascripts/core/capture.js new file mode 100644 index 0000000..44bfc97 --- /dev/null +++ b/CordovaLib/javascripts/core/capture.js @@ -0,0 +1,194 @@ +if (!Cordova.hasResource("capture")) { + Cordova.addResource("capture"); +/** + * The CaptureError interface encapsulates all errors in the Capture API. + */ +function CaptureError() { + this.code = null; +}; + +// Capture error codes +CaptureError.CAPTURE_INTERNAL_ERR = 0; +CaptureError.CAPTURE_APPLICATION_BUSY = 1; +CaptureError.CAPTURE_INVALID_ARGUMENT = 2; +CaptureError.CAPTURE_NO_MEDIA_FILES = 3; +CaptureError.CAPTURE_NOT_SUPPORTED = 20; + +/** + * The Capture interface exposes an interface to the camera and microphone of the hosting device. + */ +function Capture() { + this.supportedAudioModes = []; + this.supportedImageModes = []; + this.supportedVideoModes = []; +}; + +/** + * Launch audio recorder application for recording audio clip(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureAudioOptions} options + * + * No audio recorder to launch for iOS - return CAPTURE_NOT_SUPPORTED + */ +Capture.prototype.captureAudio = function(successCallback, errorCallback, options) { + /*if (errorCallback && typeof errorCallback === "function") { + errorCallback({ + "code": CaptureError.CAPTURE_NOT_SUPPORTED + }); + }*/ + Cordova.exec(successCallback, errorCallback, "org.apache.cordova.mediacapture", "captureAudio", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype.captureImage = function(successCallback, errorCallback, options) { + Cordova.exec(successCallback, errorCallback, "org.apache.cordova.mediacapture", "captureImage", [options]); +}; + +/** + * Casts a PluginResult message property (array of objects) to an array of MediaFile objects + * (used in Objective-C) + * + * @param {PluginResult} pluginResult + */ +Capture.prototype._castMediaFile = function(pluginResult) { + var mediaFiles = []; + var i; + for (i=0; i} categories +* @param {ContactField[]} urls contact's web sites +*/ +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, birthday, note, photos, categories, urls) { + this.id = id || null; + this.displayName = displayName || null; + this.name = name || null; // ContactName + this.nickname = nickname || null; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.birthday = birthday || null; // JS Date + this.note = note || null; + this.photos = photos || null; // ContactField[] + this.categories = categories || null; + this.urls = urls || null; // ContactField[] +}; + +/** +* Converts Dates to milliseconds before sending to iOS +*/ +Contact.prototype.convertDatesOut = function() +{ + var dates = new Array("birthday"); + for (var i=0; i 0) + { + var constructor = Cordova._constructors.shift(); + try + { + constructor(); + } + catch(e) + { + if (typeof(console['log']) == 'function') + { + console.log("Failed to run constructor: " + console.processMessage(e)); + } + else + { + alert("Failed to run constructor: " + e.message); + } + } + } + // all constructors run, now fire the deviceready event + var e = document.createEvent('Events'); + e.initEvent('deviceready'); + document.dispatchEvent(e); + } + }, 1); +})(); + +// session id for calls +Cordova.sessionKey = 0; + +// centralized callbacks +Cordova.callbackId = 0; +Cordova.callbacks = {}; +Cordova.callbackStatus = { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }; + +/** + * Creates a gap bridge iframe used to notify the native code about queued + * commands. + * + * @private + */ +Cordova.createGapBridge = function() { + gapBridge = document.createElement("iframe"); + gapBridge.setAttribute("style", "display:none;"); + gapBridge.setAttribute("height","0px"); + gapBridge.setAttribute("width","0px"); + gapBridge.setAttribute("frameborder","0"); + document.documentElement.appendChild(gapBridge); + return gapBridge; +} + +/** + * Execute a Cordova command by queuing it and letting the native side know + * there are queued commands. The native side will then request all of the + * queued commands and execute them. + * + * Arguments may be in one of two formats: + * + * FORMAT ONE (preferable) + * The native side will call Cordova.callbackSuccess or + * Cordova.callbackError, depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action The name of the action to use + * @param {String[]} [args] Zero or more arguments to pass to the method + * + * FORMAT TWO + * @param {String} command Command to be run in Cordova, e.g. + * "ClassName.method" + * @param {String[]} [args] Zero or more arguments to pass to the method + * object parameters are passed as an array object + * [object1, object2] each object will be passed as + * JSON strings + */ +Cordova.exec = function() { + if (!Cordova.available) { + alert("ERROR: Attempting to call Cordova.exec()" + +" before 'deviceready'. Ignoring."); + return; + } + + var successCallback, failCallback, service, action, actionArgs; + var callbackId = null; + if (typeof arguments[0] !== "string") { + // FORMAT ONE + successCallback = arguments[0]; + failCallback = arguments[1]; + service = arguments[2]; + action = arguments[3]; + actionArgs = arguments[4]; + + // Since we need to maintain backwards compatibility, we have to pass + // an invalid callbackId even if no callback was provided since plugins + // will be expecting it. The Cordova.exec() implementation allocates + // an invalid callbackId and passes it even if no callbacks were given. + callbackId = 'INVALID'; + } else { + // FORMAT TWO + splitCommand = arguments[0].split("."); + action = splitCommand.pop(); + service = splitCommand.join("."); + actionArgs = Array.prototype.splice.call(arguments, 1); + } + + // Start building the command object. + var command = { + className: service, + methodName: action, + arguments: [] + }; + + // Register the callbacks and add the callbackId to the positional + // arguments if given. + if (successCallback || failCallback) { + callbackId = service + Cordova.callbackId++; + Cordova.callbacks[callbackId] = + {success:successCallback, fail:failCallback}; + } + if (callbackId != null) { + command.arguments.push(callbackId); + } + + for (var i = 0; i < actionArgs.length; ++i) { + var arg = actionArgs[i]; + if (arg == undefined || arg == null) { + continue; + } else if (typeof(arg) == 'object') { + command.options = arg; + } else { + command.arguments.push(arg); + } + } + + // Stringify and queue the command. We stringify to command now to + // effectively clone the command arguments in case they are mutated before + // 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 (!Cordova.gapBridge) { + Cordova.gapBridge = Cordova.createGapBridge(); + } + + Cordova.gapBridge.src = "gap://ready"; + } +} + +/** + * Called by native code to retrieve all queued commands and clear the queue. + */ +Cordova.getAndClearQueuedCommands = function() { + json = JSON.stringify(Cordova.commandQueue); + Cordova.commandQueue = []; + return json; +} + +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + * args.status - Cordova.callbackStatus + * args.message - return value + * args.keepCallback - 0 to remove callback, 1 to keep callback in Cordova.callbacks[] + */ +Cordova.callbackSuccess = function(callbackId, args) { + if (Cordova.callbacks[callbackId]) { + + // If result is to be sent to callback + if (args.status == Cordova.callbackStatus.OK) { + try { + if (Cordova.callbacks[callbackId].success) { + Cordova.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete Cordova.callbacks[callbackId]; + } + } +}; + +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ +Cordova.callbackError = function(callbackId, args) { + if (Cordova.callbacks[callbackId]) { + try { + if (Cordova.callbacks[callbackId].fail) { + Cordova.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete Cordova.callbacks[callbackId]; + } + } +}; + + +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +Cordova.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(Cordova.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + if (obj instanceof Date) { + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = Cordova.clone(obj[i]); + } + } + return retVal; +}; + +// Intercept calls to document.addEventListener +Cordova.m_document_addEventListener = document.addEventListener; + +// Intercept calls to window.addEventListener +Cordova.m_window_addEventListener = window.addEventListener; + +/** + * Add a custom window event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +Cordova.addWindowEventHandler = function(event, callback) { + Cordova.windowEventHandler[event] = callback; +} + +/** + * Add a custom document event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +Cordova.addDocumentEventHandler = function(event, callback) { + Cordova.documentEventHandler[event] = callback; +} + +/** + * Intercept adding document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof Cordova.documentEventHandler[e] !== "undefined") { + if (Cordova.documentEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + Cordova.m_document_addEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept adding window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof Cordova.windowEventHandler[e] !== "undefined") { + if (Cordova.windowEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + Cordova.m_window_addEventListener.call(window, evt, handler, capture); +}; + +// Intercept calls to document.removeEventListener and watch for events that +// are generated by Cordova native code +Cordova.m_document_removeEventListener = document.removeEventListener; + +// Intercept calls to window.removeEventListener +Cordova.m_window_removeEventListener = window.removeEventListener; + +/** + * Intercept removing document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof Cordova.documentEventHandler[e] !== "undefined") { + if (Cordova.documentEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + Cordova.m_document_removeEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept removing window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof Cordova.windowEventHandler[e] !== "undefined") { + if (Cordova.windowEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + Cordova.m_window_removeEventListener.call(window, evt, handler, capture); +}; + +/** + * Method to fire document event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +Cordova.fireDocumentEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + document.dispatchEvent(e); +}; + +/** + * Method to fire window event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +Cordova.fireWindowEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + window.dispatchEvent(e); +}; + +/** + * Method to fire event from native code + * Leaving this generic version to handle problems with iOS 3.x. Is currently used by orientation and battery events + * Remove when iOS 3.x no longer supported and call fireWindowEvent or fireDocumentEvent directly + */ +Cordova.fireEvent = function(type, target, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + target = target || document; + if (target.dispatchEvent === undefined) { // ie window.dispatchEvent is undefined in iOS 3.x + target = document; + } + + target.dispatchEvent(e); +}; +/** + * Create a UUID + * + * @return + */ +Cordova.createUUID = function() { + return Cordova.UUIDcreatePart(4) + '-' + + Cordova.UUIDcreatePart(2) + '-' + + Cordova.UUIDcreatePart(2) + '-' + + Cordova.UUIDcreatePart(2) + '-' + + Cordova.UUIDcreatePart(6); +}; + +Cordova.UUIDcreatePart = function(length) { + var uuidpart = ""; + for (var i=0; i