e122ee3edb1c4219d1d84199321a8003d52c821c
[WebKit-https.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 "APIWebsiteDataStore.h"
30 #include "WebCookieManagerProxy.h"
31 #include "WebProcessPool.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 class APIWebCookieManagerProxyObserver : public WebCookieManagerProxy::Observer {
121     WTF_MAKE_FAST_ALLOCATED;
122 public:
123     explicit APIWebCookieManagerProxyObserver(API::HTTPCookieStore& cookieStore)
124         : m_cookieStore(cookieStore)
125     {
126     }
127
128 private:
129     void cookiesDidChange() final
130     {
131         m_cookieStore.cookiesDidChange();
132     }
133
134     void managerDestroyed() final
135     {
136         m_cookieStore.cookieManagerDestroyed();
137     }
138
139     API::HTTPCookieStore& m_cookieStore;
140 };
141
142 void HTTPCookieStore::registerObserver(Observer& observer)
143 {
144     m_observers.add(&observer);
145
146     if (m_cookieManagerProxyObserver)
147         return;
148
149     ASSERT(!m_observedCookieManagerProxy);
150
151     m_cookieManagerProxyObserver = makeUnique<APIWebCookieManagerProxyObserver>(*this);
152
153     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
154
155     if (!pool) {
156         ASSERT(!m_observingUIProcessCookies);
157
158         // Listen for cookie notifications in the UIProcess in the meantime.
159         startObservingChangesToDefaultUIProcessCookieStore([this] () {
160             cookiesDidChange();
161         });
162
163         m_observingUIProcessCookies = true;
164         return;
165     }
166
167     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
168     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
169 }
170
171 void HTTPCookieStore::unregisterObserver(Observer& observer)
172 {
173     m_observers.remove(&observer);
174
175     if (!m_observers.isEmpty())
176         return;
177
178     if (m_observedCookieManagerProxy)
179         m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
180
181     if (m_observingUIProcessCookies)
182         stopObservingChangesToDefaultUIProcessCookieStore();
183
184     if (m_processPoolCreationListenerIdentifier)
185         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
186
187     m_processPoolCreationListenerIdentifier = 0;
188     m_observedCookieManagerProxy = nullptr;
189     m_cookieManagerProxyObserver = nullptr;
190     m_observingUIProcessCookies = false;
191 }
192
193 void HTTPCookieStore::cookiesDidChange()
194 {
195     for (auto* observer : m_observers)
196         observer->cookiesDidChange(*this);
197 }
198
199 void HTTPCookieStore::cookieManagerDestroyed()
200 {
201     m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
202     m_observedCookieManagerProxy = nullptr;
203
204     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
205
206     if (!pool)
207         return;
208
209     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
210     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
211 }
212
213 void HTTPCookieStore::registerForNewProcessPoolNotifications()
214 {
215     ASSERT(!m_processPoolCreationListenerIdentifier);
216
217     m_processPoolCreationListenerIdentifier = WebProcessPool::registerProcessPoolCreationListener([this](WebProcessPool& newProcessPool) {
218         if (!m_owningDataStore->isAssociatedProcessPool(newProcessPool))
219             return;
220
221         // Now that an associated process pool exists, we need to flush the UI process cookie store
222         // to make sure any changes are reflected within the new process pool.
223         flushDefaultUIProcessCookieStore();
224         newProcessPool.ensureNetworkProcess();
225
226         if (m_cookieManagerProxyObserver) {
227             m_observedCookieManagerProxy = newProcessPool.supplement<WebKit::WebCookieManagerProxy>();
228             m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
229         }
230         unregisterForNewProcessPoolNotifications();
231     });
232 }
233
234 void HTTPCookieStore::unregisterForNewProcessPoolNotifications()
235 {
236     if (m_processPoolCreationListenerIdentifier)
237         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
238
239     m_processPoolCreationListenerIdentifier = 0;
240 }
241
242 #if !PLATFORM(COCOA)
243 void HTTPCookieStore::flushDefaultUIProcessCookieStore() { }
244 Vector<WebCore::Cookie> HTTPCookieStore::getAllDefaultUIProcessCookieStoreCookies() { return { }; }
245 void HTTPCookieStore::setCookieInDefaultUIProcessCookieStore(const WebCore::Cookie&) { }
246 void HTTPCookieStore::deleteCookieFromDefaultUIProcessCookieStore(const WebCore::Cookie&) { }
247 void HTTPCookieStore::startObservingChangesToDefaultUIProcessCookieStore(Function<void()>&&) { }
248 void HTTPCookieStore::stopObservingChangesToDefaultUIProcessCookieStore() { }
249 #endif
250     
251 } // namespace API