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 2013/03/05 08:11:01 UTC

mac commit: [CB-2621] Initial implementation of cordova.exec bridge

Updated Branches:
  refs/heads/master bcb2f0824 -> 9aac186a9


[CB-2621] Initial implementation of cordova.exec bridge


Project: http://git-wip-us.apache.org/repos/asf/cordova-osx/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-osx/commit/9aac186a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-osx/tree/9aac186a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-osx/diff/9aac186a

Branch: refs/heads/master
Commit: 9aac186a9a21b85fd7bf240c301e5da1866d71ac
Parents: bcb2f08
Author: Shazron Abdullah <sh...@apache.org>
Authored: Mon Mar 4 23:10:54 2013 -0800
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Mon Mar 4 23:10:54 2013 -0800

----------------------------------------------------------------------
 CordovaMac/CordovaMac.xcodeproj/project.pbxproj  |   18 ++-
 CordovaMac/CordovaMac/CDVBridge.h                |   33 +++
 CordovaMac/CordovaMac/CDVBridge.m                |  175 +++++++++++++++++
 CordovaMac/CordovaMac/Commands/CDVNotification.m |    2 +-
 CordovaMac/CordovaMac/WebViewDelegate.h          |    2 +
 CordovaMac/CordovaMac/WebViewDelegate.m          |    4 +-
 CordovaMac/www/index.html                        |    3 +-
 7 files changed, 232 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac.xcodeproj/project.pbxproj b/CordovaMac/CordovaMac.xcodeproj/project.pbxproj
index 7243033..77a119f 100644
--- a/CordovaMac/CordovaMac.xcodeproj/project.pbxproj
+++ b/CordovaMac/CordovaMac.xcodeproj/project.pbxproj
@@ -10,6 +10,7 @@
 		30513C05154B6DED002B79B6 /* CDVNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 30513C02154B6DED002B79B6 /* CDVNotification.m */; };
 		30513C06154B6DED002B79B6 /* CDVSound.m in Sources */ = {isa = PBXBuildFile; fileRef = 30513C04154B6DED002B79B6 /* CDVSound.m */; };
 		30513C09154B6F56002B79B6 /* CDVConsole.m in Sources */ = {isa = PBXBuildFile; fileRef = 30513C08154B6F56002B79B6 /* CDVConsole.m */; };
+		30FC415116E5845A004E6F35 /* CDVBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 30FC415016E5845A004E6F35 /* CDVBridge.m */; };
 		488B21E7152F6242007056D6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 488B21E6152F6242007056D6 /* AppDelegate.m */; };
 		488B21EC152F742C007056D6 /* Cordova.icns in Resources */ = {isa = PBXBuildFile; fileRef = 488B21EB152F742C007056D6 /* Cordova.icns */; };
 		48B43519152E5E3500906A36 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48B43518152E5E3500906A36 /* Cocoa.framework */; };
@@ -31,6 +32,8 @@
 		30513C04154B6DED002B79B6 /* CDVSound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVSound.m; sourceTree = "<group>"; };
 		30513C07154B6F56002B79B6 /* CDVConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVConsole.h; sourceTree = "<group>"; };
 		30513C08154B6F56002B79B6 /* CDVConsole.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVConsole.m; sourceTree = "<group>"; };
+		30FC414F16E5845A004E6F35 /* CDVBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVBridge.h; sourceTree = "<group>"; };
+		30FC415016E5845A004E6F35 /* CDVBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVBridge.m; sourceTree = "<group>"; };
 		488B21E5152F6242007056D6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
 		488B21E6152F6242007056D6 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
 		488B21EB152F742C007056D6 /* Cordova.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Cordova.icns; path = ../Cordova.icns; sourceTree = "<group>"; };
@@ -124,6 +127,8 @@
 			isa = PBXGroup;
 			children = (
 				30513C00154B6DED002B79B6 /* Commands */,
