3

WKWebView can manage its own cookie in WKHTTPCookieStorage, independent with NSHTTPCookieStorage. How can I sync cookie from WKHTTPCookieStore to NSHTTPCookieStorage.

My target is sync the cookies with WKHTTPCookieStore and NSHTTPCookieStorage.

I try to sync cookie with implement the observer method WKHTTPCookieStoreObserver.

- (void)cookiesDidChangeInCookieStore:(WKHTTPCookieStore *)cookieStore {
[cookieStore getAllCookies:^(NSArray<NSHTTPCookie *> *array) {
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *nsHttpCookies = cookieStorage.cookies;

    //add new Cookie from wkWebView
    [array enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) {
        if(![nsHttpCookies containsObject:cookie]){
            [cookieStorage setCookie:cookie];
        }
    }];

    //add old Cookie from wkWebView
    [nsHttpCookies enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) {
        if(![array containsObject:cookie]){
            [cookieStorage deleteCookie:cookie];
        }
    }];
}];
}

It's the right way to sync the cookie from WKWebView to NSHTTPCookieStorage?

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
S.Captain
  • 167
  • 1
  • 9
  • Hey, did you try to use WKNavigationDelegate instead? Maybe you could use WKNavigationResponse and extract header fields from the urlResponse. In the header fields, you should have a `Cookie` header as a String. Then you can explode it and compare what's missing. It's just an idea – Ben Feb 20 '18 at 17:48
  • Unfortunately, at least in iOS 13, the observer method isn't called at all... (https://stackoverflow.com/q/58397343/2778898). So I decided to implement the synchronization manually when initiating a new request. – LaborEtArs May 01 '20 at 08:57

1 Answers1

3

As Ben answered in a comment you need to extract the cookies from the response header and set them manual in the HTTPCookieStorage.

Swift 4:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Swift.Void) {
    guard
        let response = navigationResponse.response as? HTTPURLResponse,
        let url = navigationResponse.response.url
    else {
        decisionHandler(.cancel)
        return
    }

    if let headerFields = response.allHeaderFields as? [String: String] {
        let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
        cookies.forEach { (cookie) in
             HTTPCookieStorage.shared.setCookie(cookie)
        }
    }

    decisionHandler(.allow)
}

Objective-C:

NSHTTPURLResponse * resp = (NSHTTPURLResponse*)[navigationResponse response];
NSDictionary  *diction = [resp allHeaderFields];

NSArray * cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:diction forURL:[resp URL]];

for (NSHTTPCookie *cookie in cookies) {
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}

return decisionHandler(YES);
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Lloyd Keijzer
  • 1,229
  • 1
  • 12
  • 22