-[WKHTTPCookieStore deleteCookie:completionHandler:] doesn't delete cookies
https://bugs.webkit.org/show_bug.cgi?id=184938
<rdar://problem/34737395>

Patch by Sihui Liu <sihui_liu@apple.com> on 2018-04-26
Reviewed by Geoffrey Garen.

Source/WebCore:

When a Cookie object was converted to NSHTTPCookie object, the HTTPOnly property information
was lost so the delete function cannot find the proper cookie to delete.
This patch implements a workaround that compares Cookie object instead of NSHTTPCookie
object. We might want to add the ability to set HTTPOnly header during conversion if there
is an easy way to do it later.

New API test: WebKit.WKHTTPCookieStoreHttpOnly

* platform/network/cocoa/CookieCocoa.mm:
(WebCore::Cookie::operator== const):
* platform/network/cocoa/NetworkStorageSessionCocoa.mm:
(WebCore::NetworkStorageSession::deleteCookie):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm:
(TEST):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231067 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index df742bc..a3e7e8f 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,24 @@
+2018-04-26  Sihui Liu  <sihui_liu@apple.com>
+
+        -[WKHTTPCookieStore deleteCookie:completionHandler:] doesn't delete cookies
+        https://bugs.webkit.org/show_bug.cgi?id=184938
+        <rdar://problem/34737395>
+
+        Reviewed by Geoffrey Garen.
+
+        When a Cookie object was converted to NSHTTPCookie object, the HTTPOnly property information
+        was lost so the delete function cannot find the proper cookie to delete.
+        This patch implements a workaround that compares Cookie object instead of NSHTTPCookie 
+        object. We might want to add the ability to set HTTPOnly header during conversion if there
+        is an easy way to do it later.
+        
+        New API test: WebKit.WKHTTPCookieStoreHttpOnly
+
+        * platform/network/cocoa/CookieCocoa.mm:
+        (WebCore::Cookie::operator== const):
+        * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+        (WebCore::NetworkStorageSession::deleteCookie):
+
 2018-04-26  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r231052.
diff --git a/Source/WebCore/platform/network/cocoa/CookieCocoa.mm b/Source/WebCore/platform/network/cocoa/CookieCocoa.mm
index 8df8bb2..19adf2a 100644
--- a/Source/WebCore/platform/network/cocoa/CookieCocoa.mm
+++ b/Source/WebCore/platform/network/cocoa/CookieCocoa.mm
@@ -132,8 +132,18 @@
     if (thisNull || otherNull)
         return thisNull == otherNull;
     
-    NSHTTPCookie *nsCookie(*this);
-    return [nsCookie isEqual:other];
+    return name == other.name
+    && value == other.value
+    && domain == other.domain
+    && path == other.path
+    && created == other.created
+    && expires == other.expires
+    && httpOnly == other.httpOnly
+    && secure == other.secure
+    && session == other.session
+    && comment == other.comment
+    && commentURL == other.commentURL
+    && ports == other.ports;
 }
     
 unsigned Cookie::hash() const
diff --git a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
index b9a95fd..f499c2b 100644
--- a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
+++ b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm
@@ -60,8 +60,14 @@
 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
-
-    [nsCookieStorage() deleteCookie:(NSHTTPCookie *)cookie];
+    
+    NSArray *nsCookies = [nsCookieStorage() cookies];
+    for (NSHTTPCookie *nsCookie in nsCookies) {
+        if (Cookie(nsCookie) == cookie) {
+            [nsCookieStorage() deleteCookie:nsCookie];
+            break;
+        }
+    }
 }
 
 static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies)
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 390eea0..61d7941 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,16 @@
+2018-04-26  Sihui Liu  <sihui_liu@apple.com>
+
+        -[WKHTTPCookieStore deleteCookie:completionHandler:] doesn't delete cookies
+        https://bugs.webkit.org/show_bug.cgi?id=184938
+        <rdar://problem/34737395>
+
+        Reviewed by Geoffrey Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm:
+        (TEST):
+
 2018-04-26  Ross Kirsling  <ross.kirsling@sony.com>
 
         WinCairo test bots should run JSC tests with options for Windows command prompt.
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm
index a875332..2a4b7f7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm
+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKHTTPCookieStore.mm
@@ -192,6 +192,90 @@
     runTestWithWebsiteDataStore([WKWebsiteDataStore defaultDataStore]);
 }
 
