cf706d56fd56d879f56e96119f33c0cb4960ba7e
[WebKit.git] / Source / WebKit / UIProcess / API / APIHTTPCookieStore.cpp
1 /*
2  * Copyright (C) 2017 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "APIHTTPCookieStore.h"
28
29 #include "WebCookieManagerProxy.h"
30 #include "WebProcessPool.h"
31 #include "WebsiteDataStore.h"
32 #include <WebCore/Cookie.h>
33 #include <WebCore/CookieStorage.h>
34 #include <WebCore/NetworkStorageSession.h>
35
36 using namespace WebKit;
37
38 namespace API {
39
40 HTTPCookieStore::HTTPCookieStore(WebKit::WebsiteDataStore& websiteDataStore)
41     : m_owningDataStore(websiteDataStore)
42 {
43     if (!m_owningDataStore->processPoolForCookieStorageOperations())
44         registerForNewProcessPoolNotifications();
45 }
46
47 HTTPCookieStore::~HTTPCookieStore()
48 {
49     ASSERT(m_observers.isEmpty());
50     ASSERT(!m_observedCookieManagerProxy);
51     ASSERT(!m_cookieManagerProxyObserver);
52
53     unregisterForNewProcessPoolNotifications();
54 }
55
56 void HTTPCookieStore::cookies(CompletionHandler<void(const Vector<WebCore::Cookie>&)>&& completionHandler)
57 {
58     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
59     if (!pool) {
60         Vector<WebCore::Cookie> allCookies;
61         if (m_owningDataStore->sessionID() == PAL::SessionID::defaultSessionID())
62             allCookies = getAllDefaultUIProcessCookieStoreCookies();
63         allCookies.appendVector(m_owningDataStore->pendingCookies());
64
65         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), allCookies] () mutable {
66             completionHandler(allCookies);
67         });
68         return;
69     }
70
71     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
72     cookieManager->getAllCookies(m_owningDataStore->sessionID(), [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)] (const Vector<WebCore::Cookie>& cookies, CallbackBase::Error error) mutable {
73         completionHandler(cookies);
74     });
75 }
76
77 void HTTPCookieStore::setCookies(const Vector<WebCore::Cookie>& cookies, CompletionHandler<void()>&& completionHandler)
78 {
79     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
80     if (!pool) {
81         for (auto& cookie : cookies) {
82             // FIXME: pendingCookies used for defaultSession because session cookies cannot be propagated to Network Process with uiProcessCookieStorageIdentifier.
83             if (m_owningDataStore->sessionID() == PAL::SessionID::defaultSessionID() && !cookie.session)
84                 setCookieInDefaultUIProcessCookieStore(cookie);
85             else
86                 m_owningDataStore->addPendingCookie(cookie);
87         }
88
89         RunLoop::main().dispatch(WTFMove(completionHandler));
90         return;
91     }
92
93     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
94     cookieManager->setCookies(m_owningDataStore->sessionID(), cookies, [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)] (CallbackBase::Error error) mutable {
95         completionHandler();
96     });
97 }
98
99 void HTTPCookieStore::deleteCookie(const WebCore::Cookie& cookie, CompletionHandler<void()>&& completionHandler)
100 {
101     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
102     if (!pool) {
103         if (m_owningDataStore->sessionID() == PAL::SessionID::defaultSessionID() && !cookie.session)
104             deleteCookieFromDefaultUIProcessCookieStore(cookie);
105         else
106             m_owningDataStore->removePendingCookie(cookie);
107
108         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
109             completionHandler();
110         });
111         return;
112     }
113
114     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
115     cookieManager->deleteCookie(m_owningDataStore->sessionID(), cookie, [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)](CallbackBase::Error error) mutable {
116         completionHandler();
117     });
118 }
119
120 void HTTPCookieStore::deleteAllCookies(CompletionHandler<void()>&& completionHandler)
121 {
122     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
123     if (!pool) {
124         if (!m_owningDataStore->sessionID().isEphemeral())
125             deleteCookiesInDefaultUIProcessCookieStore();
126         RunLoop::main().dispatch(WTFMove(completionHandler));
127         return;
128     }
129
130     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
131     cookieManager->deleteAllCookies(m_owningDataStore->sessionID());
132     // FIXME: The CompletionHandler should be passed to WebCookieManagerProxy::deleteAllCookies.
133     RunLoop::main().dispatch(WTFMove(completionHandler));
134 }
135
136 void HTTPCookieStore::setHTTPCookieAcceptPolicy(WebKit::HTTPCookieAcceptPolicy policy, CompletionHandler<void()>&& completionHandler)
137 {
138     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
139     if (!pool) {
140         if (!m_owningDataStore->sessionID().isEphemeral())
141             setHTTPCookieAcceptPolicyInDefaultUIProcessCookieStore(policy);
142         RunLoop::main().dispatch(WTFMove(completionHandler));
143         return;
144     }
145
146     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
147     cookieManager->setHTTPCookieAcceptPolicy(m_owningDataStore->sessionID(), policy, [completionHandler = WTFMove(completionHandler)] (CallbackBase::Error) mutable {
148         completionHandler();
149     });
150 }
151
152 class APIWebCookieManagerProxyObserver : public WebCookieManagerProxy::Observer {
153     WTF_MAKE_FAST_ALLOCATED;
154 public:
155     explicit APIWebCookieManagerProxyObserver(API::HTTPCookieStore& cookieStore)
156         : m_cookieStore(cookieStore)
157     {
158     }
159
160 private:
161     void cookiesDidChange() final
162     {
163         m_cookieStore.cookiesDidChange();
164     }
165
166     void managerDestroyed() final
167     {
168         m_cookieStore.cookieManagerDestroyed();
169     }
170
171     API::HTTPCookieStore& m_cookieStore;
172 };
173
174 void HTTPCookieStore::registerObserver(Observer& observer)
175 {
176     m_observers.add(&observer);
177
178     if (m_cookieManagerProxyObserver)
179         return;
180
181     ASSERT(!m_observedCookieManagerProxy);
182
183     m_cookieManagerProxyObserver = makeUnique<APIWebCookieManagerProxyObserver>(*this);
184
185     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
186
187     if (!pool) {
188         ASSERT(!m_observingUIProcessCookies);
189
190         // Listen for cookie notifications in the UIProcess in the meantime.
191         startObservingChangesToDefaultUIProcessCookieStore([this] () {
192             cookiesDidChange();
193         });
194
195         m_observingUIProcessCookies = true;
196         return;
197     }
198
199     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
200     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
201 }
202
203 void HTTPCookieStore::unregisterObserver(Observer& observer)
204 {
205     m_observers.remove(&observer);
206
207     if (!m_observers.isEmpty())
208         return;
209
210     if (m_observedCookieManagerProxy)
211         m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
212
213     if (m_observingUIProcessCookies)
214         stopObservingChangesToDefaultUIProcessCookieStore();
215
216     if (m_processPoolCreationListenerIdentifier)
217         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
218
219     m_processPoolCreationListenerIdentifier = 0;
220     m_observedCookieManagerProxy = nullptr;
221     m_cookieManagerProxyObserver = nullptr;
222     m_observingUIProcessCookies = false;
223 }
224
225 void HTTPCookieStore::cookiesDidChange()
226 {
227     for (auto* observer : m_observers)
228         observer->cookiesDidChange(*this);
229 }
230
231 void HTTPCookieStore::cookieManagerDestroyed()
232 {
233     m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
234     m_observedCookieManagerProxy = nullptr;
235
236     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
237
238     if (!pool)
239         return;
240
241     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
242     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
243 }
244
245 void HTTPCookieStore::registerForNewProcessPoolNotifications()
246 {
247     ASSERT(!m_processPoolCreationListenerIdentifier);
248
249     m_processPoolCreationListenerIdentifier = WebProcessPool::registerProcessPoolCreationListener([this](WebProcessPool& newProcessPool) {
250         if (!m_owningDataStore->isAssociatedProcessPool(newProcessPool))
251             return;
252
253         // Now that an associated process pool exists, we need to flush the UI process cookie store
254         // to make sure any changes are reflected within the new process pool.
255         flushDefaultUIProcessCookieStore();
256         newProcessPool.ensureNetworkProcess();
257
258         if (m_cookieManagerProxyObserver) {
259             m_observedCookieManagerProxy = newProcessPool.supplement<WebKit::WebCookieManagerProxy>();
260             m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
261         }
262         unregisterForNewProcessPoolNotifications();
263     });
264 }
265
266 void HTTPCookieStore::unregisterForNewProcessPoolNotifications()
267 {
268     if (m_processPoolCreationListenerIdentifier)
269         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
270
271     m_processPoolCreationListenerIdentifier = 0;
272 }
273
274 #if !PLATFORM(COCOA)
275 void HTTPCookieStore::flushDefaultUIProcessCookieStore() { }
276 Vector<WebCore::Cookie> HTTPCookieStore::getAllDefaultUIProcessCookieStoreCookies() { return { }; }
277 void HTTPCookieStore::setCookieInDefaultUIProcessCookieStore(const WebCore::Cookie&) { }
278 void HTTPCookieStore::deleteCookieFromDefaultUIProcessCookieStore(const WebCore::Cookie&) { }
279 void HTTPCookieStore::startObservingChangesToDefaultUIProcessCookieStore(Function<void()>&&) { }
280 void HTTPCookieStore::stopObservingChangesToDefaultUIProcessCookieStore() { }
281 void HTTPCookieStore::deleteCookiesInDefaultUIProcessCookieStore() { }
282 void HTTPCookieStore::setHTTPCookieAcceptPolicyInDefaultUIProcessCookieStore(WebKit::HTTPCookieAcceptPolicy) { }
283 #endif
284     
285 } // namespace API