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 "WebOriginDataManagerProxy.h"
28
29#include "SecurityOriginData.h"
30#include "WebContext.h"
31#include "WebOriginDataManagerMessages.h"
32#include "WebOriginDataManagerProxyMessages.h"
33#include "WebSecurityOrigin.h"
34#include <WebCore/SecurityOrigin.h>
35#include <wtf/NeverDestroyed.h>
36
37using namespace WebCore;
38
39namespace WebKit {
40
41const char* WebOriginDataManagerProxy::supplementName()
42{
43    return "WebOriginDataManagerProxy";
44}
45
46PassRefPtr<WebOriginDataManagerProxy> WebOriginDataManagerProxy::create(WebContext* context)
47{
48    return adoptRef(new WebOriginDataManagerProxy(context));
49}
50
51WebOriginDataManagerProxy::WebOriginDataManagerProxy(WebContext* context)
52    : WebContextSupplement(context)
53{
54    context->addMessageReceiver(Messages::WebOriginDataManagerProxy::messageReceiverName(), *this);
55}
56
57WebOriginDataManagerProxy::~WebOriginDataManagerProxy()
58{
59}
60
61
62void WebOriginDataManagerProxy::contextDestroyed()
63{
64    invalidateCallbackMap(m_arrayCallbacks, CallbackBase::Error::OwnerWasInvalidated);
65}
66
67void WebOriginDataManagerProxy::processDidClose(WebProcessProxy*)
68{
69    invalidateCallbackMap(m_arrayCallbacks, CallbackBase::Error::ProcessExited);
70}
71
72bool WebOriginDataManagerProxy::shouldTerminate(WebProcessProxy*) const
73{
74    return m_arrayCallbacks.isEmpty();
75}
76
77void WebOriginDataManagerProxy::refWebContextSupplement()
78{
79    API::Object::ref();
80}
81
82void WebOriginDataManagerProxy::derefWebContextSupplement()
83{
84    API::Object::deref();
85}
86
87void WebOriginDataManagerProxy::getOrigins(WKOriginDataTypes types, std::function<void (API::Array*, CallbackBase::Error)> callbackFunction)
88{
89    // FIXME: Right now we only support IndexedDatabase data so we know that we're only sending this request to the DatabaseProcess.
90    // That's why having one single callback works.
91    // In the future when we message N-processes we'll have to wait for all N replies before responding to the client.
92    if (!(types & kWKIndexedDatabaseData)) {
93        callbackFunction(nullptr, CallbackBase::Error::None);
94        return;
95    }
96
97    RefPtr<ArrayCallback> callback = ArrayCallback::create(WTF::move(callbackFunction));
98
99    if (!context()) {
100        callback->invalidate();
101        return;
102    }
103
104    uint64_t callbackID = callback->callbackID();
105    m_arrayCallbacks.set(callbackID, callback.release());
106
107    context()->sendToDatabaseProcessRelaunchingIfNecessary(Messages::WebOriginDataManager::GetOrigins(types, callbackID));
108}
109
110void WebOriginDataManagerProxy::didGetOrigins(IPC::Connection* connection, const Vector<SecurityOriginData>& originIdentifiers, uint64_t callbackID)
111{
112    RefPtr<ArrayCallback> callback = m_arrayCallbacks.take(callbackID);
113    MESSAGE_CHECK_BASE(callback, connection);
114
115    Vector<RefPtr<API::Object>> securityOrigins;
116    securityOrigins.reserveInitialCapacity(originIdentifiers.size());
117
118    for (const auto& originIdentifier : originIdentifiers)
119        securityOrigins.uncheckedAppend(WebSecurityOrigin::create(originIdentifier.securityOrigin()));
120
121    callback->performCallbackWithReturnValue(API::Array::create(WTF::move(securityOrigins)).get());
122}
123
124void WebOriginDataManagerProxy::deleteEntriesForOrigin(WKOriginDataTypes types, WebSecurityOrigin* origin, std::function<void (CallbackBase::Error)> callbackFunction)
125{
126    // FIXME: Right now we only support IndexedDatabase data so we know that we're only sending this request to the DatabaseProcess.
127    // That's why having one single callback works.
128    // In the future when we message N-processes we'll have to wait for all N replies before responding to the client.
129    if (!(types & kWKIndexedDatabaseData)) {
130        callbackFunction(CallbackBase::Error::None);
131        return;
132    }
133
134    RefPtr<VoidCallback> callback = VoidCallback::create(WTF::move(callbackFunction));
135
136    if (!context()) {
137        callback->invalidate();
138        return;
139    }
140
141    uint64_t callbackID = callback->callbackID();
142    m_voidCallbacks.set(callbackID, callback.release());
143
144    SecurityOriginData securityOriginData;
145    securityOriginData.protocol = origin->securityOrigin().protocol();
146    securityOriginData.host = origin->securityOrigin().host();
147    securityOriginData.port = origin->securityOrigin().port();
148
149    context()->sendToDatabaseProcessRelaunchingIfNecessary(Messages::WebOriginDataManager::DeleteEntriesForOrigin(types, securityOriginData, callbackID));
150}
151
152void WebOriginDataManagerProxy::deleteEntriesModifiedBetweenDates(WKOriginDataTypes types, double startDate, double endDate, std::function<void (CallbackBase::Error)> callbackFunction)
153{
154    // FIXME: Right now we only support IndexedDatabase data so we know that we're only sending this request to the DatabaseProcess.
155    // That's why having one single callback works.
156    // In the future when we message N-processes we'll have to wait for all N replies before responding to the client.
157    if (!(types & kWKIndexedDatabaseData)) {
158        callbackFunction(CallbackBase::Error::None);
159        return;
160    }
161
162    RefPtr<VoidCallback> callback = VoidCallback::create(WTF::move(callbackFunction));
163
164    if (!context()) {
165        callback->invalidate();
166        return;
167    }
168
169    uint64_t callbackID = callback->callbackID();
170    m_voidCallbacks.set(callbackID, callback.release());
171
172    context()->sendToDatabaseProcessRelaunchingIfNecessary(Messages::WebOriginDataManager::DeleteEntriesModifiedBetweenDates(types, startDate, endDate, callbackID));
173}
174
175void WebOriginDataManagerProxy::didDeleteEntries(IPC::Connection* connection, uint64_t callbackID)
176{
177    RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
178    MESSAGE_CHECK_BASE(callback, connection);
179    callback->performCallback();
180}
181
182void WebOriginDataManagerProxy::deleteAllEntries(WKOriginDataTypes types, std::function<void (CallbackBase::Error)> callbackFunction)
183{
184    // FIXME: Right now we only support IndexedDatabase data so we know that we're only sending this request to the DatabaseProcess.
185    // That's why having one single callback works.
186    // In the future when we message N-processes we'll have to wait for all N replies before responding to the client.
187    if (!(types & kWKIndexedDatabaseData)) {
188        callbackFunction(CallbackBase::Error::None);
189        return;
190    }
191
192    RefPtr<VoidCallback> callback = VoidCallback::create(WTF::move(callbackFunction));
193
194    if (!context()) {
195        callback->invalidate();
196        return;
197    }
198
199    uint64_t callbackID = callback->callbackID();
200    m_voidCallbacks.set(callbackID, callback.release());
201
202    context()->sendToDatabaseProcessRelaunchingIfNecessary(Messages::WebOriginDataManager::DeleteAllEntries(types, callbackID));
203}
204
205void WebOriginDataManagerProxy::didDeleteAllEntries(IPC::Connection* connection, uint64_t callbackID)
206{
207    RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
208    MESSAGE_CHECK_BASE(callback, connection);
209    callback->performCallback();
210}
211
212} // namespace WebKit
213