+TEST(WebKit, WKHTTPCookieStoreHttpOnly) 
+{
+    WKWebsiteDataStore* dataStore = [WKWebsiteDataStore defaultDataStore];
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    configuration.get().websiteDataStore = dataStore;
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    [webView loadHTMLString:@"WebKit Test" baseURL:[NSURL URLWithString:@"http://webkit.org"]];
+    [webView _test_waitForDidFinishNavigation];
+
+    [dataStore removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:[] {
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+
+    id pool = [WKProcessPool _sharedProcessPool];
+    EXPECT_EQ([pool _pluginProcessCount], static_cast<size_t>(0));
+
+    globalCookieStore = dataStore.httpCookieStore;
+
+    NSArray<NSHTTPCookie *> *cookies = nil;
+    [globalCookieStore getAllCookies:[cookiesPtr = &cookies](NSArray<NSHTTPCookie *> *nsCookies) {
+        *cookiesPtr = [nsCookies retain];
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+
+    ASSERT_EQ(cookies.count, 0u);
+    [cookies release];
+
+    CFMutableDictionaryRef cookieProperties = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    CFDictionarySetValue(cookieProperties, CFSTR("Name"), CFSTR("httpCookie"));
+    CFDictionarySetValue(cookieProperties, CFSTR("Value"), CFSTR("httpCookieValue"));
+    CFDictionarySetValue(cookieProperties, CFSTR("Domain"), CFSTR(".www.webkit.org"));
+    CFDictionarySetValue(cookieProperties, CFSTR("Path"), CFSTR("/httpPath"));
+    CFDictionarySetValue(cookieProperties, CFSTR("HttpOnly"), kCFBooleanTrue);
+    RetainPtr<NSHTTPCookie> httpOnlyCookie = [NSHTTPCookie cookieWithProperties:(NSDictionary*) cookieProperties];
+    CFDictionaryRemoveValue(cookieProperties, CFSTR("HttpOnly"));
+    RetainPtr<NSHTTPCookie> notHttpOnlyCookie = [NSHTTPCookie cookieWithProperties:(NSDictionary*) cookieProperties];
+    EXPECT_TRUE(httpOnlyCookie.get().HTTPOnly);
+    EXPECT_FALSE(notHttpOnlyCookie.get().HTTPOnly);
+
+    [globalCookieStore setCookie:notHttpOnlyCookie.get() completionHandler:[]() {
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+
+    [globalCookieStore getAllCookies:[cookiesPtr = &cookies](NSArray<NSHTTPCookie *> *nsCookies) {
+        *cookiesPtr = [nsCookies retain];
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+
+    ASSERT_EQ(cookies.count, 1u);
+    [cookies release];
+
+    [globalCookieStore deleteCookie:httpOnlyCookie.get() completionHandler:[]() {
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+    [globalCookieStore getAllCookies:[cookiesPtr = &cookies](NSArray<NSHTTPCookie *> *nsCookies) {
+        *cookiesPtr = [nsCookies retain];
+        gotFlag = true;
+    }];
+
+    TestWebKitAPI::Util::run(&gotFlag);
+    gotFlag = false;
+
+    // Delete httpOnlyCookie should fail because it is different from notHttpOnlyCookie. 
+    ASSERT_EQ(cookies.count, 1u);
+    [cookies release];
+}
+
 // FIXME: This should be removed once <rdar://problem/35344202> is resolved and bots are updated.
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED <= 101301) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MAX_ALLOWED <= 110102)
 TEST(WebKit, WKHTTPCookieStoreNonPersistent)