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 2015/09/01 01:35:14 UTC

[6/6] mac commit: CB-9581 OSX WebView does not send cookies is safari cache is cleared (closes #21, closes #22)

CB-9581 OSX WebView does not send cookies is safari cache is cleared (closes #21, closes #22)


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

Branch: refs/heads/master
Commit: 90843d7cdc157e45718318f0be592838eee9eb24
Parents: 3fad357
Author: Tobias Bocanegra <tr...@adobe.com>
Authored: Mon Aug 31 23:02:07 2015 +0100
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Mon Aug 31 16:38:05 2015 -0700

----------------------------------------------------------------------
 CordovaLib/CordovaLib.xcodeproj/project.pbxproj |  10 +
 .../CordovaLib/Classes/CDVWebViewDelegate.m     |  55 +++++-
 CordovaLib/CordovaLib/Classes/CookieJar.h       |  38 ++++
 CordovaLib/CordovaLib/Classes/CookieJar.m       | 197 +++++++++++++++++++
 .../CordovaLib/Classes/Localizable.strings      |   7 +
 5 files changed, 298 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/90843d7c/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 78f2e1f..c6a5705 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -49,8 +49,10 @@
 		CC6A01B9AD6ECF2D913FF418 /* CDVWindowSizeCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A03B1971BACCB9183AEFE /* CDVWindowSizeCommand.h */; };
 		CC6A03130738A1F299369195 /* CDVCursorMonitorService.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A07666A2CE3AE46F85AD6 /* CDVCursorMonitorService.m */; };
 		CC6A051516599A029D1ECA50 /* CDVMainWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A0F82EDAFA619D95D3392 /* CDVMainWindow.m */; };
+		CC6A0567D3BA91121C2D643C /* CookieJar.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A01435C5B9099EA0BF004 /* CookieJar.m */; };
 		CC6A060DFE3B49803140B568 /* CDVCursorMonitorService.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A08BE679E9B2A17CB995E /* CDVCursorMonitorService.h */; };
 		CC6A061F0987401A5AB7FE69 /* NSScreen+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A00E23A9BC2910E28D36E /* NSScreen+Utils.h */; };
+		CC6A07272E088962F187CA76 /* CookieJar.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A0412F2FA8BB2F08FEF21 /* CookieJar.h */; };
 		CC6A07EE3FA39E9ED21FC2AD /* CDVWindowSizeCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A0DB9905DAB3A94C6BCC8 /* CDVWindowSizeCommand.m */; };
 		CC6A0C2EAD9E57810677CE21 /* NSScreen+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A01EC9D87C6FC66791911 /* NSScreen+Utils.m */; };
 		CC6A0EC955BC7E3B3BF31EA3 /* CDVMainWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A04379104F7E27DB88C08 /* CDVMainWindow.h */; };
@@ -105,8 +107,11 @@
 		70DAA9241908E82600AF3749 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
 		70E382C81909BBFF0029A2F0 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
 		CC6A00E23A9BC2910E28D36E /* NSScreen+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSScreen+Utils.h"; sourceTree = "<group>"; };
+		CC6A01435C5B9099EA0BF004 /* CookieJar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CookieJar.m; sourceTree = "<group>"; };
 		CC6A01EC9D87C6FC66791911 /* NSScreen+Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSScreen+Utils.m"; sourceTree = "<group>"; };
 		CC6A03B1971BACCB9183AEFE /* CDVWindowSizeCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVWindowSizeCommand.h; sourceTree = "<group>"; };
+		CC6A0412F2FA8BB2F08FEF21 /* CookieJar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CookieJar.h; sourceTree = "<group>"; };
+		CC6A04147D67DAA53ABBFD7C /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = "<group>"; };
 		CC6A04379104F7E27DB88C08 /* CDVMainWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVMainWindow.h; sourceTree = "<group>"; };
 		CC6A07666A2CE3AE46F85AD6 /* CDVCursorMonitorService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCursorMonitorService.m; sourceTree = "<group>"; };
 		CC6A08BE679E9B2A17CB995E /* CDVCursorMonitorService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCursorMonitorService.h; sourceTree = "<group>"; };
@@ -195,6 +200,9 @@
 				70BD679018FFA12D00A1EFCF /* Utils */,
 				CC6A04379104F7E27DB88C08 /* CDVMainWindow.h */,
 				CC6A0F82EDAFA619D95D3392 /* CDVMainWindow.m */,