+				30FC414F16E5845A004E6F35 /* CDVBridge.h */,
+				30FC415016E5845A004E6F35 /* CDVBridge.m */,
 				48B43542152E60A300906A36 /* Utils.h */,
 				48B43543152E60A300906A36 /* Utils.m */,
 				488B21E5152F6242007056D6 /* AppDelegate.h */,
@@ -179,7 +184,7 @@
 			isa = PBXProject;
 			attributes = {
 				CLASSPREFIX = CDV;
-				LastUpgradeCheck = 0430;
+				LastUpgradeCheck = 0460;
 				ORGANIZATIONNAME = OpenOSX.org;
 			};
 			buildConfigurationList = 48B4350E152E5E3500906A36 /* Build configuration list for PBXProject "CordovaMac" */;
@@ -227,6 +232,7 @@
 				30513C05154B6DED002B79B6 /* CDVNotification.m in Sources */,
 				30513C06154B6DED002B79B6 /* CDVSound.m in Sources */,
 				30513C09154B6F56002B79B6 /* CDVConsole.m in Sources */,
+				30FC415116E5845A004E6F35 /* CDVBridge.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -265,6 +271,10 @@
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
@@ -291,6 +301,10 @@
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -308,6 +322,7 @@
 		48B43533152E5E3600906A36 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "CordovaMac/CordovaMac-Prefix.pch";
 				INFOPLIST_FILE = "CordovaMac/CordovaMac-Info.plist";
@@ -319,6 +334,7 @@
 		48B43534152E5E3600906A36 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				COMBINE_HIDPI_IMAGES = YES;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "CordovaMac/CordovaMac-Prefix.pch";
 				INFOPLIST_FILE = "CordovaMac/CordovaMac-Info.plist";

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac/CDVBridge.h
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac/CDVBridge.h b/CordovaMac/CordovaMac/CDVBridge.h
new file mode 100644
index 0000000..cdca928
--- /dev/null
+++ b/CordovaMac/CordovaMac/CDVBridge.h
@@ -0,0 +1,33 @@
+/*
+ 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 <Cocoa/Cocoa.h>
+@class WebView;
+
+@interface CDVBridge : NSObject {
+	
+}
+
+@property (nonatomic, retain) WebView* webView;
+
+- (id) initWithWebView:(WebView*)webView;
+- (void) exec:(NSString*)callbackId withService:(NSString*)service andAction:(NSString*)action andArguments:(NSArray*)arguments;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac/CDVBridge.m
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac/CDVBridge.m b/CordovaMac/CordovaMac/CDVBridge.m
new file mode 100644
index 0000000..f9ac368
--- /dev/null
+++ b/CordovaMac/CordovaMac/CDVBridge.m
@@ -0,0 +1,175 @@
+/*
+ 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 "CDVBridge.h"
+#import <WebKit/WebKit.h>
+#import <AppKit/AppKit.h>
+#import <Foundation/NSJSONSerialization.h>
+
+@implementation CDVBridge
+
+- (BOOL) isArray:(id)item
+{
+    id win = [self.webView windowScriptObject];
+    NSNumber* result = [win callWebScriptMethod:@"__isArray__" withArguments:[NSArray arrayWithObject:item]];
+
+    return [result boolValue];
+}
+
+- (BOOL) isDictionary:(id)item
+{
+    id win = [self.webView windowScriptObject];
+    NSNumber* result = [win callWebScriptMethod:@"__isObject__" withArguments:[NSArray arrayWithObject:item]];
+    return [result boolValue];
+}
+
+- (NSDictionary*) convertWebScriptObjectToNSDictionary:(WebScriptObject*)webScriptObject
+{
+    // Assumption: webScriptObject has already been tested using isDictionary:
+
+    id win = [self.webView windowScriptObject];
+
+    WebScriptObject* keysObject = [win callWebScriptMethod:@"__dictionaryKeys__" withArguments:[NSArray arrayWithObject:webScriptObject]];
+    NSArray* keys = [self convertWebScriptObjectToNSArray:keysObject];
+    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:[keys count]];
+
+    NSEnumerator* enumerator = [keys objectEnumerator];
+    id key;
+    while (key = [enumerator nextObject]) {
+        [dict setObject:[webScriptObject valueForKey:key] forKey:key];
+    }
+    
+    return dict;
+}
+
+- (NSArray*) convertWebScriptObjectToNSArray:(WebScriptObject*)webScriptObject
+{
+    // Assumption: webScriptObject has already been tested using isArray:
+    
+    NSUInteger count = [[webScriptObject valueForKey:@"length"] integerValue];
+    NSMutableArray *a = [NSMutableArray array];
+    for (unsigned i = 0; i < count; i++) {
+        id item = [webScriptObject webScriptValueAtIndex:i];
+        if ([item isKindOfClass:[WebScriptObject class]]) {
+            if ([self isArray:item]) {
+                [a addObject:[self convertWebScriptObjectToNSArray:item]];
+            } else if ([self isDictionary:item]) {
+                [a addObject:[self convertWebScriptObjectToNSDictionary:item]];
+            };
+        } else {
+            [a addObject:item];
+        }
+    }
+    
+    return a;
+}
+
+- (void) registerJavaScriptHelpers
+{
+    NSString* isArray = [NSString stringWithFormat:@"function __isArray__(obj) { return obj.constructor == Array; };"];
+    NSString* isObject = [NSString stringWithFormat:@"function __isObject__(obj) { return obj.constructor == Object; };"];
+    NSString* dictionaryKeys = [NSString stringWithFormat:
+                                @" \
+                                function __dictionaryKeys__(obj) { \
+                                    var a = []; \
+                                    for (var key in obj) { \
+                                        if (!obj.hasOwnProperty(key)) { \
+                                            continue; \
+                                        } \
+                                        a.push(key); \
+                                    } \
+                                    return a; \
+                                }"
+                                ];
+    
+    id win = [self.webView windowScriptObject];
+    [win evaluateWebScript:isArray];
+    [win evaluateWebScript:isObject];
+    [win evaluateWebScript:dictionaryKeys];
+}
+
+- (id) initWithWebView:(WebView *)webView
+{
+    if ((self = [super init]) != nil) {
+        self.webView = webView;
+        [self registerJavaScriptHelpers];
+    }
+    
+    return self;
+}
+
+- (void) exec:(NSString*)callbackId withService:(NSString*)service andAction:(NSString*)action andArguments:(WebScriptObject*)webScriptObject
+{
+    // We are going with the iOS method of passing in a callbackId.
+    // Note that we can use the JavaScriptCore C API to pass in the JavaScript function references
+    // and context and call them directly, but this is done this way for possible plugin sharing
+    // between iOS and OS X. Also we are going async as well.
+    
+    // we're just going to assume the webScriptObject passed in is an NSArray
+    NSArray* arguments = [self convertWebScriptObjectToNSArray:webScriptObject];
+#pragma unused(arguments)
+    
+	NSLog(@"TODO: flesh out exec to dispatch the commands, possibly re-use iOS code");
+}
+
+#pragma mark WebScripting Protocol
+
+/* checks whether a selector is acceptable to be called from JavaScript */
++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
+{
+	BOOL	result = YES;
+	
+	int			i = 0;
+	static SEL	* acceptableList = NULL;
+	SEL			currentSelector;
+	
+	if (acceptableList == NULL && (acceptableList = calloc(256, sizeof(SEL))))	// up to 256 selectors
+	{
+		acceptableList[i++] = @selector(exec:withService:andAction:andArguments:);
+	}
+	
+	i = 0;
+	while (result == YES && (currentSelector = acceptableList[i++]))
+	{
+		//checking for exclusions
+		result = !(selector == currentSelector);
+	}
+	
+	return result;
+}
+
+/* helper function so we don't have to have underscores and stuff in js to refer to the right method */
++ (NSString*) webScriptNameForSelector:(SEL)aSelector
+{
+	id	result = nil;
+	
+	if (aSelector == @selector(exec:withService:andAction:andArguments:)) {
+		result = @"exec";
+	}
+	
+	return result;
+}
+
+// right now exclude all properties (eg keys)
++ (BOOL) isKeyExcludedFromWebScript:(const char*)name
+{
+	return YES;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac/Commands/CDVNotification.m
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac/Commands/CDVNotification.m b/CordovaMac/CordovaMac/Commands/CDVNotification.m
index e52aeed..1830a13 100644
--- a/CordovaMac/CordovaMac/Commands/CDVNotification.m
+++ b/CordovaMac/CordovaMac/Commands/CDVNotification.m
@@ -27,7 +27,7 @@
 {
     NSAlert* alert = [NSAlert alertWithMessageText:title
                                      defaultButton:@"OK" alternateButton:nil
-                                       otherButton:nil informativeTextWithFormat:message];
+                                       otherButton:nil informativeTextWithFormat:@"%@", message];
     [alert runModal];
 }
 

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac/WebViewDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac/WebViewDelegate.h b/CordovaMac/CordovaMac/WebViewDelegate.h
index a7c5899..c99d305 100644
--- a/CordovaMac/CordovaMac/WebViewDelegate.h
+++ b/CordovaMac/CordovaMac/WebViewDelegate.h
@@ -23,6 +23,7 @@
 @class CDVSound;
 @class CDVNotification;
 @class CDVConsole;
