[iOS] TestWebKitAPI.WebKit.WKHTTPCookieStoreWithoutProcessPool fails because cookies...
[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(WebsiteDataStore& websiteDataStore)
41     : m_owningDataStore(websiteDataStore.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     ASSERT(!m_observingUIProcessCookies);
53
54     unregisterForNewProcessPoolNotifications();
55 }
56
57 void HTTPCookieStore::cookies(Function<void(const Vector<WebCore::Cookie>&)>&& completionHandler)
58 {
59     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
60     if (!pool) {
61         Vector<WebCore::Cookie> allCookies;
62         if (m_owningDataStore->sessionID() == PAL::SessionID::defaultSessionID())
63             allCookies = WebCore::NetworkStorageSession::defaultStorageSession().getAllCookies();
64         allCookies.appendVector(m_owningDataStore->pendingCookies());
65
66         callOnMainThread([completionHandler = WTFMove(completionHandler), allCookies]() {
67             completionHandler(allCookies);
68         });
69         return;
70     }
71
72     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
73     cookieManager->getAllCookies(m_owningDataStore->sessionID(), [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)](const Vector<WebCore::Cookie>& cookies, CallbackBase::Error error) {
74         completionHandler(cookies);
75     });
76 }
77
78 void HTTPCookieStore::setCookie(const WebCore::Cookie& cookie, Function<void ()>&& completionHandler)
79 {
80     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
81     if (!pool) {
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             WebCore::NetworkStorageSession::defaultStorageSession().setCookie(cookie);
85         else
86             m_owningDataStore->addPendingCookie(cookie);
87
88         callOnMainThread([completionHandler = WTFMove(completionHandler)]() {
89             completionHandler();
90         });
91         return;
92     }
93
94     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
95     cookieManager->setCookie(m_owningDataStore->sessionID(), cookie, [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)](CallbackBase::Error error) {
96         completionHandler();
97     });
98 }
99
100 void HTTPCookieStore::deleteCookie(const WebCore::Cookie& cookie, Function<void ()>&& completionHandler)
101 {
102     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
103     if (!pool) {
104         if (m_owningDataStore->sessionID() == PAL::SessionID::defaultSessionID() && !cookie.session)
105             WebCore::NetworkStorageSession::defaultStorageSession().deleteCookie(cookie);
106         else
107             m_owningDataStore->removePendingCookie(cookie);
108
109         callOnMainThread([completionHandler = WTFMove(completionHandler)]() {
110             completionHandler();
111         });
112         return;
113     }
114
115     auto* cookieManager = pool->supplement<WebKit::WebCookieManagerProxy>();
116     cookieManager->deleteCookie(m_owningDataStore->sessionID(), cookie, [pool = WTFMove(pool), completionHandler = WTFMove(completionHandler)](CallbackBase::Error error) {
117         completionHandler();
118     });
119 }
120
121 class APIWebCookieManagerProxyObserver : public WebCookieManagerProxy::Observer {
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 = std::make_unique<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         WebCore::startObservingCookieChanges(WebCore::NetworkStorageSession::defaultStorageSession(), [this] () {
160             cookiesDidChange();
161         });
162
163         m_observingUIProcessCookies = true;
164
165         return;
166     }
167
168     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
169     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
170 }
171
172 void HTTPCookieStore::unregisterObserver(Observer& observer)
173 {
174     m_observers.remove(&observer);
175
176     if (!m_observers.isEmpty())
177         return;
178
179     if (m_observedCookieManagerProxy)
180         m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
181
182     if (m_observingUIProcessCookies)
183         WebCore::stopObservingCookieChanges(WebCore::NetworkStorageSession::defaultStorageSession());
184
185     if (m_processPoolCreationListenerIdentifier)
186         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
187
188     m_processPoolCreationListenerIdentifier = 0;
189     m_observedCookieManagerProxy = nullptr;
190     m_cookieManagerProxyObserver = nullptr;
191     m_observingUIProcessCookies = false;
192 }
193
194 void HTTPCookieStore::cookiesDidChange()
195 {
196     for (auto* observer : m_observers)
197         observer->cookiesDidChange(*this);
198 }
199
200 void HTTPCookieStore::cookieManagerDestroyed()
201 {
202     m_observedCookieManagerProxy->unregisterObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
203     m_observedCookieManagerProxy = nullptr;
204
205     auto* pool = m_owningDataStore->processPoolForCookieStorageOperations();
206
207     if (!pool)
208         return;
209
210     m_observedCookieManagerProxy = pool->supplement<WebKit::WebCookieManagerProxy>();
211     m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
212 }
213
214 void HTTPCookieStore::registerForNewProcessPoolNotifications()
215 {
216     ASSERT(!m_processPoolCreationListenerIdentifier);
217
218     m_processPoolCreationListenerIdentifier = WebProcessPool::registerProcessPoolCreationListener([this](WebProcessPool& newProcessPool) {
219         if (!m_owningDataStore->isAssociatedProcessPool(newProcessPool))
220             return;
221
222         // Now that an associated process pool exists, we need to flush the UI process cookie store
223         // to make sure any changes are reflected within the new process pool.
224         WebCore::NetworkStorageSession::defaultStorageSession().flushCookieStore();
225         newProcessPool.ensureNetworkProcess();
226
227         if (m_cookieManagerProxyObserver) {
228             m_observedCookieManagerProxy = newProcessPool.supplement<WebKit::WebCookieManagerProxy>();
229             m_observedCookieManagerProxy->registerObserver(m_owningDataStore->sessionID(), *m_cookieManagerProxyObserver);
230         }
231         unregisterForNewProcessPoolNotifications();
232     });
233 }
234
235 void HTTPCookieStore::unregisterForNewProcessPoolNotifications()
236 {
237     if (m_processPoolCreationListenerIdentifier)
238         WebProcessPool::unregisterProcessPoolCreationListener(m_processPoolCreationListenerIdentifier);
239
240     m_processPoolCreationListenerIdentifier = 0;
241 }
242
243 } // namespace API