You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2012/02/17 02:38:49 UTC
[6/27] Rename PhoneGap to Cordova.
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFileTransfer.m b/CordovaLib/Classes/CDVFileTransfer.m
new file mode 100644
index 0000000..499bd47
--- /dev/null
+++ b/CordovaLib/Classes/CDVFileTransfer.m
@@ -0,0 +1,318 @@
+/*
+ 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 "CDVFileTransfer.h"
+#import "CDVFile.h"
+
+
+@implementation CDVFileTransfer
+
+- (void) upload:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
+ NSString* callbackId = [arguments objectAtIndex:0];
+ NSString* fileKey = (NSString*)[options objectForKey:@"fileKey"];
+ NSString* fileName = (NSString*)[options objectForKey:@"fileName"];
+ NSString* mimeType = (NSString*)[options objectForKey:@"mimeType"];
+ NSMutableDictionary* params = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)[options objectForKey:@"params"]];
+ NSString* filePath = (NSString*)[options objectForKey:@"filePath"];
+ NSString* server = (NSString*)[options objectForKey:@"server"];
+ CDVPluginResult* result = nil;
+ CDVFileTransferError errorCode = 0;
+
+
+ NSURL* file;
+ NSData *fileData = nil;
+
+ if ([filePath hasPrefix:@"/"]) {
+ file = [NSURL fileURLWithPath:filePath];
+ } else {
+ file = [NSURL URLWithString:filePath];
+ }
+
+ NSURL *url = [NSURL URLWithString:server];
+
+
+ if (!url) {
+ errorCode = INVALID_URL_ERR;
+ NSLog(@"File Transfer Error: Invalid server URL");
+ } else if(![file isFileURL]) {
+ errorCode = FILE_NOT_FOUND_ERR;
+ NSLog(@"File Transfer Error: Invalid file path or URL");
+ } else {
+ // check that file is valid
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ BOOL bIsDirectory = NO;
+ BOOL bExists = [fileMgr fileExistsAtPath:[file path] isDirectory:&bIsDirectory];
+ if (!bExists || bIsDirectory) {
+ errorCode = FILE_NOT_FOUND_ERR;
+ } else {
+ // file exists, make sure we can get the data
+ fileData = [NSData dataWithContentsOfURL:file];
+
+ if(!fileData) {
+ errorCode = FILE_NOT_FOUND_ERR;
+ NSLog(@"File Transfer Error: Could not read file data");
+ }
+ }
+ [fileMgr release];
+ }
+
+ if(errorCode > 0) {
+ //result = [PluginResult resultWithStatus: PGCommandStatus_OK messageAsInt: INVALID_URL_ERR cast: @"navigator.fileTransfer._castTransferError"];
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: [self createFileTransferError:[NSString stringWithFormat:@"%d", errorCode] AndSource:filePath AndTarget:server]];
+
+ [self writeJavascript:[result toErrorCallbackString:callbackId]];
+ return;
+ }
+
+ NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
+ [req setHTTPMethod:@"POST"];
+
+// Magic value to set a cookie
+ if([params objectForKey:@"__cookie"]) {
+ [req setValue:[params objectForKey:@"__cookie"] forHTTPHeaderField:@"Cookie"];
+ [params removeObjectForKey:@"__cookie"];
+ [req setHTTPShouldHandleCookies:NO];
+ }
+
+ NSString *boundary = @"*****org.apache.cordova.formBoundary";
+
+ NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
+ [req setValue:contentType forHTTPHeaderField:@"Content-Type"];
+ //Content-Type: multipart/form-data; boundary=*****org.apache.cordova.formBoundary
+ [req setValue:@"XMLHttpRequest" forHTTPHeaderField:@"X-Requested-With"];
+ NSString* userAgent = [[self.webView request] valueForHTTPHeaderField:@"User-agent"];
+ if(userAgent) {
+ [req setValue: userAgent forHTTPHeaderField:@"User-Agent"];
+ }
+
+
+ NSMutableData *postBody = [NSMutableData data];
+
+ NSEnumerator *enumerator = [params keyEnumerator];
+ id key;
+ id val;
+
+ while ((key = [enumerator nextObject])) {
+ val = [params objectForKey:key];
+ if(!val || val == [NSNull null]) {
+ continue;
+ }
+ // if it responds to stringValue selector (eg NSNumber) get the NSString
+ if ([val respondsToSelector:@selector(stringValue)]) {
+ val = [val stringValue];
+ }
+ // finally, check whether it is a NSString (for dataUsingEncoding selector below)
+ if (![val isKindOfClass:[NSString class]]) {
+ continue;
+ }
+
+ [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[val dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+
+ [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fileKey, fileName] dataUsingEncoding:NSUTF8StringEncoding]];
+ [postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimeType] dataUsingEncoding:NSUTF8StringEncoding]];
+ NSLog(@"fileData length: %d", [fileData length]);
+ [postBody appendData:fileData];
+ [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
+
+ //[req setValue:[[NSNumber numberWithInteger:[postBody length]] stringValue] forHTTPHeaderField:@"Content-Length"];
+ [req setHTTPBody:postBody];
+
+
+ CDVFileTransferDelegate* delegate = [[[CDVFileTransferDelegate alloc] init] autorelease];
+ delegate.command = self;
+ delegate.callbackId = callbackId;
+ delegate.source = server;
+ delegate.target = filePath;
+
+ [NSURLConnection connectionWithRequest:req delegate:delegate];
+
+}
+
+- (void) download:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
+ NSLog(@"File Transfer downloading file...");
+
+ [self performSelectorInBackground:@selector(downloadFile:) withObject:arguments];
+}
+
+-(void) downloadFile:(NSMutableArray*)arguments {
+ NSString * callbackId = [arguments objectAtIndex:0];
+ NSString * sourceUrl = [arguments objectAtIndex:1];
+ NSString * filePath = [arguments objectAtIndex:2];
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString:sourceUrl] ];
+ NSArray * results = nil;
+
+ NSLog(@"Write file %@", filePath);
+ NSError *error=[[[NSError alloc]init] autorelease];
+
+ @try {
+ NSString * parentPath = [ filePath stringByDeletingLastPathComponent ];
+
+ // check if the path exists => create directories if needed
+ if(![[NSFileManager defaultManager] fileExistsAtPath:parentPath ]) [[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:nil];
+
+ BOOL response = [data writeToFile:filePath options:NSDataWritingFileProtectionNone error:&error];
+
+ if ( response == NO ) {
+ // send our results back to the main thread
+ results = [NSArray arrayWithObjects: callbackId, [NSString stringWithFormat:@"%d", INVALID_URL_ERR], sourceUrl, filePath, nil];
+ [self performSelectorOnMainThread:@selector(downloadFail:) withObject:results waitUntilDone:YES];
+ } else {
+ // jump back to main thread
+ results = [NSArray arrayWithObjects: callbackId, filePath, nil];
+ [self performSelectorOnMainThread:@selector(downloadSuccess:) withObject:results waitUntilDone:YES];
+ }
+ }
+ @catch (id exception) {
+ // jump back to main thread
+ results = [NSArray arrayWithObjects: callbackId, [NSString stringWithFormat:@"%d", FILE_NOT_FOUND_ERR], sourceUrl, filePath, nil];
+ [self performSelectorOnMainThread:@selector(downloadFail:) withObject:results waitUntilDone:YES];
+ }
+
+ [pool drain];
+}
+
+-(void) downloadSuccess:(NSMutableArray *)arguments
+{
+ NSString * callbackId = [arguments objectAtIndex:0];
+ NSString * filePath = [arguments objectAtIndex:1];
+
+ BOOL bDirRequest = NO;
+
+ NSLog(@"File Transfert Download success");
+
+ CDVFile * file = [[[CDVFile alloc] init] autorelease];
+
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: [file getDirectoryEntry: filePath isDirectory: bDirRequest] cast: @"window.localFileSystem._castEntry"];
+ [self writeJavascript: [result toSuccessCallbackString:callbackId]];
+}
+
+-(void) downloadFail:(NSMutableArray *)arguments
+{
+ NSString * callbackId = [arguments objectAtIndex:0];
+ NSString * code = [arguments objectAtIndex:1];
+ NSString * source = [arguments objectAtIndex:2];
+ NSString * target = [arguments objectAtIndex:3];
+
+ NSLog(@"File Transfer Error: %@", source);
+
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: [self createFileTransferError:code AndSource:source AndTarget:target]];
+
+ [self writeJavascript: [pluginResult toErrorCallbackString:callbackId]];
+}
+
+-(NSMutableDictionary*) createFileTransferError:(NSString*)code AndSource:(NSString*)source AndTarget:(NSString*)target
+{
+ NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:3];
+ [result setObject: code forKey:@"code"];
+ [result setObject: source forKey:@"source"];
+ [result setObject: target forKey:@"target"];
+
+ return result;
+}
+
+@end
+
+
+@implementation CDVFileTransferDelegate
+
+@synthesize callbackId, source, target, responseData, command, bytesWritten;
+
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection
+{
+ NSString* response = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
+ // create dictionary to return FileUploadResult object
+ NSMutableDictionary* uploadResult = [NSMutableDictionary dictionaryWithCapacity:3];
+ [uploadResult setObject: [response stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey: @"response"];
+ [uploadResult setObject:[NSNumber numberWithInt: self.bytesWritten] forKey:@"bytesSent"];
+ [uploadResult setObject:[NSNull null] forKey: @"responseCode"];
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: uploadResult cast: @"navigator.fileTransfer._castUploadResult"];
+ [command writeJavascript:[result toSuccessCallbackString: callbackId]];
+ [response release];
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
+{
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: [command createFileTransferError: [NSString stringWithFormat: @"%d", CONNECTION_ERR] AndSource:source AndTarget:target]];
+ NSLog(@"File Transfer Error: %@", [error localizedDescription]);
+ [command writeJavascript:[result toErrorCallbackString: callbackId]];
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
+{
+ [responseData appendData:data];
+}
+- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
+{
+ self.bytesWritten = totalBytesWritten;
+}
+/* TESTING ONLY CODE
+// use ONLY for testing with self signed certificates
+// uncomment and modify server name in connectiondidReceiveAuthenticationChallenge
+- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
+{
+ return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
+}
+
+- (void)connection:(NSURLConnection *) connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge
+{
+ if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
+ {
+ //NSLog(@"challenge host: %@", challenge.protectionSpace.host);
+ // we only trust our own domain
+ if ([challenge.protectionSpace.host isEqualToString:@"serverName.domain.com"]){
+ NSURLCredential* myCredential = [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust];
+
+ [challenge.sender useCredential:myCredential forAuthenticationChallenge:challenge];
+
+ }
+ }
+
+ [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
+}
+// uncomment the above two methods for testing servers with self signed certificates
+// END TESTING ONLY CODE
+ */
+- (id) init
+{
+ if ((self = [super init])) {
+ self.responseData = [NSMutableData data];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [callbackId release];
+ [responseData release];
+ [command release];
+ [super dealloc];
+}
+
+
+@end;
+
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVInvokedUrlCommand.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInvokedUrlCommand.h b/CordovaLib/Classes/CDVInvokedUrlCommand.h
new file mode 100644
index 0000000..b7beb7d
--- /dev/null
+++ b/CordovaLib/Classes/CDVInvokedUrlCommand.h
@@ -0,0 +1,39 @@
+/*
+ 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 <Foundation/Foundation.h>
+
+
+@interface CDVInvokedUrlCommand : NSObject {
+ NSString* className;
+ NSString* methodName;
+ NSMutableArray* arguments;
+ NSMutableDictionary* options;
+}
+
+@property(retain) NSMutableArray* arguments;
+@property(retain) NSMutableDictionary* options;
+@property(copy) NSString* className;
+@property(copy) NSString* methodName;
+
++ (CDVInvokedUrlCommand*) commandFromObject:(NSDictionary*)object;
+
+- (void) dealloc;
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVInvokedUrlCommand.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInvokedUrlCommand.m b/CordovaLib/Classes/CDVInvokedUrlCommand.m
new file mode 100644
index 0000000..45b0a1d
--- /dev/null
+++ b/CordovaLib/Classes/CDVInvokedUrlCommand.m
@@ -0,0 +1,51 @@
+/*
+ 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 "CDVInvokedUrlCommand.h"
+#import "JSONKit.h"
+
+@implementation CDVInvokedUrlCommand
+
+@synthesize arguments;
+@synthesize options;
+@synthesize className;
+@synthesize methodName;
+
++ (CDVInvokedUrlCommand*) commandFromObject:(NSDictionary*)object
+{
+ CDVInvokedUrlCommand* iuc = [[[CDVInvokedUrlCommand alloc] init] autorelease];
+ iuc.className = [object objectForKey:@"className"];
+ iuc.methodName = [object objectForKey:@"methodName"];
+ iuc.arguments = [object objectForKey:@"arguments"];
+ iuc.options = [object objectForKey:@"options"];
+
+ return iuc;
+}
+
+- (void) dealloc
+{
+ [arguments release];
+ [options release];
+ [className release];
+ [methodName release];
+
+ [super dealloc];
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVLocation.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocation.h b/CordovaLib/Classes/CDVLocation.h
new file mode 100755
index 0000000..e18aef6
--- /dev/null
+++ b/CordovaLib/Classes/CDVLocation.h
@@ -0,0 +1,91 @@
+/*
+ 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 <UIKit/UIKit.h>
+#import <CoreLocation/CoreLocation.h>
+#import "CDVPlugin.h"
+
+enum CDVHeadingStatus {
+ HEADINGSTOPPED = 0,
+ HEADINGSTARTING,
+ HEADINGRUNNING,
+ HEADINGERROR
+};
+typedef NSUInteger CDVHeadingStatus;
+
+// simple object to keep track of heading information
+@interface CDVHeadingData : NSObject {
+ CDVHeadingStatus headingStatus;
+ BOOL headingRepeats;
+ CLHeading* headingInfo;
+ NSMutableArray* headingCallbacks;
+ NSString* headingFilter;
+
+}
+
+@property (nonatomic, assign) CDVHeadingStatus headingStatus;
+@property (nonatomic, assign) BOOL headingRepeats;
+@property (nonatomic, retain) CLHeading* headingInfo;
+@property (nonatomic, retain) NSMutableArray* headingCallbacks;
+@property (nonatomic, retain) NSString* headingFilter;
+
+@end
+
+@interface CDVLocation : CDVPlugin <CLLocationManagerDelegate> {
+
+ @private BOOL __locationStarted;
+ CDVHeadingData* headingData;
+}
+
+@property (nonatomic, retain) CLLocationManager *locationManager;
+@property (nonatomic, retain) CDVHeadingData* headingData;
+
+
+- (BOOL) hasHeadingSupport;
+
+- (void)startLocation:(NSMutableArray*)arguments
+ withDict:(NSMutableDictionary*)options;
+
+- (void)stopLocation:(NSMutableArray*)arguments
+ withDict:(NSMutableDictionary*)options;
+
+- (void)locationManager:(CLLocationManager *)manager
+ didUpdateToLocation:(CLLocation *)newLocation
+ fromLocation:(CLLocation *)oldLocation;
+
+- (void)locationManager:(CLLocationManager *)manager
+ didFailWithError:(NSError *)error;
+
+- (BOOL) isLocationServicesEnabled;
+
+- (void)getCurrentHeading:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
+- (void)returnHeadingInfo: (NSString*) callbackId keepCallback: (BOOL) bRetain;
+
+- (void)stopHeading:(NSMutableArray*)arguments
+ withDict:(NSMutableDictionary*)options;
+- (void) startHeadingWithFilter: (CLLocationDegrees) filter;
+- (void)locationManager:(CLLocationManager *)manager
+ didUpdateHeading:(CLHeading *)heading;
+
+- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager;
+
+@end
+
+
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVLocation.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVLocation.m b/CordovaLib/Classes/CDVLocation.m
new file mode 100755
index 0000000..fb6cdb4
--- /dev/null
+++ b/CordovaLib/Classes/CDVLocation.m
@@ -0,0 +1,515 @@
+/*
+ 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 "CDVLocation.h"
+#import "CDVViewController.h"
+
+#pragma mark Constants
+
+#define kPGLocationErrorDomain @"kPGLocationErrorDomain"
+#define kPGLocationDesiredAccuracyKey @"desiredAccuracy"
+#define kPGLocationForcePromptKey @"forcePrompt"
+#define kPGLocationDistanceFilterKey @"distanceFilter"
+#define kPGLocationFrequencyKey @"frequency"
+
+#pragma mark -
+#pragma mark Categories
+
+@interface NSError(JSONMethods)
+
+- (NSString*) JSONRepresentation;
+
+@end
+
+@interface CLLocation(JSONMethods)
+
+- (NSString*) JSONRepresentation;
+
+@end
+
+
+@interface CLHeading(JSONMethods)
+
+- (NSString*) JSONRepresentation;
+
+@end
+
+#pragma mark -
+#pragma mark CDVHeadingData
+
+@implementation CDVHeadingData
+
+@synthesize headingStatus, headingRepeats, headingInfo, headingCallbacks, headingFilter;
+-(CDVHeadingData*) init
+{
+ self = (CDVHeadingData*)[super init];
+ if (self)
+ {
+ self.headingRepeats = NO;
+ self.headingStatus = HEADINGSTOPPED;
+ self.headingInfo = nil;
+ self.headingCallbacks = nil;
+ self.headingFilter = nil;
+ }
+ return self;
+}
+-(void) dealloc
+{
+ self.headingInfo = nil;
+ self.headingCallbacks = nil;
+ self.headingFilter = nil;
+ [super dealloc];
+}
+
+@end
+
+#pragma mark -
+#pragma mark CDVLocation
+
+@implementation CDVLocation
+
+@synthesize locationManager, headingData;
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView
+{
+ self = (CDVLocation*)[super initWithWebView:(UIWebView*)theWebView];
+ if (self)
+ {
+ self.locationManager = [[[CLLocationManager alloc] init] autorelease];
+ self.locationManager.delegate = self; // Tells the location manager to send updates to this object
+ __locationStarted = NO;
+ self.headingData = nil;
+ }
+ return self;
+}
+
+- (BOOL) hasHeadingSupport
+{
+ BOOL headingInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(headingAvailable)]; // iOS 3.x
+ BOOL headingClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(headingAvailable)]; // iOS 4.x
+
+ if (headingInstancePropertyAvailable) { // iOS 3.x
+ return [(id)self.locationManager headingAvailable];
+ } else if (headingClassPropertyAvailable) { // iOS 4.x
+ return [CLLocationManager headingAvailable];
+ } else { // iOS 2.x
+ return NO;
+ }
+}
+
+- (BOOL) isAuthorized
+{
+ BOOL authorizationStatusClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+
+ if (authorizationStatusClassPropertyAvailable)
+ {
+ NSUInteger authStatus = [CLLocationManager authorizationStatus];
+ return (authStatus == kCLAuthorizationStatusAuthorized) || (authStatus == kCLAuthorizationStatusNotDetermined);
+ }
+
+ // by default, assume YES (for iOS < 4.2)
+ return YES;
+}
+
+- (BOOL) isLocationServicesEnabled
+{
+ BOOL locationServicesEnabledInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 3.x
+ BOOL locationServicesEnabledClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 4.x
+
+ if (locationServicesEnabledClassPropertyAvailable)
+ { // iOS 4.x
+ return [CLLocationManager locationServicesEnabled];
+ }
+ else if (locationServicesEnabledInstancePropertyAvailable)
+ { // iOS 2.x, iOS 3.x
+ return [(id)self.locationManager locationServicesEnabled];
+ }
+ else
+ {
+ return NO;
+ }
+}
+
+- (void) startLocation:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ if (![self isLocationServicesEnabled])
+ {
+ BOOL forcePrompt = NO;
+ // if forcePrompt is true iPhone will still show the "Location Services not active." Settings | Cancel prompt.
+ if ([options objectForKey:kPGLocationForcePromptKey])
+ {
+ forcePrompt = [[options objectForKey:kPGLocationForcePromptKey] boolValue];
+ }
+
+ if (!forcePrompt)
+ {
+ NSError* error = [NSError errorWithDomain:kPGLocationErrorDomain code:1 userInfo:
+ [NSDictionary dictionaryWithObject:@"Location services is not enabled" forKey:NSLocalizedDescriptionKey]];
+ NSLog(@"%@", [error JSONRepresentation]);
+
+ NSString* jsCallback = [NSString stringWithFormat:@"navigator.geolocation.setError(%@);", [error JSONRepresentation]];
+ [super writeJavascript:jsCallback];
+
+ return;
+ }
+ }
+ if (![self isAuthorized])
+ {
+ NSUInteger code = -1;
+ BOOL authStatusAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+
+ if (authStatusAvailable) {
+ code = [CLLocationManager authorizationStatus];
+ }
+
+ NSError* error = [NSError errorWithDomain:NSCocoaErrorDomain code:code userInfo:
+ [NSDictionary dictionaryWithObject:@"App is not authorized for Location Services" forKey:NSLocalizedDescriptionKey]];
+ NSLog(@"%@", [error JSONRepresentation]);
+
+ NSString* jsCallback = [NSString stringWithFormat:@"navigator.geolocation.setError(%@);", [error JSONRepresentation]];
+ [super writeJavascript:jsCallback];
+
+ return;
+ }
+
+ // Tell the location manager to start notifying us of location updates. We
+ // first stop, and then start the updating to ensure we get at least one
+ // update, even if our location did not change.
+ [self.locationManager stopUpdatingLocation];
+ [self.locationManager startUpdatingLocation];
+ __locationStarted = YES;
+
+ if ([options objectForKey:kPGLocationDistanceFilterKey])
+ {
+ CLLocationDistance distanceFilter = [(NSString *)[options objectForKey:kPGLocationDistanceFilterKey] doubleValue];
+ self.locationManager.distanceFilter = distanceFilter;
+ }
+
+ if ([options objectForKey:kPGLocationDesiredAccuracyKey])
+ {
+ int desiredAccuracy_num = [(NSString *)[options objectForKey:kPGLocationDesiredAccuracyKey] integerValue];
+ CLLocationAccuracy desiredAccuracy = kCLLocationAccuracyBest;
+
+ if (desiredAccuracy_num < 10) {
+ desiredAccuracy = kCLLocationAccuracyBest;
+ }
+ else if (desiredAccuracy_num < 100) {
+ desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
+ }
+ else if (desiredAccuracy_num < 1000) {
+ desiredAccuracy = kCLLocationAccuracyHundredMeters;
+ }
+ else if (desiredAccuracy_num < 3000) {
+ desiredAccuracy = kCLLocationAccuracyKilometer;
+ }
+ else {
+ desiredAccuracy = kCLLocationAccuracyThreeKilometers;
+ }
+
+ self.locationManager.desiredAccuracy = desiredAccuracy;
+ }
+}
+
+- (void) stopLocation:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ if (__locationStarted)
+ {
+ if (![self isLocationServicesEnabled]) {
+ return;
+ }
+
+ [self.locationManager stopUpdatingLocation];
+ __locationStarted = NO;
+ }
+}
+
+- (void) locationManager:(CLLocationManager *)manager
+ didUpdateToLocation:(CLLocation *)newLocation
+ fromLocation:(CLLocation *)oldLocation
+{
+
+ NSString* jsCallback = [NSString stringWithFormat:@"navigator.geolocation.setLocation(%@);", [newLocation JSONRepresentation]];
+ [super writeJavascript:jsCallback];
+}
+// called to get the current heading
+// Will call location manager to startUpdatingHeading if necessary
+
+- (void)getCurrentHeading:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSString* callbackId = [arguments objectAtIndex:0];
+ NSNumber* repeats = [options valueForKey:@"repeats"]; // indicates this call will be repeated at regular intervals
+
+ if ([self hasHeadingSupport] == NO)
+ {
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:20];
+ [super writeJavascript:[result toErrorCallbackString:callbackId]];
+ } else {
+ // heading retrieval does is not affected by disabling locationServices and authorization of app for location services
+ if (!self.headingData) {
+ self.headingData = [[[CDVHeadingData alloc] init] autorelease];
+ }
+ CDVHeadingData* hData = self.headingData;
+
+ if (repeats != nil) {
+ hData.headingRepeats = YES;
+ }
+ if (!hData.headingCallbacks) {
+ hData.headingCallbacks = [NSMutableArray arrayWithCapacity:1];
+ }
+ // add the callbackId into the array so we can call back when get data
+ [hData.headingCallbacks addObject:callbackId];
+
+ if (hData.headingStatus != HEADINGRUNNING && hData.headingStatus != HEADINGERROR) {
+ // Tell the location manager to start notifying us of heading updates
+ [self startHeadingWithFilter: 0.2];
+ }
+ else {
+ [self returnHeadingInfo: callbackId keepCallback:NO];
+ }
+ }
+
+
+}
+// called to request heading updates when heading changes by a certain amount (filter)
+- (void)watchHeadingFilter:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSString* callbackId = [arguments objectAtIndex:0];
+ NSNumber* filter = [options valueForKey:@"filter"];
+ CDVHeadingData* hData = self.headingData;
+ if ([self hasHeadingSupport] == NO) {
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:20];
+ [super writeJavascript:[result toErrorCallbackString:callbackId]];
+ } else {
+ if (!hData) {
+ self.headingData = [[[CDVHeadingData alloc] init] autorelease];
+ hData = self.headingData;
+ }
+ if (hData.headingStatus != HEADINGRUNNING) {
+ // Tell the location manager to start notifying us of heading updates
+ [self startHeadingWithFilter: [filter doubleValue]];
+ } else {
+ // if already running check to see if due to existing watch filter
+ if (hData.headingFilter && ![hData.headingFilter isEqualToString:callbackId]){
+ // new watch filter being specified
+ // send heading data one last time to clear old successCallback
+ [self returnHeadingInfo:hData.headingFilter keepCallback: NO];
+ }
+
+ }
+ // save the new filter callback and update the headingFilter setting
+ hData.headingFilter = callbackId;
+ // check if need to stop and restart in order to change value???
+ self.locationManager.headingFilter = [filter doubleValue];
+ }
+}
+- (void)returnHeadingInfo: (NSString*) callbackId keepCallback: (BOOL) bRetain
+{
+ CDVPluginResult* result = nil;
+ NSString* jsString = nil;
+ CDVHeadingData* hData = self.headingData;
+
+ if (hData && hData.headingStatus == HEADINGERROR) {
+ // return error
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:0];
+ jsString = [result toErrorCallbackString:callbackId];
+ } else if (hData && hData.headingStatus == HEADINGRUNNING && hData.headingInfo) {
+ // if there is heading info, return it
+ CLHeading* hInfo = hData.headingInfo;
+ NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:4];
+ NSNumber* timestamp = [NSNumber numberWithDouble:([hInfo.timestamp timeIntervalSince1970]*1000)];
+ [returnInfo setObject:timestamp forKey:@"timestamp"];
+ [returnInfo setObject:[NSNumber numberWithDouble: hInfo.magneticHeading] forKey:@"magneticHeading"];
+ id trueHeading = __locationStarted ? (id)[NSNumber numberWithDouble:hInfo.trueHeading]:(id)[NSNull null];
+ [returnInfo setObject:trueHeading forKey:@"trueHeading"];
+ [returnInfo setObject:[NSNumber numberWithDouble: hInfo.headingAccuracy] forKey:@"headingAccuracy"];
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: returnInfo];
+ [result setKeepCallbackAsBool:bRetain];
+
+ jsString = [result toSuccessCallbackString:callbackId];
+ }
+ if (jsString) {
+ [super writeJavascript:jsString];
+ }
+
+
+}
+
+- (void) stopHeading:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ CDVHeadingData* hData = self.headingData;
+ if (hData && hData.headingStatus != HEADINGSTOPPED)
+ {
+ if (hData.headingFilter) {
+ // callback one last time to clear callback
+ [self returnHeadingInfo:hData.headingFilter keepCallback:NO];
+ hData.headingFilter = nil;
+ }
+ [self.locationManager stopUpdatingHeading];
+ self.headingData = nil;
+ }
+}
+
+
+// helper method to check the orientation and start updating headings
+- (void) startHeadingWithFilter: (CLLocationDegrees) filter
+{
+ if ([self.locationManager respondsToSelector: @selector(headingOrientation)]) {
+ UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
+ if (currentOrientation != UIDeviceOrientationUnknown) {
+ CDVViewController* pgViewController = (CDVViewController*)self.viewController;
+
+ if ([pgViewController.supportedOrientations containsObject:
+ [NSNumber numberWithInt:currentOrientation]]) {
+
+ self.locationManager.headingOrientation = (CLDeviceOrientation)currentOrientation;
+ // FYI UIDeviceOrientation and CLDeviceOrientation enums are currently the same
+ }
+ }
+ }
+ self.locationManager.headingFilter = filter;
+ [self.locationManager startUpdatingHeading];
+ self.headingData.headingStatus = HEADINGSTARTING;
+}
+- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
+{
+ return YES;
+}
+
+- (void) locationManager:(CLLocationManager *)manager
+ didUpdateHeading:(CLHeading *)heading
+{
+ CDVHeadingData* hData = self.headingData;
+ // save the data for next call into getHeadingData
+ hData.headingInfo = heading;
+
+ if (hData.headingStatus == HEADINGSTARTING) {
+ hData.headingStatus = HEADINGRUNNING; // so returnHeading info will work
+ //this is the first update
+ for (NSString* callbackId in hData.headingCallbacks) {
+ [self returnHeadingInfo:callbackId keepCallback:NO];
+ }
+ [hData.headingCallbacks removeAllObjects];
+ if (!hData.headingRepeats && !hData.headingFilter) {
+ [self stopHeading:nil withDict:nil];
+ }
+ }
+ if (hData.headingFilter) {
+ [self returnHeadingInfo: hData.headingFilter keepCallback:YES];
+ }
+ hData.headingStatus = HEADINGRUNNING; // to clear any error
+
+}
+- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
+{
+ NSLog(@"locationManager::didFailWithError %@", [error localizedFailureReason]);
+ NSString* jsCallback = @"";
+
+ // Compass Error
+ if ([error code] == kCLErrorHeadingFailure)
+ {
+ CDVHeadingData* hData = self.headingData;
+ if (hData) {
+ if (hData.headingStatus == HEADINGSTARTING) {
+ // heading error during startup - report error
+ for (NSString* callbackId in hData.headingCallbacks) {
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:0];
+ [super writeJavascript: [result toErrorCallbackString:callbackId]];
+ }
+ [hData.headingCallbacks removeAllObjects];
+ } // else for frequency watches next call to getCurrentHeading will report error
+ else if (hData.headingFilter) {
+ CDVPluginResult* resultFilter = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:0];
+ [super writeJavascript: [resultFilter toErrorCallbackString:hData.headingFilter]];
+ }
+ hData.headingStatus = HEADINGERROR;
+ }
+ }
+ // Location Error
+ else
+ {
+ /*
+ W3C PositionError
+ PositionError.UNKNOWN_ERROR = 0; // equivalent to kCLErrorLocationUnknown=0
+ PositionError.PERMISSION_DENIED = 1; // equivalent to kCLErrorDenied=1
+ PositionError.POSITION_UNAVAILABLE = 2; // equivalent to kCLErrorNetwork=2
+
+ (any other errors are translated to PositionError.UNKNOWN_ERROR)
+ */
+ if (error.code > kCLErrorNetwork) {
+ error = [NSError errorWithDomain:error.domain code:kCLErrorLocationUnknown userInfo:error.userInfo];
+ }
+
+ jsCallback = [NSString stringWithFormat:@"navigator.geolocation.setError(%@);", [error JSONRepresentation]];
+ }
+
+ [super writeJavascript:jsCallback];
+
+ [self.locationManager stopUpdatingLocation];
+ __locationStarted = NO;
+}
+
+- (void) dealloc
+{
+ self.locationManager.delegate = nil;
+ self.locationManager = nil;
+ self.headingData = nil;
+ [super dealloc];
+}
+
+@end
+
+#pragma mark -
+#pragma mark CLLocation(JSONMethods)
+
+@implementation CLLocation(JSONMethods)
+
+- (NSString*) JSONRepresentation
+{
+ return [NSString stringWithFormat:
+ @"{ timestamp: %.00f, \
+ coords: { latitude: %f, longitude: %f, altitude: %.02f, heading: %.02f, speed: %.02f, accuracy: %.02f, altitudeAccuracy: %.02f } \
+ }",
+ [self.timestamp timeIntervalSince1970] * 1000.0,
+ self.coordinate.latitude,
+ self.coordinate.longitude,
+ self.altitude,
+ self.course,
+ self.speed,
+ self.horizontalAccuracy,
+ self.verticalAccuracy
+ ];
+}
+
+@end
+
+
+#pragma mark NSError(JSONMethods)
+
+@implementation NSError(JSONMethods)
+
+- (NSString*) JSONRepresentation
+{
+ return [NSString stringWithFormat:
+ @"{ code: %d, message: '%@'}",
+ self.code,
+ [self localizedDescription]
+ ];
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVMotion.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVMotion.h b/CordovaLib/Classes/CDVMotion.h
new file mode 100644
index 0000000..4abb037
--- /dev/null
+++ b/CordovaLib/Classes/CDVMotion.h
@@ -0,0 +1,36 @@
+/*
+ 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 <Foundation/Foundation.h>
+#import "CDVPlugin.h"
+
+
+@interface CDVMotion : CDVPlugin {
+}
+
+@property (readonly, getter=isDeviceMotionAvailable) BOOL deviceMotionAvailable;
+@property (readonly, getter=isDeviceOrientationAvailable) BOOL deviceOrientationAvailable;
+
+
+/* Checks whether the DeviceMotionEvent is available in the UIWebView */
+- (BOOL) deviceMotionAvailable;
+/* Checks whether the DeviceOrientationEvent is available in the UIWebView */
+- (BOOL) deviceOrientationAvailable;
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVMotion.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVMotion.m b/CordovaLib/Classes/CDVMotion.m
new file mode 100644
index 0000000..de94334
--- /dev/null
+++ b/CordovaLib/Classes/CDVMotion.m
@@ -0,0 +1,78 @@
+/*
+ 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 "CDVMotion.h"
+
+@implementation CDVMotion
+
+@synthesize deviceMotionAvailable, deviceOrientationAvailable;
+
+- (void) startDeviceMotionEvents
+{
+ // TODO: all iOS devices have accelerometers. Barring a way to detect if any listeners are bound,
+ // we will have to flood the UIWebView with these events
+ // If !isDeviceMotionAvailable, we pump out the events
+}
+
+- (void) startDeviceOrientationEvents
+{
+ // TODO: currently only iPhone 4 has support for gyro. We would only need to fill in support for iOS 4.0 and 4.1
+ // (since the DeviceOrientationEvent is supported in in 4.2 for UIWebView)
+ // If gyro is available (see CMMotionManagerin CoreMotion.framework) AND !isDeviceOrientationAvailable, we pump out the events
+}
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView
+{
+ self = (CDVMotion*)[super initWithWebView:theWebView];
+ if (self) {
+ // this class has to be created somewhere for it to pump out events,
+ // perhaps in the AppDelegate
+ if (self.isDeviceMotionAvailable) {
+ [self startDeviceMotionEvents];
+ }
+ if (self.isDeviceOrientationAvailable) {
+ [self startDeviceOrientationEvents];
+ }
+ }
+ return self;
+}
+
+- (BOOL) deviceMotionAvailable
+{
+ NSString* js = @"window.DeviceMotionEvent != undefined";
+ NSString* result = [self.webView stringByEvaluatingJavaScriptFromString:js];
+
+ return [result isEqualToString:@"true"];
+}
+
+- (BOOL) deviceOrientationAvailable
+{
+ NSString* js = @"window.DeviceOrientationEvent != undefined";
+ NSString* result = [self.webView stringByEvaluatingJavaScriptFromString:js];
+
+ return [result isEqualToString:@"true"];
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVNotification.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVNotification.h b/CordovaLib/Classes/CDVNotification.h
new file mode 100644
index 0000000..daff4b2
--- /dev/null
+++ b/CordovaLib/Classes/CDVNotification.h
@@ -0,0 +1,41 @@
+/*
+ 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 <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import <AudioToolbox/AudioServices.h>
+#import "CDVPlugin.h"
+
+@interface CDVNotification : CDVPlugin <UIAlertViewDelegate>{
+}
+
+- (void)alert:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; // confirm is just a variant of alert
+- (void)vibrate:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
+
+@end
+
+@interface CDVAlertView : UIAlertView {
+ NSString* callBackId;
+}
+@property(nonatomic, retain) NSString* callbackId;
+
+-(void) dealloc;
+
+@end
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVNotification.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVNotification.m b/CordovaLib/Classes/CDVNotification.m
new file mode 100644
index 0000000..6bb40b4
--- /dev/null
+++ b/CordovaLib/Classes/CDVNotification.m
@@ -0,0 +1,117 @@
+/*
+ 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 "CDVNotification.h"
+#import "NSDictionary+Extensions.h"
+
+
+@implementation CDVNotification
+
+
+- (void)alert:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSString* callbackId = [arguments objectAtIndex:0];
+ NSString* message = [arguments objectAtIndex:1];
+ NSString* title = [options objectForKey:@"title"];
+ NSString* button = [options objectForKey:@"buttonLabel"];
+
+ if (!title)
+ title = @"Alert";
+ if (!button)
+ button = @"OK";
+
+ CDVAlertView *alertView = [[CDVAlertView alloc]
+ initWithTitle:title
+ message:message
+ delegate:self
+ cancelButtonTitle:nil
+ otherButtonTitles:nil];
+
+ [alertView setCallbackId:callbackId];
+ NSArray* labels = [ button componentsSeparatedByString:@","];
+
+ int count = [ labels count ];
+
+ for(int n = 0; n < count; n++)
+ {
+ [ alertView addButtonWithTitle:[labels objectAtIndex:n]];
+ }
+
+ [alertView show];
+ [alertView release];
+}
+
+
+- (void)prompt:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ NSString* callbackId = [arguments objectAtIndex:0];
+ NSString* message = [arguments objectAtIndex:1];
+ NSString* title = [options objectForKey:@"title"];
+ NSString* button = [options objectForKey:@"buttonLabel"];
+
+ if (!title)
+ title = @"Alert";
+ if (!button)
+ button = @"OK";
+
+ CDVAlertView *openURLAlert = [[CDVAlertView alloc]
+ initWithTitle:title
+ message:message delegate:self cancelButtonTitle:button otherButtonTitles:nil];
+ [openURLAlert setCallbackId: callbackId];
+ [openURLAlert show];
+ [openURLAlert release];
+}
+
+/**
+ Callback invoked when an alert dialog's buttons are clicked.
+ Passes the index + label back to JS
+ */
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+ //NSString *buttonLabel = [alertView buttonTitleAtIndex:buttonIndex];
+
+ CDVAlertView* pgAlertView = (CDVAlertView*) alertView;
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsInt: ++buttonIndex];
+ [self writeJavascript:[result toSuccessCallbackString: [pgAlertView callbackId]]];
+ //NSString * jsCallBack = [NSString stringWithFormat:@"navigator.notification._alertCallback(%d,\"%@\");", ++buttonIndex, buttonLabel];
+ //[webView stringByEvaluatingJavaScriptFromString:jsCallBack];
+}
+
+- (void)vibrate:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
+{
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
+}
+
+@end
+
+@implementation CDVAlertView
+@synthesize callbackId;
+
+- (void) dealloc
+{
+ if (callbackId) {
+ [callbackId release];
+ }
+
+
+ [super dealloc];
+}
+@end
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVPlugin.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPlugin.h b/CordovaLib/Classes/CDVPlugin.h
new file mode 100644
index 0000000..662d4e9
--- /dev/null
+++ b/CordovaLib/Classes/CDVPlugin.h
@@ -0,0 +1,65 @@
+/*
+ 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 <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "CDVPluginResult.h"
+#import "NSMutableArray+QueueAdditions.h"
+#import "CDVCommandDelegate.h"
+
+#define CDVPluginHandleOpenURLNotification @"CDVPluginHandleOpenURLNotification"
+
+#define VERIFY_ARGUMENTS(args, expectedCount, callbackId) if (![self verifyArguments:args withExpectedCount:expectedCount andCallbackId:callbackId \
+callerFileName:__FILE__ callerFunctionName:__PRETTY_FUNCTION__]) { return; }
+
+
+@interface CDVPlugin : NSObject {
+}
+
+@property (nonatomic, retain) UIWebView* webView;
+@property (nonatomic, retain) NSDictionary* settings;
+@property (nonatomic, retain) UIViewController* viewController;
+@property (nonatomic, retain) id<CDVCommandDelegate> commandDelegate;
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings;
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView;
+
+- (void) handleOpenURL:(NSNotification*)notification;
+- (void) onAppTerminate;
+- (void) onMemoryWarning;
+
+/*
+ // see initWithWebView implementation
+ - (void) onPause {}
+ - (void) onResume {}
+ - (void) onOrientationWillChange {}
+ - (void) onOrientationDidChange {}
+ */
+
+- (id) appDelegate;
+- (UIViewController*) appViewController __attribute__((deprecated)); /* just use the .viewController property in the future */
+
+- (NSString*) writeJavascript:(NSString*)javascript;
+- (NSString*) success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId;
+- (NSString*) error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId;
+
+- (BOOL) verifyArguments:(NSMutableArray*)arguments withExpectedCount:(NSUInteger)expectedCount andCallbackId:(NSString*)callbackId
+ callerFileName:(const char*)callerFileName callerFunctionName:(const char*)callerFunctionName;
+
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVPlugin.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPlugin.m b/CordovaLib/Classes/CDVPlugin.m
new file mode 100644
index 0000000..cdb4821
--- /dev/null
+++ b/CordovaLib/Classes/CDVPlugin.m
@@ -0,0 +1,161 @@
+/*
+ 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 "CDVPlugin.h"
+
+
+@implementation CDVPlugin
+@synthesize webView, settings, viewController, commandDelegate;
+
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings
+{
+ self = [self initWithWebView:theWebView];
+ if (self) {
+ self.settings = classSettings;
+ }
+ return self;
+}
+
+- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView
+{
+ self = [super init];
+ if (self) {
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:CDVPluginHandleOpenURLNotification object:nil];
+
+ self.webView = theWebView;
+
+ // You can listen to more app notifications, see:
+ // http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006728-CH3-DontLinkElementID_4
+ /*
+ // NOTE: if you want to use these, make sure you uncomment the corresponding notification handler, and also the removeObserver in dealloc
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume) name:UIApplicationWillEnterForegroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationWillChange) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+ */
+ }
+ return self;
+}
+
+/*
+ The arguments passed in should not included the callbackId.
+ If argument count is not as expected, it will call the error callback using PluginResult (if callbackId is available),
+ or it will write to stderr using NSLog.
+
+ Usage is through the VERIFY_ARGUMENTS macro.
+ */
+- (BOOL) verifyArguments:(NSMutableArray*)arguments withExpectedCount:(NSUInteger)expectedCount andCallbackId:(NSString*)callbackId
+ callerFileName:(const char*)callerFileName callerFunctionName:(const char*)callerFunctionName
+{
+ NSUInteger argc = [arguments count];
+ BOOL ok = (argc >= expectedCount); // allow for optional arguments
+
+ if (!ok) {
+ NSString* errorString = [NSString stringWithFormat:@"Incorrect no. of arguments for plugin: was %d, expected %d", argc, expectedCount];
+ if (callbackId) {
+ NSString* callbackId = [arguments objectAtIndex:0];
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorString];
+ [self writeJavascript:[pluginResult toErrorCallbackString:callbackId]];
+ } else {
+ NSString* fileName = [[[[NSString alloc] initWithBytes:callerFileName length:strlen(callerFileName) encoding:NSUTF8StringEncoding] autorelease] lastPathComponent];
+ NSLog(@"%@::%s - Error: %@", fileName, callerFunctionName, errorString);
+ }
+ }
+
+ return ok;
+}
+
+/*
+// NOTE: for onPause and onResume, calls into JavaScript must not call or trigger any blocking UI, like alerts
+- (void) onPause {}
+- (void) onResume {}
+- (void) onOrientationWillChange {}
+- (void) onOrientationDidChange {}
+*/
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void) handleOpenURL:(NSNotification*)notification
+{
+ // override to handle urls sent to your app
+ // register your url schemes in your App-Info.plist
+
+ NSURL* url = [notification object];
+ if ([url isKindOfClass:[NSURL class]]) {
+ /* Do your thing! */
+ }
+}
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void) onAppTerminate
+{
+ // override this if you need to do any cleanup on app exit
+}
+
+- (void) onMemoryWarning
+{
+ // override to remove caches, etc
+}
+
+- (void) dealloc
+{
+ self.settings = nil;
+ self.webView = nil;
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:CDVPluginHandleOpenURLNotification object:nil];
+ /*
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+ */
+ [super dealloc];
+}
+
+- (id) appDelegate
+{
+ return [[UIApplication sharedApplication] delegate];
+}
+
+/* deprecated - just use the viewController property */
+- (UIViewController*) appViewController
+{
+ return self.viewController;
+}
+
+- (NSString*) writeJavascript:(NSString*)javascript
+{
+ return [self.webView stringByEvaluatingJavaScriptFromString:javascript];
+}
+
+- (NSString*) success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId
+{
+ return [self writeJavascript:[NSString stringWithFormat:@"setTimeout(function() { %@; }, 0);", [pluginResult toSuccessCallbackString:callbackId]]];
+}
+
+- (NSString*) error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId
+{
+ return [self writeJavascript:[NSString stringWithFormat:@"setTimeout(function() { %@; }, 0);", [pluginResult toErrorCallbackString:callbackId]]];
+}
+
+@end
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVPluginResult.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPluginResult.h b/CordovaLib/Classes/CDVPluginResult.h
new file mode 100644
index 0000000..aeaf853
--- /dev/null
+++ b/CordovaLib/Classes/CDVPluginResult.h
@@ -0,0 +1,73 @@
+/*
+ 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 <Foundation/Foundation.h>
+
+typedef enum {
+ CDVCommandStatus_NO_RESULT = 0,
+ CDVCommandStatus_OK,
+ CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION,
+ CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION,
+ CDVCommandStatus_INSTANTIATION_EXCEPTION,
+ CDVCommandStatus_MALFORMED_URL_EXCEPTION,
+ CDVCommandStatus_IO_EXCEPTION,
+ CDVCommandStatus_INVALID_ACTION,
+ CDVCommandStatus_JSON_EXCEPTION,
+ CDVCommandStatus_ERROR
+} CDVCommandStatus;
+
+@interface CDVPluginResult : NSObject {
+ NSNumber* status;
+ id message;
+ NSNumber* keepCallback;
+ NSString* cast;
+
+}
+
+@property (nonatomic, retain, readonly) NSNumber* status;
+@property (nonatomic, retain, readonly) id message;
+@property (nonatomic, retain) NSNumber* keepCallback;
+@property (nonatomic, retain, readonly) NSString* cast;
+
+-(CDVPluginResult*) init;
++(void) releaseStatus;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsString: (NSString*) theMessage;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsArray: (NSArray*) theMessage;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsInt: (int) theMessage;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDouble: (double) theMessage;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDictionary: (NSDictionary*) theMessage;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsString: (NSString*) theMessage cast: (NSString*) theCast;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsArray: (NSArray*) theMessage cast: (NSString*) theCast;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsInt: (int) theMessage cast: (NSString*) theCast;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDouble: (double) theMessage cast: (NSString*) theCast;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDictionary: (NSDictionary*) theMessage cast: (NSString*) theCast;
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageToErrorObject: (int) errorCode;
+
+
+
+-(void) setKeepCallbackAsBool: (BOOL) bKeepCallback;
+
+
+-(NSString*) toJSONString;
+-(NSString*) toSuccessCallbackString: (NSString*) callbackId;
+-(NSString*) toErrorCallbackString: (NSString*) callbackId;
+
+-(void) dealloc;
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVPluginResult.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVPluginResult.m b/CordovaLib/Classes/CDVPluginResult.m
new file mode 100644
index 0000000..57f1577
--- /dev/null
+++ b/CordovaLib/Classes/CDVPluginResult.m
@@ -0,0 +1,176 @@
+/*
+ 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 "CDVPluginResult.h"
+#import "JSONKit.h"
+#import "CDVDebug.h"
+
+@interface CDVPluginResult()
+
+-(CDVPluginResult*) initWithStatus:(CDVCommandStatus)statusOrdinal message: (id) theMessage cast: (NSString*) theCast;
+
+@end
+
+
+@implementation CDVPluginResult
+@synthesize status, message, keepCallback, cast;
+
+static NSArray* org_apache_cordova_CommandStatusMsgs;
+
++(void) initialize
+{
+ org_apache_cordova_CommandStatusMsgs = [[NSArray alloc] initWithObjects: @"No result",
+ @"OK",
+ @"Class not found",
+ @"Illegal access",
+ @"Instantiation error",
+ @"Malformed url",
+ @"IO error",
+ @"Invalid action",
+ @"JSON error",
+ @"Error",
+ nil];
+}
++(void) releaseStatus
+{
+ if (org_apache_cordova_CommandStatusMsgs != nil){
+ [org_apache_cordova_CommandStatusMsgs release];
+ org_apache_cordova_CommandStatusMsgs = nil;
+ }
+}
+
+-(CDVPluginResult*) init
+{
+ return [self initWithStatus: CDVCommandStatus_NO_RESULT message: nil cast: nil];
+}
+-(CDVPluginResult*) initWithStatus:(CDVCommandStatus)statusOrdinal message: (id) theMessage cast: (NSString*) theCast{
+ self = [super init];
+ if(self) {
+ status = [NSNumber numberWithInt: statusOrdinal];
+ message = theMessage;
+ cast = theCast;
+ keepCallback = [NSNumber numberWithBool: NO];
+ }
+ return self;
+}
+
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: [org_apache_cordova_CommandStatusMsgs objectAtIndex: statusOrdinal] cast: nil] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsString: (NSString*) theMessage
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:nil] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsArray: (NSArray*) theMessage
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:nil] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsInt: (int) theMessage
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: [NSNumber numberWithInt: theMessage] cast:nil] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDouble: (double) theMessage
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: [NSNumber numberWithDouble: theMessage] cast:nil] autorelease];
+}
+
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDictionary: (NSDictionary*) theMessage
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:nil] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsString: (NSString*) theMessage cast: (NSString*) theCast
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:theCast] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsArray: (NSArray*) theMessage cast: (NSString*) theCast
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:theCast] autorelease];
+}
+
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsInt: (int) theMessage cast: (NSString*) theCast
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: [NSNumber numberWithInt: theMessage] cast:theCast] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDouble: (double) theMessage cast: (NSString*) theCast
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: [NSNumber numberWithDouble: theMessage] cast:theCast] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageAsDictionary: (NSDictionary*) theMessage cast: (NSString*) theCast
+{
+ return [[[self alloc] initWithStatus: statusOrdinal message: theMessage cast:theCast] autorelease];
+}
++(CDVPluginResult*) resultWithStatus: (CDVCommandStatus) statusOrdinal messageToErrorObject: (int) errorCode
+{
+ NSDictionary* errDict = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:errorCode] forKey:@"code"];
+ return [[[self alloc] initWithStatus: statusOrdinal message: errDict cast:nil] autorelease];
+}
+
+
+-(void) setKeepCallbackAsBool:(BOOL)bKeepCallback
+{
+ [self setKeepCallback: [NSNumber numberWithBool:bKeepCallback]];
+}
+
+-(NSString*) toJSONString{
+ NSString* resultString = [[NSDictionary dictionaryWithObjectsAndKeys:
+ self.status, @"status",
+ self.message ? self.message : [NSNull null], @"message",
+ self.keepCallback, @"keepCallback",
+ nil] JSONString];
+ DLog(@"PluginResult:toJSONString - %@", resultString);
+ return resultString;
+}
+-(NSString*) toSuccessCallbackString: (NSString*) callbackId
+{
+ NSString* successCB;
+
+ if ([self cast] != nil) {
+ successCB = [NSString stringWithFormat: @"var temp = %@(%@);\nCordova.callbackSuccess('%@',temp);", self.cast, [self toJSONString], callbackId];
+ }
+ else {
+ successCB = [NSString stringWithFormat:@"Cordova.callbackSuccess('%@',%@);", callbackId, [self toJSONString]];
+ }
+ DLog(@"PluginResult toSuccessCallbackString: %@", successCB);
+ return successCB;
+}
+-(NSString*) toErrorCallbackString: (NSString*) callbackId
+{
+ NSString* errorCB = nil;
+
+ if ([self cast] != nil) {
+ errorCB = [NSString stringWithFormat: @"var temp = %@(%@);\nCordova.callbackError('%@',temp);", self.cast, [self toJSONString], callbackId];
+ }
+ else {
+ errorCB = [NSString stringWithFormat:@"Cordova.callbackError('%@',%@);", callbackId, [self toJSONString]];
+ }
+ DLog(@"PluginResult toErrorCallbackString: %@", errorCB);
+ return errorCB;
+}
+
+-(void) dealloc
+{
+ status = nil;
+ message = nil;
+ keepCallback = nil;
+ cast = nil;
+
+ [super dealloc];
+}
+@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVReachability.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVReachability.h b/CordovaLib/Classes/CDVReachability.h
new file mode 100644
index 0000000..b00fb95
--- /dev/null
+++ b/CordovaLib/Classes/CDVReachability.h
@@ -0,0 +1,89 @@
+/*
+
+ File: Reachability.h
+ Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
+
+ Version: 2.2
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under
+ Apple's copyrights in this original Apple software (the "Apple Software"), to
+ use, reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions
+ of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+ to endorse or promote products derived from the Apple Software without specific
+ prior written permission from Apple. Except as expressly stated in this notice,
+ no other rights or licenses, express or implied, are granted by Apple herein,
+ including but not limited to any patent rights that may be infringed by your
+ derivative works or by other works in which the Apple Software may be
+ incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+ DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+ CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+ APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2010 Apple Inc. All Rights Reserved.
+
+*/
+
+
+#import <Foundation/Foundation.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+#import <netinet/in.h>
+
+typedef enum {
+ NotReachable = 0,
+ ReachableViaWWAN, // this value has been swapped with ReachableViaWiFi for Cordova backwards compat. reasons
+ ReachableViaWiFi // this value has been swapped with ReachableViaWWAN for Cordova backwards compat. reasons
+} NetworkStatus;
+#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
+
+@interface CDVReachability: NSObject
+{
+ BOOL localWiFiRef;
+ SCNetworkReachabilityRef reachabilityRef;
+}
+
+//reachabilityWithHostName- Use to check the reachability of a particular host name.
++ (CDVReachability*) reachabilityWithHostName: (NSString*) hostName;
+
+//reachabilityWithAddress- Use to check the reachability of a particular IP address.
++ (CDVReachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
+
+//reachabilityForInternetConnection- checks whether the default route is available.
+// Should be used by applications that do not connect to a particular host
++ (CDVReachability*) reachabilityForInternetConnection;
+
+//reachabilityForLocalWiFi- checks whether a local wifi connection is available.
++ (CDVReachability*) reachabilityForLocalWiFi;
+
+//Start listening for reachability notifications on the current run loop
+- (BOOL) startNotifier;
+- (void) stopNotifier;
+
+- (NetworkStatus) currentReachabilityStatus;
+//WWAN may be available, but not active until a connection has been established.
+//WiFi may require a connection for VPN on Demand.
+- (BOOL) connectionRequired;
+@end
+
+
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/bcff9559/CordovaLib/Classes/CDVReachability.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVReachability.m b/CordovaLib/Classes/CDVReachability.m
new file mode 100644
index 0000000..227264a
--- /dev/null
+++ b/CordovaLib/Classes/CDVReachability.m
@@ -0,0 +1,285 @@
+/*
+
+ File: Reachability.m
+ Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
+
+ Version: 2.2
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under
+ Apple's copyrights in this original Apple software (the "Apple Software"), to
+ use, reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions
+ of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may be used
+ to endorse or promote products derived from the Apple Software without specific
+ prior written permission from Apple. Except as expressly stated in this notice,
+ no other rights or licenses, express or implied, are granted by Apple herein,
+ including but not limited to any patent rights that may be infringed by your
+ derivative works or by other works in which the Apple Software may be
+ incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
+ DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
+ CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+ APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2010 Apple Inc. All Rights Reserved.
+
+*/
+
+#import <sys/socket.h>
+#import <netinet/in.h>
+#import <netinet6/in6.h>
+#import <arpa/inet.h>
+#import <ifaddrs.h>
+#import <netdb.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+
+#import "CDVReachability.h"
+
+#define kShouldPrintReachabilityFlags 0
+
+static void CDVPrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
+{
+#if kShouldPrintReachabilityFlags
+
+ NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
+ (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
+ (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
+
+ (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
+ (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
+ (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
+ (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
+ comment
+ );
+#endif
+}
+
+
+@implementation CDVReachability
+
+static void CDVReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
+{
+ #pragma unused (target, flags)
+// NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
+// NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
+
+ // Converted the asserts above to conditionals, with safe return from the function
+ if (info == NULL) {
+ NSLog(@"info was NULL in ReachabilityCallback");
+ return;
+ }
+
+ if (![(NSObject*) info isKindOfClass: [CDVReachability class]]) {
+ NSLog(@"info was wrong class in ReachabilityCallback");
+ return;
+ }
+
+ //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
+ // in case someon uses the Reachablity object in a different thread.
+ NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
+
+ CDVReachability* noteObject = (CDVReachability*) info;
+ // Post a notification to notify the client that the network reachability changed.
+ [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
+
+ [myPool release];
+}
+
+- (BOOL) startNotifier
+{
+ BOOL retVal = NO;
+ SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
+ if(SCNetworkReachabilitySetCallback(reachabilityRef, CDVReachabilityCallback, &context))
+ {
+ if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
+ {
+ retVal = YES;
+ }
+ }
+ return retVal;
+}
+
+- (void) stopNotifier
+{
+ if(reachabilityRef!= NULL)
+ {
+ SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ }
+}
+
+- (void) dealloc
+{
+ [self stopNotifier];
+ if(reachabilityRef!= NULL)
+ {
+ CFRelease(reachabilityRef);
+ }
+ [super dealloc];
+}
+
++ (CDVReachability*) reachabilityWithHostName: (NSString*) hostName;
+{
+ CDVReachability* retVal = NULL;
+ SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
+ if(reachability!= NULL)
+ {
+ retVal= [[[self alloc] init] autorelease];
+ if(retVal!= NULL)
+ {
+ retVal->reachabilityRef = reachability;
+ retVal->localWiFiRef = NO;
+ }
+ }
+ return retVal;
+}
+
++ (CDVReachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
+{
+ SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
+ CDVReachability* retVal = NULL;
+ if(reachability!= NULL)
+ {
+ retVal= [[[self alloc] init] autorelease];
+ if(retVal!= NULL)
+ {
+ retVal->reachabilityRef = reachability;
+ retVal->localWiFiRef = NO;
+ }
+ }
+ return retVal;
+}
+
++ (CDVReachability*) reachabilityForInternetConnection;
+{
+ struct sockaddr_in zeroAddress;
+ bzero(&zeroAddress, sizeof(zeroAddress));
+ zeroAddress.sin_len = sizeof(zeroAddress);
+ zeroAddress.sin_family = AF_INET;
+ return [self reachabilityWithAddress: &zeroAddress];
+}
+
++ (CDVReachability*) reachabilityForLocalWiFi;
+{
+ struct sockaddr_in localWifiAddress;
+ bzero(&localWifiAddress, sizeof(localWifiAddress));
+ localWifiAddress.sin_len = sizeof(localWifiAddress);
+ localWifiAddress.sin_family = AF_INET;
+ // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
+ localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
+ CDVReachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
+ if(retVal!= NULL)
+ {
+ retVal->localWiFiRef = YES;
+ }
+ return retVal;
+}
+
+#pragma mark Network Flag Handling
+
+- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
+{
+ CDVPrintReachabilityFlags(flags, "localWiFiStatusForFlags");
+
+ BOOL retVal = NotReachable;
+ if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
+ {
+ retVal = ReachableViaWiFi;
+ }
+ return retVal;
+}
+
+- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
+{
+ CDVPrintReachabilityFlags(flags, "networkStatusForFlags");
+ if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
+ {
+ // if target host is not reachable
+ return NotReachable;
+ }
+
+ BOOL retVal = NotReachable;
+
+ if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
+ {
+ // if target host is reachable and no connection is required
+ // then we'll assume (for now) that your on Wi-Fi
+ retVal = ReachableViaWiFi;
+ }
+
+
+ if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
+ (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
+ {
+ // ... and the connection is on-demand (or on-traffic) if the
+ // calling application is using the CFSocketStream or higher APIs
+
+ if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
+ {
+ // ... and no [user] intervention is needed
+ retVal = ReachableViaWiFi;
+ }
+ }
+
+ if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
+ {
+ // ... but WWAN connections are OK if the calling application
+ // is using the CFNetwork (CFSocketStream?) APIs.
+ retVal = ReachableViaWWAN;
+ }
+ return retVal;
+}
+
+- (BOOL) connectionRequired;
+{
+ NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
+ SCNetworkReachabilityFlags flags;
+ if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
+ }
+ return NO;
+}
+
+- (NetworkStatus) currentReachabilityStatus
+{
+ NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
+ NetworkStatus retVal = NotReachable;
+ SCNetworkReachabilityFlags flags;
+ if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ if(localWiFiRef)
+ {
+ retVal = [self localWiFiStatusForFlags: flags];
+ }
+ else
+ {
+ retVal = [self networkStatusForFlags: flags];
+ }
+ }
+ return retVal;
+}
+@end