From 2215219ac5442c0a48211dc88cae72f017c86d0d Mon Sep 17 00:00:00 2001 From: Philipp Wallrich Date: Mon, 16 Jul 2018 08:40:18 +0200 Subject: [PATCH 1/6] Added Cookie Handling --- ios/RCTWKWebView/RCTWKWebView.m | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ios/RCTWKWebView/RCTWKWebView.m b/ios/RCTWKWebView/RCTWKWebView.m index b0f33f43..daefca72 100644 --- a/ios/RCTWKWebView/RCTWKWebView.m +++ b/ios/RCTWKWebView/RCTWKWebView.m @@ -299,11 +299,49 @@ - (void)stopLoading [_webView stopLoading]; } +- (void) copyCookies { + + NSHTTPCookieStorage* storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + NSArray* array = [storage cookies]; + + + if (@available(ios 11,*)) { + + // The webView websiteDataStore only gets initialized, when needed. Setting cookies on the dataStore's + // httpCookieStore doesn't seem to initialize it. That's why fetchDataRecordsOfTypes is called. + // All the cookies of the sharedHttpCookieStorage, which is used in react-native-cookie, + // are copied to the webSiteDataStore's httpCookieStore. + // https://bugs.webkit.org/show_bug.cgi?id=185483 + [_webView.configuration.websiteDataStore fetchDataRecordsOfTypes:[NSSet setWithObject:WKWebsiteDataTypeCookies] completionHandler:^(NSArray *records) { + for (NSHTTPCookie* cookie in array) { + [_webView.configuration.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil]; + } + }]; + } else { + // Create WKUserScript for each cookie + // Cookies are injected with Javascript AtDocumentStart + for (NSHTTPCookie* cookie in array){ + NSString* cookieSource = [NSString stringWithFormat:@"document.cookie = '%@'", [self cookieDescription:cookie]]; + WKUserScript* cookieScript = [[WKUserScript alloc] + initWithSource:cookieSource + injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; + + + [_webView.configuration.userContentController addUserScript:cookieScript]; + } + } +} + - (void)setSource:(NSDictionary *)source { if (![_source isEqualToDictionary:source]) { _source = [source copy]; _sendCookies = [source[@"sendCookies"] boolValue]; + + if (_sendCookies) { + [self copyCookies]; + } + if ([source[@"customUserAgent"] length] != 0 && [_webView respondsToSelector:@selector(setCustomUserAgent:)]) { [_webView setCustomUserAgent:source[@"customUserAgent"]]; } From ddf71c84c128d2072c8d82c2a3fc007843231e9e Mon Sep 17 00:00:00 2001 From: Philipp Wallrich Date: Tue, 17 Jul 2018 13:49:05 +0200 Subject: [PATCH 2/6] added missing Method --- ios/RCTWKWebView/RCTWKWebView.m | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ios/RCTWKWebView/RCTWKWebView.m b/ios/RCTWKWebView/RCTWKWebView.m index daefca72..02a88cbb 100644 --- a/ios/RCTWKWebView/RCTWKWebView.m +++ b/ios/RCTWKWebView/RCTWKWebView.m @@ -299,6 +299,23 @@ - (void)stopLoading [_webView stopLoading]; } +- (NSString *) cookieDescription:(NSHTTPCookie *)cookie { + + NSMutableString *cDesc = [[NSMutableString alloc] init]; + [cDesc appendFormat:@"%@=%@;", + [[cookie name] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [[cookie value] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + if ([cookie.domain length] > 0) + [cDesc appendFormat:@"domain=%@;", [cookie domain]]; + if ([cookie.path length] > 0) + [cDesc appendFormat:@"path=%@;", [cookie path]]; + if (cookie.expiresDate != nil) + [cDesc appendFormat:@"expiresDate=%@;", [cookie expiresDate]]; + + + return cDesc; +} + - (void) copyCookies { NSHTTPCookieStorage* storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; From 3eac1f52a25529b962c16b6c16314b5542c46360 Mon Sep 17 00:00:00 2001 From: Philipp Wallrich Date: Tue, 24 Jul 2018 09:43:43 +0200 Subject: [PATCH 3/6] Added new useWKCookieStore option --- README.md | 4 ++++ WKWebView.ios.js | 5 +++++ ios/RCTWKWebView/RCTWKWebView.m | 20 +++++++++++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 66ca2066..55551d5e 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ If set to true, links with `target="_blank"` or `window.open` will be opened in Set `sendCookies` to true to copy cookies from `sharedHTTPCookieStorage` when calling loadRequest. This emulates the behavior of react-native's `WebView` component. You can set cookies using `react-native-cookies` Default is false. +- **useWKCookieStore** + +Set `useWKCookieStore` to true to use the webView's `WKHTTPCookieStorage`. All Cookies from `sharedHTTPCookieStorage` will be copied to it. + - **source={{file: '', allowingReadAccessToURL: '' }}** This allows WKWebView loads a local HTML file. Please note the underlying API is only introduced in iOS 9+. So in iOS 8, it will simple ignores these two properties. diff --git a/WKWebView.ios.js b/WKWebView.ios.js index e23c7ab7..41de6458 100644 --- a/WKWebView.ios.js +++ b/WKWebView.ios.js @@ -228,6 +228,10 @@ class WKWebView extends React.Component { * Set this to true to emulate behavior of WebView component. */ sendCookies: PropTypes.bool, + /** + * Initializes the webView's WKHTTPCookieStorage and copies all cookies from sharedHTTPCookieStorage + */ + useWKCookieStore: PropTypes.bool, /** * If set to true, target="_blank" or window.open will be opened in WebView, instead * of new window. Default is false to be backward compatible. @@ -313,6 +317,7 @@ class WKWebView extends React.Component { source.sendCookies = this.props.sendCookies; source.customUserAgent = this.props.customUserAgent || this.props.userAgent; + source.useWKCookieStore: this.props.useWKCookieStore; } if (this.props.html) { diff --git a/ios/RCTWKWebView/RCTWKWebView.m b/ios/RCTWKWebView/RCTWKWebView.m index 02a88cbb..9b35714d 100644 --- a/ios/RCTWKWebView/RCTWKWebView.m +++ b/ios/RCTWKWebView/RCTWKWebView.m @@ -34,6 +34,7 @@ @interface RCTWKWebView () Date: Mon, 30 Jul 2018 09:29:00 +0200 Subject: [PATCH 4/6] fix syntax --- WKWebView.ios.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WKWebView.ios.js b/WKWebView.ios.js index 41de6458..26c7d9c1 100644 --- a/WKWebView.ios.js +++ b/WKWebView.ios.js @@ -317,7 +317,7 @@ class WKWebView extends React.Component { source.sendCookies = this.props.sendCookies; source.customUserAgent = this.props.customUserAgent || this.props.userAgent; - source.useWKCookieStore: this.props.useWKCookieStore; + source.useWKCookieStore = this.props.useWKCookieStore; } if (this.props.html) { From 36c7c367cf1689241b079ba44593d591c8a174e2 Mon Sep 17 00:00:00 2001 From: Jens Fahnenbruck Date: Wed, 15 Aug 2018 10:30:15 +0200 Subject: [PATCH 5/6] create copy of read only object --- WKWebView.ios.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/WKWebView.ios.js b/WKWebView.ios.js index 26c7d9c1..dcad991b 100644 --- a/WKWebView.ios.js +++ b/WKWebView.ios.js @@ -312,13 +312,11 @@ class WKWebView extends React.Component { WKWebViewManager.startLoadWithResult(!!shouldStart, event.nativeEvent.lockIdentifier); }); - let source = this.props.source || {}; - if (typeof source == 'object') { - source.sendCookies = this.props.sendCookies; - source.customUserAgent = - this.props.customUserAgent || this.props.userAgent; - source.useWKCookieStore = this.props.useWKCookieStore; - } + let source = Object.assign({}, this.props.source || {}, { + sendCookies: this.props.sendCookies, + customUserAgent: this.props.customUserAgent || this.props.userAgent, + useWKCookieStore: this.props.useWKCookieStore, + }); if (this.props.html) { source.html = this.props.html; From 50a49a8f01ac4e09b69f6faf57a2e26310bd62df Mon Sep 17 00:00:00 2001 From: Jens Fahnenbruck Date: Wed, 15 Aug 2018 10:35:53 +0200 Subject: [PATCH 6/6] clean spaces --- ios/RCTWKWebView/RCTWKWebView.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/RCTWKWebView/RCTWKWebView.m b/ios/RCTWKWebView/RCTWKWebView.m index 9b35714d..d1bcd6b5 100644 --- a/ios/RCTWKWebView/RCTWKWebView.m +++ b/ios/RCTWKWebView/RCTWKWebView.m @@ -301,7 +301,7 @@ - (void)stopLoading } - (NSString *) cookieDescription:(NSHTTPCookie *)cookie { - + NSMutableString *cDesc = [[NSMutableString alloc] init]; [cDesc appendFormat:@"%@=%@;", [[cookie name] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding], @@ -312,8 +312,8 @@ - (NSString *) cookieDescription:(NSHTTPCookie *)cookie { [cDesc appendFormat:@"path=%@;", [cookie path]]; if (cookie.expiresDate != nil) [cDesc appendFormat:@"expiresDate=%@;", [cookie expiresDate]]; - - + + return cDesc; }