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/07/30 21:58:36 UTC
[2/15] ios commit: Change wire format of exec handler.
Change wire format of exec handler.
The JS now sends commands as a JSON array instead of pre-processed JSON
object. The code maintains compatibility with old-style plugins by
performing the "options" dict extraction on the native side when the
plugin responds to method:withDict: selector. The new way of
implementing native callbacks is to us a method called method:, which is
passed the CDVInvokedUrlCommand.
Update CDVFileTransfer to use the new API.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/commit/8300635b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/8300635b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/8300635b
Branch: refs/heads/master
Commit: 8300635be8976dd04d7bb6a864baf15d2ecd487d
Parents: 07abacf
Author: Andrew Grieve <ag...@chromium.org>
Authored: Fri Jul 27 13:34:49 2012 -0400
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Mon Jul 30 12:52:38 2012 -0700
----------------------------------------------------------------------
CordovaLib/Classes/CDVFileTransfer.h | 6 +-
CordovaLib/Classes/CDVFileTransfer.m | 55 ++++++-------
CordovaLib/Classes/CDVInvokedUrlCommand.h | 31 +++++--
CordovaLib/Classes/CDVInvokedUrlCommand.m | 70 ++++++++++++----
CordovaLib/Classes/CDVViewController.m | 36 +++++---
CordovaLib/CordovaLibTests/CDVFileTransferTests.m | 22 ++++--
6 files changed, 143 insertions(+), 77 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/Classes/CDVFileTransfer.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFileTransfer.h b/CordovaLib/Classes/CDVFileTransfer.h
index 54a37b3..3adbf37 100644
--- a/CordovaLib/Classes/CDVFileTransfer.h
+++ b/CordovaLib/Classes/CDVFileTransfer.h
@@ -41,12 +41,12 @@ extern NSString* const kOptionsKeyCookie;
}
-- (void) upload:(NSArray*)arguments withDict:(NSDictionary*)options;
-- (void) download:(NSArray*)arguments withDict:(NSDictionary*)options;
+- (void) upload:(CDVInvokedUrlCommand*)command;
+- (void) download:(CDVInvokedUrlCommand*)command;
- (NSString*) escapePathComponentForUrlString:(NSString*)urlString;
// Visible for testing.
-- (NSURLRequest*) requestForUpload:(NSArray*)arguments withDict:(NSDictionary*)options fileData:(NSData*)fileData;
+- (NSURLRequest*) requestForUploadCommand:(CDVInvokedUrlCommand*)command fileData:(NSData*)fileData;
-(NSMutableDictionary*) createFileTransferError:(int)code AndSource:(NSString*)source AndTarget:(NSString*)target;
-(NSMutableDictionary*) createFileTransferError:(int)code
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/Classes/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVFileTransfer.m b/CordovaLib/Classes/CDVFileTransfer.m
index 147be32..e831537 100644
--- a/CordovaLib/Classes/CDVFileTransfer.m
+++ b/CordovaLib/Classes/CDVFileTransfer.m
@@ -23,9 +23,9 @@
@interface CDVFileTransfer ()
// Creates a delegate to handle an upload.
-- (CDVFileTransferDelegate*)delegateForUpload:(NSArray*)arguments;
+- (CDVFileTransferDelegate*)delegateForUploadCommand:(CDVInvokedUrlCommand*)command;
// Creates an NSData* for the file for the given upload arguments.
-- (NSData*)fileDataForUploadArguments:(NSArray*)arguments;
+- (NSData*)fileDataForUploadCommand:(CDVInvokedUrlCommand*)command;
@end
// Buffer size to use for streaming uploads.
@@ -74,18 +74,17 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
return [schemeAndHost stringByAppendingString:pathComponent];
}
-- (NSURLRequest*) requestForUpload:(NSArray*)arguments withDict:(NSDictionary*)options fileData:(NSData*)fileData {
- NSString* callbackId = [arguments objectAtIndex:0];
-
+- (NSURLRequest*) requestForUploadCommand:(CDVInvokedUrlCommand *)command fileData:(NSData *)fileData {
// arguments order from js: [filePath, server, fileKey, fileName, mimeType, params, debug, chunkedMode]
// however, params is a JavaScript object and during marshalling is put into the options dict,
// thus debug and chunkedMode are the 6th and 7th arguments
-
- NSString* target = (NSString*)[arguments objectAtIndex:1];
- NSString* server = (NSString*)[arguments objectAtIndex:2];
- NSString* fileKey = (NSString*)[arguments objectAtIndex:3];
- NSString* fileName = [arguments objectAtIndex:4 withDefault:@"no-filename"];
- NSString* mimeType = [arguments objectAtIndex:5 withDefault:nil];
+ NSArray* arguments = command.arguments;
+ NSString* target = (NSString*)[arguments objectAtIndex:0];
+ NSString* server = (NSString*)[arguments objectAtIndex:1];
+ NSString* fileKey = (NSString*)[arguments objectAtIndex:2];
+ NSString* fileName = [arguments objectAtIndex:3 withDefault:@"no-filename"];
+ NSString* mimeType = [arguments objectAtIndex:4 withDefault:nil];
+ NSDictionary* options = [arguments objectAtIndex:5 withDefault:nil];
// NSString* trustAllHosts = (NSString*)[arguments objectAtIndex:6]; // allow self-signed certs
BOOL chunkedMode = [[arguments objectAtIndex:7 withDefault:[NSNumber numberWithBool:YES]] boolValue];
@@ -113,7 +112,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
if(errorCode > 0) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: [self createFileTransferError:errorCode AndSource:target AndTarget:server]];
- [self writeJavascript:[result toErrorCallbackString:callbackId]];
+ [self writeJavascript:[result toErrorCallbackString:command.callbackId]];
return nil;
}
@@ -228,22 +227,21 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
return req;
}
-- (CDVFileTransferDelegate*) delegateForUpload:(NSArray*)arguments {
- NSString* callbackId = [arguments objectAtIndex:0];
- NSString* target = (NSString*)[arguments objectAtIndex:1];
- NSString* server = (NSString*)[arguments objectAtIndex:2];
+- (CDVFileTransferDelegate*) delegateForUploadCommand:(CDVInvokedUrlCommand *)command {
+ NSString* target = [command.arguments objectAtIndex:0];
+ NSString* server = [command.arguments objectAtIndex:1];
CDVFileTransferDelegate* delegate = [[[CDVFileTransferDelegate alloc] init] autorelease];
delegate.command = self;
delegate.direction = CDV_TRANSFER_UPLOAD;
- delegate.callbackId = callbackId;
+ delegate.callbackId = command.callbackId;
delegate.source = server;
delegate.target = target;
return delegate;
}
-- (NSData*) fileDataForUploadArguments:(NSArray*)arguments {
- NSString* target = (NSString*)[arguments objectAtIndex:1];
+- (NSData*) fileDataForUploadCommand:(CDVInvokedUrlCommand*)command {
+ NSString* target = (NSString*)[command.arguments objectAtIndex:0];
NSError *err = nil;
// Extract the path part out of a file: URL.
NSString* filePath = [target hasPrefix:@"/"] ? [[target copy] autorelease] : [[NSURL URLWithString:target] path];
@@ -256,19 +254,18 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
return fileData;
}
-- (void) upload:(NSArray*)arguments withDict:(NSDictionary*)options {
+- (void) upload:(CDVInvokedUrlCommand*)command {
// fileData and req are split into helper functions to ease the unit testing of delegateForUpload.
- NSData* fileData = [self fileDataForUploadArguments:arguments];
- NSURLRequest* req = [self requestForUpload:arguments withDict:options fileData:fileData];
- CDVFileTransferDelegate* delegate = [self delegateForUpload:arguments];
+ NSData* fileData = [self fileDataForUploadCommand:command];
+ NSURLRequest* req = [self requestForUploadCommand:command fileData:fileData];
+ CDVFileTransferDelegate* delegate = [self delegateForUploadCommand:command];
[NSURLConnection connectionWithRequest:req delegate:delegate];
}
-- (void) download:(NSArray*)arguments withDict:(NSDictionary*)options {
+- (void) download:(CDVInvokedUrlCommand*)command {
DLog(@"File Transfer downloading file...");
- NSString * callbackId = [arguments objectAtIndex:0];
- NSString * sourceUrl = [arguments objectAtIndex:1];
- NSString * filePath = [arguments objectAtIndex:2];
+ NSString * sourceUrl = [command.arguments objectAtIndex:0];
+ NSString * filePath = [command.arguments objectAtIndex:1];
CDVPluginResult *result = nil;
CDVFileTransferError errorCode = 0;
@@ -293,7 +290,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
if(errorCode > 0) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: [self createFileTransferError:errorCode AndSource:sourceUrl AndTarget:filePath]];
- [self writeJavascript:[result toErrorCallbackString:callbackId]];
+ [self writeJavascript:[result toErrorCallbackString:command.callbackId]];
return;
}
@@ -302,7 +299,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream) {
CDVFileTransferDelegate* delegate = [[[CDVFileTransferDelegate alloc] init] autorelease];
delegate.command = self;
delegate.direction = CDV_TRANSFER_DOWNLOAD;
- delegate.callbackId = callbackId;
+ delegate.callbackId = command.callbackId;
delegate.source = sourceUrl;
delegate.target = filePath;
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/Classes/CDVInvokedUrlCommand.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInvokedUrlCommand.h b/CordovaLib/Classes/CDVInvokedUrlCommand.h
index b7beb7d..ff7f1ff 100644
--- a/CordovaLib/Classes/CDVInvokedUrlCommand.h
+++ b/CordovaLib/Classes/CDVInvokedUrlCommand.h
@@ -21,19 +21,30 @@
@interface CDVInvokedUrlCommand : NSObject {
- NSString* className;
- NSString* methodName;
- NSMutableArray* arguments;
- NSMutableDictionary* options;
+ NSString* _callbackId;
+ NSString* _className;
+ NSString* _methodName;
+ NSArray* _arguments;
}
-@property(retain) NSMutableArray* arguments;
-@property(retain) NSMutableDictionary* options;
-@property(copy) NSString* className;
-@property(copy) NSString* methodName;
+@property(nonatomic, readonly) NSArray* arguments;
+@property(nonatomic, readonly) NSString* callbackId;
+@property(nonatomic, readonly) NSString* className;
+@property(nonatomic, readonly) NSString* methodName;
-+ (CDVInvokedUrlCommand*) commandFromObject:(NSDictionary*)object;
++ (CDVInvokedUrlCommand*) commandFromJson:(NSArray*)jsonEntry;
+
+- (id) initWithArguments:(NSArray*)arguments
+ callbackId:(NSString*)callbackId
+ className:(NSString*)className
+ methodName:(NSString*)methodName;
+
+- (id) initFromJson:(NSArray*)jsonEntry;
+
+// The first NSDictionary found in the arguments will be returned in legacyDict.
+// The arguments array with be prepended with the callbackId and have the first
+// dict removed from it.
+- (void) legacyArguments:(NSMutableArray**)legacyArguments andDict:(NSMutableDictionary**)legacyDict;
-- (void) dealloc;
@end
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/Classes/CDVInvokedUrlCommand.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVInvokedUrlCommand.m b/CordovaLib/Classes/CDVInvokedUrlCommand.m
index 45b0a1d..677e5af 100644
--- a/CordovaLib/Classes/CDVInvokedUrlCommand.m
+++ b/CordovaLib/Classes/CDVInvokedUrlCommand.m
@@ -22,28 +22,68 @@
@implementation CDVInvokedUrlCommand
-@synthesize arguments;
-@synthesize options;
-@synthesize className;
-@synthesize methodName;
+@synthesize arguments = _arguments;
+@synthesize callbackId = _callbackId;
+@synthesize className = _className;
+@synthesize methodName = _methodName;
-+ (CDVInvokedUrlCommand*) commandFromObject:(NSDictionary*)object
++ (CDVInvokedUrlCommand*) commandFromJson:(NSArray*)jsonEntry
{
- 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 [[[CDVInvokedUrlCommand alloc] initFromJson:jsonEntry] autorelease];
+}
+
+- (id) initFromJson:(NSArray*)jsonEntry
+{
+ NSString* callbackId = [jsonEntry objectAtIndex:0];
+ NSString* className = [jsonEntry objectAtIndex:1];
+ NSString* methodName = [jsonEntry objectAtIndex:2];
+ NSMutableArray* arguments = [jsonEntry objectAtIndex:3];
+
+ return [self initWithArguments:arguments
+ callbackId:callbackId
+ className:className
+ methodName:methodName];
+}
- return iuc;
+- (id) initWithArguments:(NSArray*)arguments
+ callbackId:(NSString*)callbackId
+ className:(NSString*)className
+ methodName:(NSString*)methodName
+{
+ self = [super init];
+ if (self != nil) {
+ _arguments = [arguments retain];
+ _callbackId = [callbackId retain];
+ _className = [className retain];
+ _methodName = [methodName retain];
+ }
+ return self;
+}
+
+- (void) legacyArguments:(NSMutableArray**)legacyArguments andDict:(NSMutableDictionary**)legacyDict {
+ NSMutableArray* newArguments = [NSMutableArray arrayWithArray:_arguments];
+ for (NSUInteger i = 0; i < [newArguments count]; ++i) {
+ if ([[newArguments objectAtIndex:i] isKindOfClass:[NSDictionary class]]) {
+ if (legacyDict != NULL) {
+ *legacyDict = [newArguments objectAtIndex:i];
+ }
+ [newArguments removeObjectAtIndex:i];
+ break;
+ }
+ }
+ [newArguments insertObject:_callbackId atIndex:0];
+ if (legacyArguments != NULL) {
+ *legacyArguments = newArguments;
+ }
}
+
- (void) dealloc
{
- [arguments release];
- [options release];
- [className release];
- [methodName release];
+ [_arguments release];
+ [_callbackId release];
+ [_className release];
+ [_methodName release];
[super dealloc];
}
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m b/CordovaLib/Classes/CDVViewController.m
index bd99ecc..63b2de0 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -767,21 +767,21 @@ BOOL gSplashScreenShown = NO;
// Parse the returned JSON array.
- NSArray* queuedCommands =
- [queuedCommandsJSON cdvjk_objectFromJSONString];
+ NSArray* queuedCommands = [queuedCommandsJSON cdvjk_mutableObjectFromJSONString];
// Iterate over and execute all of the commands.
- for (NSString* commandJson in queuedCommands) {
-
- if(![self.commandDelegate execute:
- [CDVInvokedUrlCommand commandFromObject:
- [commandJson cdvjk_mutableObjectFromJSONString]]])
- {
+ for (NSArray* jsonEntry in queuedCommands) {
+ CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry];
+ if(![self.commandDelegate execute:command]) {
+#ifdef DEBUG
+ NSString* commandJson = [jsonEntry cdvjk_JSONString];
static NSUInteger maxLogLength = 1024;
NSString* commandString = ([commandJson length] > maxLogLength) ?
[NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] :
commandJson;
+
DLog(@"FAILED pluginJSON = %@", commandString);
+#endif
}
}
@@ -824,16 +824,24 @@ BOOL gSplashScreenShown = NO;
}
BOOL retVal = YES;
- // construct the fill method name to ammend the second argument.
- NSString* fullMethodName = [[NSString alloc] initWithFormat:@"%@:withDict:", command.methodName];
- if ([obj respondsToSelector:NSSelectorFromString(fullMethodName)]) {
- [obj performSelector:NSSelectorFromString(fullMethodName) withObject:command.arguments withObject:command.options];
+ // Find the proper selector to call.
+ NSString* methodName = [NSString stringWithFormat:@"%@:", command.methodName];
+ NSString* methodNameWithDict = [NSString stringWithFormat:@"%@:withDict:", command.methodName];
+ SEL normalSelector = NSSelectorFromString(methodName);
+ SEL legacySelector = NSSelectorFromString(methodNameWithDict);
+ // Test for the legacy selector first in case they both exist.
+ if ([obj respondsToSelector:legacySelector]) {
+ NSMutableArray* arguments = nil;
+ NSMutableDictionary* dict = nil;
+ [command legacyArguments:&arguments andDict:&dict];
+ [obj performSelector:legacySelector withObject:arguments withObject:dict];
+ } else if ([obj respondsToSelector:normalSelector]) {
+ [obj performSelector:normalSelector withObject:command];
} else {
// There's no method to call, so throw an error.
- NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", fullMethodName, command.className);
+ NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", methodName, command.className);
retVal = NO;
}
- [fullMethodName release];
return retVal;
}
http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/8300635b/CordovaLib/CordovaLibTests/CDVFileTransferTests.m
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLibTests/CDVFileTransferTests.m b/CordovaLib/CordovaLibTests/CDVFileTransferTests.m
index 6e2fcf7..6c2b929 100644
--- a/CordovaLib/CordovaLibTests/CDVFileTransferTests.m
+++ b/CordovaLib/CordovaLibTests/CDVFileTransferTests.m
@@ -60,8 +60,9 @@ static NSData* readStream(NSInputStream* stream) {
- (void)setUp
{
[super setUp];
+
_arguments = [[NSMutableArray alloc] initWithObjects:
- kDummyArgCallbackId, kDummyArgTarget, kDummyArgServer, kDummyArgFileKey,
+ kDummyArgTarget, kDummyArgServer, kDummyArgFileKey, [NSNull null],
[NSNull null], [NSNull null], [NSNull null], [NSNull null], nil];
_dummyFileData = [[kDummyFileContents dataUsingEncoding:NSUTF8StringEncoding] retain];
_fileTransfer = [[CDVFileTransfer alloc] init];
@@ -79,19 +80,27 @@ static NSData* readStream(NSInputStream* stream) {
}
- (void)setFilePathArg:(NSString*)filePath {
- [_arguments replaceObjectAtIndex:1 withObject:filePath];
+ [_arguments replaceObjectAtIndex:0 withObject:filePath];
}
- (void)setServerUrlArg:(NSString*)serverUrl {
- [_arguments replaceObjectAtIndex:2 withObject:serverUrl];
+ [_arguments replaceObjectAtIndex:1 withObject:serverUrl];
}
- (void)setChunkedModeArg:(BOOL)chunk {
[_arguments replaceObjectAtIndex:7 withObject:[NSNumber numberWithBool:chunk]];
}
+- (void)setParams:(NSDictionary*)params {
+ [_arguments replaceObjectAtIndex:5 withObject:params];
+}
+
- (NSURLRequest*)requestForUpload {
- return [_fileTransfer requestForUpload:_arguments withDict:nil fileData:_dummyFileData];
+ CDVInvokedUrlCommand* command = [[[CDVInvokedUrlCommand alloc] initWithArguments:_arguments
+ callbackId:kDummyArgCallbackId
+ className:@"FileTransfer"
+ methodName:@"upload"] autorelease];
+ return [_fileTransfer requestForUploadCommand:command fileData:_dummyFileData];
}
- (void)checkUploadRequest:(NSURLRequest*)request chunked:(BOOL)chunked {
@@ -166,9 +175,10 @@ static NSData* readStream(NSInputStream* stream) {
[self setChunkedModeArg:NO];
NSDictionary* headers = [NSDictionary dictionaryWithObjectsAndKeys:@"val1", @"key1",
@"val2", @"key2", nil];
- NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@"cookieval", kOptionsKeyCookie,
+ NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:@"cookieval", kOptionsKeyCookie,
headers, @"headers", @"val3", @"key3", nil];
- NSURLRequest* request = [_fileTransfer requestForUpload:_arguments withDict:options fileData:_dummyFileData];
+ [self setParams:params];
+ NSURLRequest* request = [self requestForUpload];
NSString* payload = [[[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding] autorelease];
// Check that headers are properly set.
STAssertTrue([@"val1" isEqualToString:[request valueForHTTPHeaderField:@"key1"]], nil);