+@class CDVBridge;
 
 @interface WebViewDelegate : NSObject {
 }
@@ -30,5 +31,6 @@
 @property (nonatomic, retain) CDVSound* sound;
 @property (nonatomic, retain) CDVNotification* notification;
 @property (nonatomic, retain) CDVConsole* console;
+@property (nonatomic, retain) CDVBridge* bridge;
 
 @end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/CordovaMac/WebViewDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaMac/CordovaMac/WebViewDelegate.m b/CordovaMac/CordovaMac/WebViewDelegate.m
index a04cdfd..6bf5434 100644
--- a/CordovaMac/CordovaMac/WebViewDelegate.m
+++ b/CordovaMac/CordovaMac/WebViewDelegate.m
@@ -22,6 +22,7 @@
 #import "CDVSound.h"
 #import "CDVNotification.h"
 #import "CDVConsole.h"
+#import "CDVBridge.h"
 
 @implementation WebViewDelegate
 
@@ -36,7 +37,8 @@
 	if (self.notification == nil) { self.notification = [CDVNotification new]; }
 	[windowScriptObject setValue:self.notification forKey:@"notification"];
     [windowScriptObject evaluateWebScript:@"navigator.notification = notification;"];
-    
+	if (self.bridge == nil) { self.bridge = [[CDVBridge alloc] initWithWebView:webView]; }
+    [windowScriptObject setValue:self.bridge forKey:@"cordovabridge"];
 }
 
 /* This logs all errors from Javascript, nifty */

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/9aac186a/CordovaMac/www/index.html
----------------------------------------------------------------------
diff --git a/CordovaMac/www/index.html b/CordovaMac/www/index.html
index e7f62f2..24047bd 100644
--- a/CordovaMac/www/index.html
+++ b/CordovaMac/www/index.html
@@ -61,8 +61,7 @@ Licensed to the Apache Software Foundation (ASF) under one
         
         console.log("Cordova is working!");
         navigator.notification.alert("Cordova is working!", "Apache Cordova");
-        
-        
+        cordovabridge.exec('INVALID', 'TestService', 'TestAction', [ 1, 'two', { 3 : 'three', 'four': 4 }]);
 	}
         
     function onDeviceReady()