-[WKHTTPCookieStore deleteCookie:completionHandler:] doesn't delete cookies
[WebKit-https.git] / Source / WebCore / platform / network / cocoa / NetworkStorageSessionCocoa.mm
1 /*
2  * Copyright (C) 2015-2018 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "NetworkStorageSession.h"
28
29 #import "Cookie.h"
30 #import "CookieStorageObserver.h"
31 #import "URL.h"
32 #import <pal/spi/cf/CFNetworkSPI.h>
33 #import <wtf/BlockObjCExceptions.h>
34 #import <wtf/ProcessPrivilege.h>
35
36 namespace WebCore {
37
38 void NetworkStorageSession::setCookie(const Cookie& cookie)
39 {
40     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
41
42     BEGIN_BLOCK_OBJC_EXCEPTIONS;
43     [nsCookieStorage() setCookie:(NSHTTPCookie *)cookie];
44     END_BLOCK_OBJC_EXCEPTIONS;
45 }
46
47 void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL)
48 {
49     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
50
51     RetainPtr<NSMutableArray> nsCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:cookies.size()]);
52     for (const auto& cookie : cookies)
53         [nsCookies addObject:(NSHTTPCookie *)cookie];
54
55     BEGIN_BLOCK_OBJC_EXCEPTIONS;
56     [nsCookieStorage() setCookies:nsCookies.get() forURL:(NSURL *)url mainDocumentURL:(NSURL *)mainDocumentURL];
57     END_BLOCK_OBJC_EXCEPTIONS;
58 }
59
60 void NetworkStorageSession::deleteCookie(const Cookie& cookie)
61 {
62     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
63     
64     NSArray *nsCookies = [nsCookieStorage() cookies];
65     for (NSHTTPCookie *nsCookie in nsCookies) {
66         if (Cookie(nsCookie) == cookie) {
67             [nsCookieStorage() deleteCookie:nsCookie];
68             break;
69         }
70     }
71 }
72
73 static Vector<Cookie> nsCookiesToCookieVector(NSArray<NSHTTPCookie *> *nsCookies)
74 {
75     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
76
77     Vector<Cookie> cookies;
78     cookies.reserveInitialCapacity(nsCookies.count);
79     for (NSHTTPCookie *nsCookie in nsCookies)
80         cookies.uncheckedAppend(nsCookie);
81
82     return cookies;
83 }
84
85 Vector<Cookie> NetworkStorageSession::getAllCookies()
86 {
87     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
88     return nsCookiesToCookieVector(nsCookieStorage().cookies);
89 }
90
91 Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
92 {
93     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
94     return nsCookiesToCookieVector([nsCookieStorage() cookiesForURL:(NSURL *)url]);
95 }
96
97 void NetworkStorageSession::flushCookieStore()
98 {
99     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
100     [nsCookieStorage() _saveCookies];
101 }
102
103 NSHTTPCookieStorage *NetworkStorageSession::nsCookieStorage() const
104 {
105     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
106     auto cfCookieStorage = cookieStorage();
107     if (!cfCookieStorage || [NSHTTPCookieStorage sharedHTTPCookieStorage]._cookieStorage == cfCookieStorage)
108         return [NSHTTPCookieStorage sharedHTTPCookieStorage];
109
110     return [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:cfCookieStorage.get()] autorelease];
111 }
112
113 CookieStorageObserver& NetworkStorageSession::cookieStorageObserver() const
114 {
115     if (!m_cookieStorageObserver)
116         m_cookieStorageObserver = CookieStorageObserver::create(nsCookieStorage());
117
118     return *m_cookieStorageObserver;
119 }
120
121 CFURLStorageSessionRef createPrivateStorageSession(CFStringRef identifier)
122 {
123     const void* sessionPropertyKeys[] = { _kCFURLStorageSessionIsPrivate };
124     const void* sessionPropertyValues[] = { kCFBooleanTrue };
125     auto sessionProperties = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, sessionPropertyKeys, sessionPropertyValues, sizeof(sessionPropertyKeys) / sizeof(*sessionPropertyKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
126     auto storageSession = adoptCF(_CFURLStorageSessionCreate(kCFAllocatorDefault, identifier, sessionProperties.get()));
127
128     if (!storageSession)
129         return nullptr;
130
131     // The private storage session should have the same properties as the default storage session,
132     // with the exception that it should be in-memory only storage.
133
134     // FIXME 9199649: If any of the storages do not exist, do no use the storage session.
135     // This could occur if there is an issue figuring out where to place a storage on disk (e.g. the
136     // sandbox does not allow CFNetwork access).
137
138     auto cache = adoptCF(_CFURLStorageSessionCopyCache(kCFAllocatorDefault, storageSession.get()));
139     if (!cache)
140         return nullptr;
141
142     CFURLCacheSetDiskCapacity(cache.get(), 0); // Setting disk cache size should not be necessary once <rdar://problem/12656814> is fixed.
143     CFURLCacheSetMemoryCapacity(cache.get(), [[NSURLCache sharedURLCache] memoryCapacity]);
144
145     if (!NetworkStorageSession::processMayUseCookieAPI())
146         return storageSession.leakRef();
147
148     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
149
150     auto cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
151     if (!cookieStorage)
152         return nullptr;
153
154     // FIXME: Use _CFHTTPCookieStorageGetDefault when USE(CFNETWORK) is defined in WebKit for consistency.
155     CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage.get(), [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy]);
156
157     return storageSession.leakRef();
158 }
159
160 } // namespace WebCore