Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,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.
Expand Down
26 changes: 14 additions & 12 deletions WKWebView.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,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.
Expand Down Expand Up @@ -312,18 +316,16 @@ class WKWebView extends React.Component {
WKWebViewManager.startLoadWithResult(!!shouldStart, event.nativeEvent.lockIdentifier);
});

let source = this.props.source;
if (this.props.source && typeof this.props.source === 'object') {
source = Object.assign({}, this.props.source, {
sendCookies: this.props.sendCookies,
customUserAgent: this.props.customUserAgent || this.props.userAgent
});

if (this.props.html) {
source.html = this.props.html;
} else if (this.props.url) {
source.uri = this.props.url;
}
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;
} else if (this.props.url) {
source.uri = this.props.url;
}

const messagingEnabled = typeof this.props.onMessage === 'function';
Expand Down
57 changes: 57 additions & 0 deletions ios/RCTWKWebView/RCTWKWebView.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ @interface RCTWKWebView () <WKNavigationDelegate, RCTAutoInsetsProtocol, WKScrip
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
@property (nonatomic, copy) RCTDirectEventBlock onNavigationResponse;
@property (assign) BOOL sendCookies;
@property (assign) BOOL useWKCookieStore;
@property (nonatomic, strong) WKUserScript *atStartScript;
@property (nonatomic, strong) WKUserScript *atEndScript;

Expand Down Expand Up @@ -306,11 +307,67 @@ - (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];
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<NSString *> setWithObject:WKWebsiteDataTypeCookies] completionHandler:^(NSArray<WKWebsiteDataRecord *> *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];
_useWKCookieStore = [source[@"useWKCookieStore"] boolValue];

if (_useWKCookieStore) {
[self copyCookies];
}

if ([source[@"customUserAgent"] length] != 0 && [_webView respondsToSelector:@selector(setCustomUserAgent:)]) {
[_webView setCustomUserAgent:source[@"customUserAgent"]];
}
Expand Down