+				CC6A01435C5B9099EA0BF004 /* CookieJar.m */,
+				CC6A0412F2FA8BB2F08FEF21 /* CookieJar.h */,
+				CC6A04147D67DAA53ABBFD7C /* Localizable.strings */,
 			);
 			path = Classes;
 			sourceTree = "<group>";
@@ -283,6 +291,7 @@
 				CC6A061F0987401A5AB7FE69 /* NSScreen+Utils.h in Headers */,
 				CC6A060DFE3B49803140B568 /* CDVCursorMonitorService.h in Headers */,
 				CC6A0EC955BC7E3B3BF31EA3 /* CDVMainWindow.h in Headers */,
+				CC6A07272E088962F187CA76 /* CookieJar.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -359,6 +368,7 @@
 				CC6A0C2EAD9E57810677CE21 /* NSScreen+Utils.m in Sources */,
 				CC6A03130738A1F299369195 /* CDVCursorMonitorService.m in Sources */,
 				CC6A051516599A029D1ECA50 /* CDVMainWindow.m in Sources */,
+				CC6A0567D3BA91121C2D643C /* CookieJar.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/90843d7c/CordovaLib/CordovaLib/Classes/CDVWebViewDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib/Classes/CDVWebViewDelegate.m b/CordovaLib/CordovaLib/Classes/CDVWebViewDelegate.m
index 05afc47..85cef5a 100644
--- a/CordovaLib/CordovaLib/Classes/CDVWebViewDelegate.m
+++ b/CordovaLib/CordovaLib/Classes/CDVWebViewDelegate.m
@@ -21,11 +21,22 @@
 #import "CDVWebViewDelegate.h"
 #import "CDVConsole.h"
 #import "CDVBridge.h"
+#import "CookieJar.h"
 
 @implementation CDVWebViewDelegate
 
+CookieJar *_cookies;
+
 @synthesize console;
 
+- (instancetype) init {
+    self = [super init];
+    if (self) {
+        _cookies = [[CookieJar alloc] init];
+    }
+    return self;
+}
+
 - (void) webView:(WebView*) webView didClearWindowObject:(WebScriptObject*) windowScriptObject forFrame:(WebFrame*) frame {
     if (self.console == nil) {
         self.console = [CDVConsole new];
@@ -38,12 +49,6 @@
     [windowScriptObject setValue:self.bridge forKey:@"cordovabridge"];
 }
 
-- (void) webView:(WebView*) sender didFinishLoadForFrame:(WebFrame*) frame {
-    id win = [sender windowScriptObject];
-    NSString* nativeReady = @"try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady = true;}";
-    [win evaluateWebScript:nativeReady];
-}
-
 - (void) webView:(WebView*) webView addMessageToConsole:(NSDictionary*) message {
     if (![message isKindOfClass:[NSDictionary class]]) {
         return;
@@ -54,6 +59,7 @@
             message[@"message"]);
 }
 
+
 #pragma mark WebScripting protocol
 
 /* checks whether a selector is acceptable to be called from JavaScript */
@@ -71,12 +77,10 @@
 - (void) webView:(WebView*) sender decidePolicyForNavigationAction:(NSDictionary*) actionInformation request:(NSURLRequest*) request frame:(WebFrame*) frame decisionListener:(id <WebPolicyDecisionListener>) listener {
     NSString* url = [[request URL] description];
     NSLog(@"navigating to %@", url);
-
     [listener use];
 }
 
-
-#pragma mark WebUIDelegate
+#pragma mark WebViewDelegate
 
 - (BOOL) webView:(WebView*) sender runBeforeUnloadConfirmPanelWithMessage:(NSString*) message initiatedByFrame:(WebFrame*) frame {
     return [self webView:sender runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:frame];
@@ -133,4 +137,37 @@
     return nil;
 }
 
