1/*
2 * Copyright (C) 2011, 2013 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 "WebCookieManagerProxy.h"
28
29#include "APIArray.h"
30#include "APISecurityOrigin.h"
31#include "NetworkProcessMessages.h"
32#include "OptionalCallbackID.h"
33#include "WebCookieManagerMessages.h"
34#include "WebCookieManagerProxyMessages.h"
35#include "WebProcessPool.h"
36#include <WebCore/Cookie.h>
37#include <WebCore/SecurityOriginData.h>
38
39namespace WebKit {
40using namespace WebCore;
41
42const char* WebCookieManagerProxy::supplementName()
43{
44 return "WebCookieManagerProxy";
45}
46
47Ref<WebCookieManagerProxy> WebCookieManagerProxy::create(WebProcessPool* processPool)
48{
49 return adoptRef(*new WebCookieManagerProxy(processPool));
50}
51
52WebCookieManagerProxy::WebCookieManagerProxy(WebProcessPool* processPool)
53 : WebContextSupplement(processPool)
54{
55 WebContextSupplement::processPool()->addMessageReceiver(Messages::WebCookieManagerProxy::messageReceiverName(), *this);
56}
57
58WebCookieManagerProxy::~WebCookieManagerProxy()
59{
60 ASSERT(m_cookieObservers.isEmpty());
61}
62
63void WebCookieManagerProxy::initializeClient(const WKCookieManagerClientBase* client)
64{
65 m_client.initialize(client);
66}
67
68// WebContextSupplement
69
70void WebCookieManagerProxy::processPoolDestroyed()
71{
72 m_callbacks.invalidate(CallbackBase::Error::OwnerWasInvalidated);
73
74 Vector<Observer*> observers;
75 for (auto& observerSet : m_cookieObservers.values()) {
76 for (auto* observer : observerSet)
77 observers.append(observer);
78 }
79
80 for (auto* observer : observers)
81 observer->managerDestroyed();
82
83 ASSERT(m_cookieObservers.isEmpty());
84}
85
86void WebCookieManagerProxy::processDidClose(WebProcessProxy*)
87{
88 m_callbacks.invalidate(CallbackBase::Error::ProcessExited);
89}
90
91void WebCookieManagerProxy::processDidClose(NetworkProcessProxy*)
92{
93 m_callbacks.invalidate(CallbackBase::Error::ProcessExited);
94}
95
96void WebCookieManagerProxy::refWebContextSupplement()
97{
98 API::Object::ref();
99}
100
101void WebCookieManagerProxy::derefWebContextSupplement()
102{
103 API::Object::deref();
104}
105
106void WebCookieManagerProxy::getHostnamesWithCookies(PAL::SessionID sessionID, Function<void (API::Array*, CallbackBase::Error)>&& callbackFunction)
107{
108 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
109 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::GetHostnamesWithCookies(sessionID, callbackID));
110}
111
112void WebCookieManagerProxy::didGetHostnamesWithCookies(const Vector<String>& hostnames, WebKit::CallbackID callbackID)
113{
114 auto callback = m_callbacks.take<ArrayCallback>(callbackID);
115 if (!callback) {
116 // FIXME: Log error or assert.
117 return;
118 }
119
120 callback->performCallbackWithReturnValue(API::Array::createStringArray(hostnames).ptr());
121}
122
123void WebCookieManagerProxy::deleteCookiesForHostnames(PAL::SessionID sessionID, const Vector<String>& hostnames)
124{
125 processPool()->sendToNetworkingProcessRelaunchingIfNecessary(Messages::WebCookieManager::DeleteCookiesForHostnames(sessionID, hostnames));
126}
127
128void WebCookieManagerProxy::deleteAllCookies(PAL::SessionID sessionID)
129{
130 processPool()->sendToNetworkingProcessRelaunchingIfNecessary(Messages::WebCookieManager::DeleteAllCookies(sessionID));
131}
132
133void WebCookieManagerProxy::deleteCookie(PAL::SessionID sessionID, const Cookie& cookie, Function<void (CallbackBase::Error)>&& callbackFunction)
134{
135 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
136 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::DeleteCookie(sessionID, cookie, callbackID));
137}
138
139void WebCookieManagerProxy::deleteAllCookiesModifiedSince(PAL::SessionID sessionID, WallTime time, Function<void (CallbackBase::Error)>&& callbackFunction)
140{
141 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
142 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::DeleteAllCookiesModifiedSince(sessionID, time, callbackID));
143}
144
145void WebCookieManagerProxy::setCookies(PAL::SessionID sessionID, const Vector<Cookie>& cookies, Function<void(CallbackBase::Error)>&& callbackFunction)
146{
147 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
148 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::SetCookie(sessionID, cookies, callbackID));
149}
150
151void WebCookieManagerProxy::setCookies(PAL::SessionID sessionID, const Vector<Cookie>& cookies, const URL& url, const URL& mainDocumentURL, Function<void (CallbackBase::Error)>&& callbackFunction)
152{
153 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
154 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::SetCookies(sessionID, cookies, url, mainDocumentURL, callbackID));
155}
156
157void WebCookieManagerProxy::getAllCookies(PAL::SessionID sessionID, Function<void (const Vector<Cookie>&, CallbackBase::Error)>&& callbackFunction)
158{
159 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
160 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::GetAllCookies(sessionID, callbackID));
161}
162
163void WebCookieManagerProxy::getCookies(PAL::SessionID sessionID, const URL& url, Function<void (const Vector<Cookie>&, CallbackBase::Error)>&& callbackFunction)
164{
165 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
166 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::GetCookies(sessionID, url, callbackID));
167}
168
169void WebCookieManagerProxy::didSetCookies(WebKit::CallbackID callbackID)
170{
171 m_callbacks.take<VoidCallback>(callbackID)->performCallback();
172}
173
174void WebCookieManagerProxy::didGetCookies(const Vector<Cookie>& cookies, WebKit::CallbackID callbackID)
175{
176 m_callbacks.take<GetCookiesCallback>(callbackID)->performCallbackWithReturnValue(cookies);
177}
178
179void WebCookieManagerProxy::didDeleteCookies(WebKit::CallbackID callbackID)
180{
181 m_callbacks.take<VoidCallback>(callbackID)->performCallback();
182}
183
184void WebCookieManagerProxy::startObservingCookieChanges(PAL::SessionID sessionID)
185{
186 processPool()->sendToNetworkingProcessRelaunchingIfNecessary(Messages::WebCookieManager::StartObservingCookieChanges(sessionID));
187}
188
189void WebCookieManagerProxy::stopObservingCookieChanges(PAL::SessionID sessionID)
190{
191 processPool()->sendToNetworkingProcessRelaunchingIfNecessary(Messages::WebCookieManager::StopObservingCookieChanges(sessionID));
192}
193
194
195void WebCookieManagerProxy::setCookieObserverCallback(PAL::SessionID sessionID, WTF::Function<void ()>&& callback)
196{
197 if (callback)
198 m_legacyCookieObservers.set(sessionID, WTFMove(callback));
199 else
200 m_legacyCookieObservers.remove(sessionID);
201}
202
203void WebCookieManagerProxy::registerObserver(PAL::SessionID sessionID, Observer& observer)
204{
205 auto result = m_cookieObservers.set(sessionID, HashSet<Observer*>());
206 result.iterator->value.add(&observer);
207
208 if (result.isNewEntry)
209 startObservingCookieChanges(sessionID);
210}
211
212void WebCookieManagerProxy::unregisterObserver(PAL::SessionID sessionID, Observer& observer)
213{
214 auto iterator = m_cookieObservers.find(sessionID);
215 if (iterator == m_cookieObservers.end())
216 return;
217
218 iterator->value.remove(&observer);
219 if (!iterator->value.isEmpty())
220 return;
221
222 m_cookieObservers.remove(iterator);
223 stopObservingCookieChanges(sessionID);
224}
225
226void WebCookieManagerProxy::cookiesDidChange(PAL::SessionID sessionID)
227{
228 m_client.cookiesDidChange(this);
229 auto legacyIterator = m_legacyCookieObservers.find(sessionID);
230 if (legacyIterator != m_legacyCookieObservers.end())
231 ((*legacyIterator).value)();
232
233 auto iterator = m_cookieObservers.find(sessionID);
234 if (iterator == m_cookieObservers.end())
235 return;
236
237 for (auto* observer : iterator->value)
238 observer->cookiesDidChange();
239}
240
241void WebCookieManagerProxy::setHTTPCookieAcceptPolicy(PAL::SessionID, HTTPCookieAcceptPolicy policy, Function<void (CallbackBase::Error)>&& callbackFunction)
242{
243#if PLATFORM(COCOA)
244 if (!processPool()->isUsingTestingNetworkSession())
245 persistHTTPCookieAcceptPolicy(policy);
246#endif
247#if USE(SOUP)
248 processPool()->setInitialHTTPCookieAcceptPolicy(policy);
249#endif
250
251 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
252 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::SetHTTPCookieAcceptPolicy(policy, OptionalCallbackID(callbackID)));
253}
254
255void WebCookieManagerProxy::getHTTPCookieAcceptPolicy(PAL::SessionID, Function<void (HTTPCookieAcceptPolicy, CallbackBase::Error)>&& callbackFunction)
256{
257 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), processPool()->ensureNetworkProcess().throttler().backgroundActivityToken());
258 processPool()->sendToNetworkingProcess(Messages::WebCookieManager::GetHTTPCookieAcceptPolicy(callbackID));
259}
260
261void WebCookieManagerProxy::didGetHTTPCookieAcceptPolicy(uint32_t policy, WebKit::CallbackID callbackID)
262{
263 m_callbacks.take<HTTPCookieAcceptPolicyCallback>(callbackID)->performCallbackWithReturnValue(policy);
264}
265
266void WebCookieManagerProxy::didSetHTTPCookieAcceptPolicy(WebKit::CallbackID callbackID)
267{
268 m_callbacks.take<VoidCallback>(callbackID)->performCallback();
269}
270
271void WebCookieManagerProxy::setStorageAccessAPIEnabled(bool enabled)
272{
273#if PLATFORM(COCOA)
274 processPool()->sendToNetworkingProcess(Messages::NetworkProcess::SetStorageAccessAPIEnabled(enabled));
275#else
276 UNUSED_PARAM(enabled);
277#endif
278}
279
280} // namespace WebKit
281