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 = 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 | 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 |
252 | |