+# pragma mark WebResourceLoadDelegate
+- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier
+          willSendRequest:(NSURLRequest *)request
+         redirectResponse:(NSURLResponse *)redirectResponse
+           fromDataSource:(WebDataSource *)dataSource {
+    // only handle cookies for http and https
+    if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]]) {
+        [_cookies handleCookiesInResponse:(NSHTTPURLResponse*) redirectResponse];
+    }
+
+    NSMutableURLRequest* modifiedRequest = [request mutableCopy];
+    [modifiedRequest setHTTPShouldHandleCookies:NO];
+    [_cookies handleCookiesInRequest:modifiedRequest];
+    return modifiedRequest;
+}
+
+- (void)   webView:(WebView *)sender resource:(id)identifier
+didReceiveResponse:(NSURLResponse *)response
+    fromDataSource:(WebDataSource *)dataSource {
+    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
+        [_cookies handleCookiesInResponse: (NSHTTPURLResponse *) response];
+    }
+}
+
+#pragma mark WebFrameLoadDelegate
+
+- (void) webView:(WebView*) sender didFinishLoadForFrame:(WebFrame*) frame {
+    id win = [sender windowScriptObject];
+    NSString* nativeReady = @"try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady = true;}";
+    [win evaluateWebScript:nativeReady];
+}
+
+
 @end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/90843d7c/CordovaLib/CordovaLib/Classes/CookieJar.h
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib/Classes/CookieJar.h b/CordovaLib/CordovaLib/Classes/CookieJar.h
new file mode 100644
index 0000000..11f6090
--- /dev/null
+++ b/CordovaLib/CordovaLib/Classes/CookieJar.h
@@ -0,0 +1,38 @@
+/*
+ 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 CookieJar : NSObject
+
+- (void) putCookie:(NSHTTPCookie*) cookie;
+
+- (void) putCookies:(NSArray*) cookies;
+
+- (NSArray*) cookies;
+
+- (NSDictionary*) cookiesForURL:(NSURL*) url;
+
+- (void) handleCookiesInRequest:(NSMutableURLRequest*) request;
+
+- (void) handleCookiesInResponse:(NSHTTPURLResponse*) response;
+
+- (void) clear;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/90843d7c/CordovaLib/CordovaLib/Classes/CookieJar.m
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib/Classes/CookieJar.m b/CordovaLib/CordovaLib/Classes/CookieJar.m
new file mode 100644
index 0000000..4248d2d
--- /dev/null
+++ b/CordovaLib/CordovaLib/Classes/CookieJar.m
@@ -0,0 +1,197 @@
+/*
+ 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 "CookieJar.h"
+
+@interface CookieJar()
+
+    + (NSString*) getDomainKey: (NSString*) domain;
+    + (NSString*) getPathKey: (NSString*) path;
+    + (BOOL) keyMatch:(NSString*) key pattern:(NSString*) pattern;
+
+@end
+
+@implementation CookieJar {
+
+    /**
+    * Store of the cookies. Contains a directory of domains, paths and cookie names. eg:
+    *
+    * "www.google.com": {
+    *   "/": {
+    *     "token": { ... }
+    *   }
+    * }
+    *
+    */
+    NSMutableDictionary* _domains;
+
+}
+
+#pragma mark Static Helpers
+
++ (NSString*) getDomainKey: (NSString*) domain {
+    domain = [domain stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+    domain = [domain lowercaseString];
+
+    NSString* key = @"";
+    while (domain.length > 0) {
+        NSRange range = [domain rangeOfString:@"." options:NSBackwardsSearch];
+        if (range.length == 0) {
+            break;
+        }
+        key = [key stringByAppendingFormat:@"%@\t", [domain substringFromIndex:range.location+1]];
+        domain = [domain substringToIndex:range.location];
+    }
+    key = [key stringByAppendingString:domain];
+    return key;
+}
+
++ (NSString*) getPathKey: (NSString*) path {
+    if ([path characterAtIndex:path.length -1] != '/') {
+        path = [path stringByAppendingString:@"/"];
+    }
+    return [path stringByReplacingOccurrencesOfString:@"/" withString:@"\t"];
+}
+
+
++ (BOOL) keyMatch:(NSString*) key pattern:(NSString*) pattern {
+    if ([key isEqualToString:pattern]) {
+        return true;
+    }
+    NSRange r = [key rangeOfString:pattern];
+    if (r.length == 0 || r.location != 0) {
+        return false;
+    }
+    return [key characterAtIndex:r.length - 1] == '\t';
+}
+
+#pragma mark Initialization
+
+- (instancetype) init {
+    self = [super init];
+    if (self) {
+        _domains = [NSMutableDictionary dictionary];
+    }
+    return self;
+}
+
+#pragma mark Cookie storage
+
+- (void) putCookie:(NSHTTPCookie*) cookie {
+    // only domain names are case insensitive
+    NSString* domainKey = [CookieJar getDomainKey:cookie.domain];
+    NSString* pathKey = [CookieJar getPathKey:cookie.path];
+    NSString* name = [cookie name];
+
+    NSMutableDictionary* paths = _domains[domainKey];
+    if (!paths) {
+        paths = _domains[domainKey] = [NSMutableDictionary dictionary];
+    }
+    NSMutableDictionary* cookies = paths[pathKey];
+    if (!cookies) {
+        cookies = paths[pathKey] = [NSMutableDictionary dictionary];
+    }
+    cookies[name] = cookie;
+}
+
+- (void) putCookies:(NSArray*) cookies {
+    for (NSHTTPCookie* cookie in cookies) {
+        [self putCookie:cookie];
+    }
+}
+
+- (NSArray*) cookies {
+    NSMutableArray* resultCookies = [NSMutableArray array];
+    for (NSDictionary* domains in [_domains allValues]) {
+        for (NSDictionary* paths in [domains allValues]) {
+            [resultCookies addObjectsFromArray:[paths allValues]];
+        }
+    }
+    return resultCookies;
+}
+
+- (NSDictionary*) cookiesForURL:(NSURL*) url {
+    if (!url.host) {
+        return nil;
+    }
+    NSString* host = [CookieJar getDomainKey:url.host];
+    NSString* path = [CookieJar getPathKey:url.path];
+    BOOL secure = [url.scheme isEqualToString:@"https"];
+    NSDate* now = [NSDate date];
+
+    NSMutableDictionary* resultCookies = [NSMutableDictionary dictionary];
+    for (NSString* domain in [[_domains allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
+        if ([CookieJar keyMatch:host pattern:domain]) {
+            NSDictionary* pathIdx = _domains[domain];
+            for (NSString* cookiePath in [[pathIdx allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
+                // "The request-uri's path path-matches the cookie's path."
+                if (![CookieJar keyMatch:path pattern:cookiePath]) {
+                    continue;
+                }
+                NSMutableDictionary* cookieIdx = pathIdx[cookiePath];
+                for (NSHTTPCookie* c in [cookieIdx allValues]) {
+                    // "If the cookie's secure-only-flag is true, then the request-uri's
+                    // scheme must denote a "secure" protocol"
+                    if ([c isSecure] && !secure) {
+                        continue;
+                    }
+
+                    // deferred from S5.3
+                    // non-RFC: allow retention of expired cookies by choice
+                    if ([c.expiresDate timeIntervalSinceDate:now] < 0) {
+                        [cookieIdx removeObjectForKey:c.name];
+                        continue;
+                    }
+                    resultCookies[c.name] = c;
+                }
+            }
+        }
+    }
+    return resultCookies;
+}
+
+- (void) clear {
+    [_domains removeAllObjects];
+}
+
+#pragma mark Request / Response Handling
+
+- (void) handleCookiesInRequest:(NSMutableURLRequest*) request {
+    NSURL* url = request.URL;
+    NSArray* cookies = [[self cookiesForURL:url] allValues];
+    NSDictionary* headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
+
+    NSUInteger count = [headers count];
+    __unsafe_unretained id keys[count], values[count];
+    [headers getObjects:values andKeys:keys];
+
+    for (NSUInteger i = 0; i < count; i++) {
+        [request setValue:values[i] forHTTPHeaderField:keys[i]];
+    }
+}
+
+
+- (void) handleCookiesInResponse:(NSHTTPURLResponse*) response {
+    NSURL* url = response.URL;
+    NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:response.allHeaderFields forURL:url];
+    [self putCookies:cookies];
+}
+
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-osx/blob/90843d7c/CordovaLib/CordovaLib/Classes/Localizable.strings
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib/Classes/Localizable.strings b/CordovaLib/CordovaLib/Classes/Localizable.strings
new file mode 100644
index 0000000..6038f0b
--- /dev/null
+++ b/CordovaLib/CordovaLib/Classes/Localizable.strings
@@ -0,0 +1,7 @@
+/****************************************************************************/
+/* Localization file */
+
+
+"OK" = "OK";
+
+"Cancel" = "Cancel";


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org