Updated Branches:
  refs/heads/master 07ee5c792 -> fdf804341

Support JS->Native messages via an XHR & URL Protocol.

This also deprecates the need to manually register CDVURLProtocol. It is
now lazily registered by the CDVViewController.


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/fdf80434
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/tree/fdf80434
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/diff/fdf80434

Branch: refs/heads/master
Commit: fdf8043414e39914ffc29b682779a10fe1c147e7
Parents: 5a7b1ce
Author: Andrew Grieve <agri...@chromium.org>
Authored: Fri Aug 17 12:59:09 2012 -0400
Committer: Andrew Grieve <agri...@chromium.org>
Committed: Fri Aug 17 12:59:09 2012 -0400

----------------------------------------------------------------------
 CordovaLib/Classes/CDVURLProtocol.h                |   13 +++-
 CordovaLib/Classes/CDVURLProtocol.m                |   55 +++++++++++----
 CordovaLib/Classes/CDVViewController.h             |    2 +-
 CordovaLib/Classes/CDVViewController.m             |   17 ++---
 .../project/__TESTING__/Classes/AppDelegate.m      |    3 -
 5 files changed, 62 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/fdf80434/CordovaLib/Classes/CDVURLProtocol.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVURLProtocol.h 
b/CordovaLib/Classes/CDVURLProtocol.h
index a8b2fd5..ff4b77a 100644
--- a/CordovaLib/Classes/CDVURLProtocol.h
+++ b/CordovaLib/Classes/CDVURLProtocol.h
@@ -19,18 +19,27 @@
 
 #import <Foundation/Foundation.h>
 
+@class CDVViewController;
+
 @interface CDVURLProtocol : NSURLProtocol {
 }
 
 + (void) registerPGHttpURLProtocol 
 #ifdef __clang__
-    __attribute__ ((deprecated("Renamed - use registerUrlProtocol instead.")));
+    __attribute__ ((deprecated("No longer required.")));
 #else
     __attribute__ ((deprecated()));
 #endif
 
-+ (void) registerURLProtocol;
++ (void) registerURLProtocol
+#ifdef __clang__
+    __attribute__ ((deprecated("No longer required.")));
+#else
+    __attribute__ ((deprecated()));
+#endif
 
++ (void)registerViewController:(CDVViewController*)viewController;
++ (void)unregisterViewController:(CDVViewController*)viewController;
 @end
 
 @interface CDVHTTPURLResponse : NSHTTPURLResponse {

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/fdf80434/CordovaLib/Classes/CDVURLProtocol.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVURLProtocol.m 
b/CordovaLib/Classes/CDVURLProtocol.m
index 94b242a..42dbef7 100644
--- a/CordovaLib/Classes/CDVURLProtocol.m
+++ b/CordovaLib/Classes/CDVURLProtocol.m
@@ -22,37 +22,66 @@
 #import "CDVViewController.h"
 
 static CDVWhitelist* gWhitelist = nil;
+// Contains a set of NSNumbers of addresses of controllers. It doesn't store
+// the actual pointer to avoid retaining.
+static NSMutableSet* gRegisteredControllers = nil;
 
 @implementation CDVURLProtocol
 
 + (void) registerPGHttpURLProtocol {
-    return [[self class] registerURLProtocol];
 }
 
-// Called before any use of the protocol, ensure it is only called once
 + (void) registerURLProtocol {
-    static BOOL registered = NO;
-    if (!registered) {
+}
+
+// Called to register the URLProtocol, and to make it away of an instance of
+// a ViewController.
++ (void)registerViewController:(CDVViewController*)viewController {
+    if (gRegisteredControllers == nil) {
         [NSURLProtocol registerClass:[CDVURLProtocol class]];
-        registered = YES;
+        gRegisteredControllers = [[NSMutableSet alloc] initWithCapacity:8];
+        // The whitelist doesn't change, so grab the first one and store it.
+        gWhitelist = viewController.whitelist;
+    }
+    @synchronized (gRegisteredControllers) {
+        [gRegisteredControllers addObject:[NSNumber numberWithLongLong:(long 
long)viewController]];
     }
 }
 
++ (void)unregisterViewController:(CDVViewController*)viewController {
+    [gRegisteredControllers removeObject:viewController];
+}
+
+
 + (BOOL) canInitWithRequest:(NSURLRequest *)theRequest
 {
     NSURL* theUrl = [theRequest URL];
     NSString* theScheme = [theUrl scheme];
     
-    if (gWhitelist == nil) {
-        id<UIApplicationDelegate> delegate = [[UIApplication 
sharedApplication] delegate];
-        
-        if ([delegate respondsToSelector:@selector(viewController)]) {
-            id vc = [delegate performSelector:@selector(viewController)];
-            if ([vc isKindOfClass:[CDVViewController class]]) {
-                gWhitelist = ((CDVViewController*)vc).whitelist;
+    if ([[theUrl path] isEqualToString:@"/!gap_exec"]) {
+        NSString* viewControllerAddressStr = [theRequest 
valueForHTTPHeaderField:@"vc"];
+        if (viewControllerAddressStr == nil) {
+            NSLog(@"!cordova request missing vc header");
+            return NO;
+        }
+        long long viewControllerAddress = [viewControllerAddressStr 
longLongValue];
+        // Ensure that the CDVViewController has not been dealloc'ed.
+        @synchronized (gRegisteredControllers) {
+            if (![gRegisteredControllers containsObject:[NSNumber 
numberWithLongLong:viewControllerAddress]]) {
+                return NO;
+            }
+            CDVViewController* viewController = (__bridge 
CDVViewController*)(void *)viewControllerAddress;
+            
+            NSString* queuedCommandsJSON = [theRequest 
valueForHTTPHeaderField:@"cmds"];
+            if ([queuedCommandsJSON length] > 0) {
+                [viewController 
performSelectorOnMainThread:@selector(executeCommandsFromJson:) 
withObject:queuedCommandsJSON waitUntilDone:NO];
+            } else {
+                [viewController 
performSelectorOnMainThread:@selector(flushCommandQueue) withObject:nil 
waitUntilDone:NO];
             }
         }
-    }
+        return NO;
+       }
+    
     
     // we only care about http and https connections
        if ([gWhitelist schemeIsAllowed:theScheme])

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/fdf80434/CordovaLib/Classes/CDVViewController.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.h 
b/CordovaLib/Classes/CDVViewController.h
index abf7e89..23d703b 100644
--- a/CordovaLib/Classes/CDVViewController.h
+++ b/CordovaLib/Classes/CDVViewController.h
@@ -55,7 +55,7 @@
 - (void) createGapView;
 - (CDVCordovaView*) newCordovaViewWithFrame:(CGRect)bounds;
 
-- (int) executeQueuedCommands;
+- (int) executeCommandsFromJson:(NSString*)queuedCommandsJSON;
 - (void) flushCommandQueue;
 
 - (void) javascriptAlert:(NSString*)text;

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/fdf80434/CordovaLib/Classes/CDVViewController.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVViewController.m 
b/CordovaLib/Classes/CDVViewController.m
index 6add9af..f3b1d73 100644
--- a/CordovaLib/Classes/CDVViewController.m
+++ b/CordovaLib/Classes/CDVViewController.m
@@ -81,6 +81,7 @@
         [self printMultitaskingInfo];
         [self printDeprecationNotice];
         self.initialized = YES;
+        [CDVURLProtocol registerViewController:self];
     }
     
     return self; 
@@ -467,7 +468,7 @@
     [self didRotateFromInterfaceOrientation:(UIInterfaceOrientation)[[UIDevice 
currentDevice] orientation]];
     
     // Tell the webview that native is ready.
-    NSString* nativeReady = 
@"try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady
 = true;}";
+    NSString* nativeReady = [NSString 
stringWithFormat:@"cordova.iOSVCAddr='%lld';try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady
 = true;}", (long long)self];
     [theWebView stringByEvaluatingJavaScriptFromString:nativeReady];
 }
 
@@ -759,13 +760,8 @@ BOOL gSplashScreenShown = NO;
  *
  * Returns the number of executed commands.
  */
-- (int) executeQueuedCommands
+- (int) executeCommandsFromJson:(NSString*)queuedCommandsJSON
 {
-    // Grab all the queued commands from the JS side.
-    NSString* queuedCommandsJSON = [self.webView 
stringByEvaluatingJavaScriptFromString:
-                                                                       
@"cordova.require('cordova/plugin/ios/nativecomm')()"];
-       
-       
     // Parse the returned JSON array.
     NSArray* queuedCommands = [queuedCommandsJSON 
cdvjk_mutableObjectFromJSONString];
        
@@ -801,7 +797,10 @@ BOOL gSplashScreenShown = NO;
     // commands are executed as well.
     int numExecutedCommands = 0;
     do {
-        numExecutedCommands = [self executeQueuedCommands];
+        // Grab all the queued commands from the JS side.
+        NSString* queuedCommandsJSON = [self.webView 
stringByEvaluatingJavaScriptFromString:
+                                        
@"cordova.require('cordova/plugin/ios/nativecomm')()"];
+        numExecutedCommands = [self 
executeCommandsFromJson:queuedCommandsJSON];
     } while (numExecutedCommands != 0);
        
     [self.webView stringByEvaluatingJavaScriptFromString:
@@ -1007,12 +1006,12 @@ BOOL gSplashScreenShown = NO;
 
 - (void)dealloc 
 {
+    [CDVURLProtocol unregisterViewController:self];
     [[NSNotificationCenter defaultCenter] removeObserver:self 
name:UIApplicationWillTerminateNotification object:nil];
     [[NSNotificationCenter defaultCenter] removeObserver:self 
name:UIApplicationWillResignActiveNotification object:nil];
     [[NSNotificationCenter defaultCenter] removeObserver:self 
name:UIApplicationWillEnterForegroundNotification object:nil];
     [[NSNotificationCenter defaultCenter] removeObserver:self 
name:UIApplicationDidBecomeActiveNotification object:nil];
     [[NSNotificationCenter defaultCenter] removeObserver:self 
name:UIApplicationDidEnterBackgroundNotification object:nil];
-    
 }
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-cordova-ios/blob/fdf80434/bin/templates/project/__TESTING__/Classes/AppDelegate.m
----------------------------------------------------------------------
diff --git a/bin/templates/project/__TESTING__/Classes/AppDelegate.m 
b/bin/templates/project/__TESTING__/Classes/AppDelegate.m
index 86e2815..b6b14e8 100644
--- a/bin/templates/project/__TESTING__/Classes/AppDelegate.m
+++ b/bin/templates/project/__TESTING__/Classes/AppDelegate.m
@@ -29,7 +29,6 @@
 #import "MainViewController.h"
 
 #import <Cordova/CDVPlugin.h>
-#import <Cordova/CDVURLProtocol.h>
 
 
 @implementation AppDelegate
@@ -44,8 +43,6 @@
     NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage 
sharedHTTPCookieStorage]; 
     [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
         
-    [CDVURLProtocol registerURLProtocol];
-    
     self = [super init];
     return self;
 }

Reply via email to