Bundle unified sources more tightly in projects with deep directory structures
[WebKit-https.git] / Source / WebKit / UIProcess / Storage / StorageProcessProxy.cpp
1 /*
2  * Copyright (C) 2013-2018 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 "StorageProcessProxy.h"
28
29 #include "NetworkProcessMessages.h"
30 #include "ServiceWorkerProcessProxy.h"
31 #include "StorageProcessMessages.h"
32 #include "StorageProcessProxyMessages.h"
33 #include "WebProcessPool.h"
34 #include "WebsiteData.h"
35 #include <WebCore/NotImplemented.h>
36
37 namespace WebKit {
38 using namespace WebCore;
39
40 static uint64_t generateStorageProcessCallbackID()
41 {
42     static uint64_t callbackID;
43
44     return ++callbackID;
45 }
46
47 Ref<StorageProcessProxy> StorageProcessProxy::create(WebProcessPool& processPool)
48 {
49     return adoptRef(*new StorageProcessProxy(processPool));
50 }
51
52 StorageProcessProxy::StorageProcessProxy(WebProcessPool& processPool)
53     : ChildProcessProxy(processPool.alwaysRunsAtBackgroundPriority())
54     , m_processPool(processPool)
55     , m_numPendingConnectionRequests(0)
56 {
57     connect();
58 }
59
60 StorageProcessProxy::~StorageProcessProxy()
61 {
62     ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
63     ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
64     ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
65 }
66
67 void StorageProcessProxy::terminateForTesting()
68 {
69     for (auto& callback : m_pendingFetchWebsiteDataCallbacks.values())
70         callback({ });
71
72     for (auto& callback : m_pendingDeleteWebsiteDataCallbacks.values())
73         callback();
74
75     for (auto& callback : m_pendingDeleteWebsiteDataForOriginsCallbacks.values())
76         callback();
77     
78     m_pendingFetchWebsiteDataCallbacks.clear();
79     m_pendingDeleteWebsiteDataCallbacks.clear();
80     m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
81     
82     terminate();
83 }
84
85 void StorageProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
86 {
87     launchOptions.processType = ProcessLauncher::ProcessType::Storage;
88     ChildProcessProxy::getLaunchOptions(launchOptions);
89 }
90
91 void StorageProcessProxy::processWillShutDown(IPC::Connection& connection)
92 {
93     ASSERT_UNUSED(connection, this->connection() == &connection);
94 }
95
96 void StorageProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
97 {
98     if (decoder.messageReceiverName() == Messages::StorageProcessProxy::messageReceiverName()) {
99         didReceiveStorageProcessProxyMessage(connection, decoder);
100         return;
101     }
102 }
103
104 void StorageProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, CompletionHandler<void (WebsiteData)>&& completionHandler)
105 {
106     ASSERT(canSendMessage());
107
108     uint64_t callbackID = generateStorageProcessCallbackID();
109     m_pendingFetchWebsiteDataCallbacks.add(callbackID, WTFMove(completionHandler));
110
111     send(Messages::StorageProcess::FetchWebsiteData(sessionID, dataTypes, callbackID), 0);
112 }
113
114 void StorageProcessProxy::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, CompletionHandler<void ()>&& completionHandler)
115 {
116     auto callbackID = generateStorageProcessCallbackID();
117
118     m_pendingDeleteWebsiteDataCallbacks.add(callbackID, WTFMove(completionHandler));
119     send(Messages::StorageProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
120 }
121
122 void StorageProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
123 {
124     ASSERT(canSendMessage());
125
126     uint64_t callbackID = generateStorageProcessCallbackID();
127     m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, WTFMove(completionHandler));
128
129     send(Messages::StorageProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, callbackID), 0);
130 }
131
132 void StorageProcessProxy::getStorageProcessConnection(WebProcessProxy& webProcessProxy, Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply&& reply)
133 {
134     m_pendingConnectionReplies.append(WTFMove(reply));
135
136     if (state() == State::Launching) {
137         m_numPendingConnectionRequests++;
138         return;
139     }
140
141     bool isServiceWorkerProcess = false;
142     SecurityOriginData securityOrigin;
143 #if ENABLE(SERVICE_WORKER)
144     if (is<ServiceWorkerProcessProxy>(webProcessProxy)) {
145         isServiceWorkerProcess = true;
146         securityOrigin = downcast<ServiceWorkerProcessProxy>(webProcessProxy).securityOrigin();
147     }
148 #endif
149
150     send(Messages::StorageProcess::CreateStorageToWebProcessConnection(isServiceWorkerProcess, securityOrigin), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
151 }
152
153 void StorageProcessProxy::didClose(IPC::Connection&)
154 {
155     auto protectedProcessPool = makeRef(m_processPool);
156
157     // The storage process must have crashed or exited, so send any pending sync replies we might have.
158     while (!m_pendingConnectionReplies.isEmpty()) {
159         auto reply = m_pendingConnectionReplies.takeFirst();
160
161 #if USE(UNIX_DOMAIN_SOCKETS)
162         reply(IPC::Attachment());
163 #elif OS(DARWIN)
164         reply(IPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
165 #elif OS(WINDOWS)
166         reply(IPC::Attachment());
167 #else
168         notImplemented();
169 #endif
170     }
171
172     while (!m_pendingFetchWebsiteDataCallbacks.isEmpty())
173         m_pendingFetchWebsiteDataCallbacks.take(m_pendingFetchWebsiteDataCallbacks.begin()->key)(WebsiteData { });
174
175     while (!m_pendingDeleteWebsiteDataCallbacks.isEmpty())
176         m_pendingDeleteWebsiteDataCallbacks.take(m_pendingDeleteWebsiteDataCallbacks.begin()->key)();
177
178     while (!m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty())
179         m_pendingDeleteWebsiteDataForOriginsCallbacks.take(m_pendingDeleteWebsiteDataForOriginsCallbacks.begin()->key)();
180
181     // Tell ProcessPool to forget about this storage process. This may cause us to be deleted.
182     m_processPool.storageProcessCrashed(this);
183 }
184
185 void StorageProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
186 {
187 }
188
189 void StorageProcessProxy::didCreateStorageToWebProcessConnection(const IPC::Attachment& connectionIdentifier)
190 {
191     ASSERT(!m_pendingConnectionReplies.isEmpty());
192
193     auto reply = m_pendingConnectionReplies.takeFirst();
194
195 #if USE(UNIX_DOMAIN_SOCKETS)
196     reply(connectionIdentifier);
197 #elif OS(DARWIN)
198     reply(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
199 #elif OS(WINDOWS)
200     reply(connectionIdentifier.handle());
201 #else
202     notImplemented();
203 #endif
204 }
205
206 void StorageProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
207 {
208     auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
209     callback(websiteData);
210 }
211
212 void StorageProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
213 {
214     auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
215     callback();
216 }
217
218 void StorageProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
219 {
220     auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
221     callback();
222 }
223
224 #if ENABLE(SANDBOX_EXTENSIONS)
225 void StorageProcessProxy::getSandboxExtensionsForBlobFiles(uint64_t requestID, const Vector<String>& paths)
226 {
227     SandboxExtension::HandleArray extensions;
228     extensions.allocate(paths.size());
229     for (size_t i = 0; i < paths.size(); ++i) {
230         // ReadWrite is required for creating hard links, which is something that might be done with these extensions.
231         SandboxExtension::createHandle(paths[i], SandboxExtension::Type::ReadWrite, extensions[i]);
232     }
233
234     send(Messages::StorageProcess::DidGetSandboxExtensionsForBlobFiles(requestID, extensions), 0);
235 }
236 #endif
237
238 void StorageProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
239 {
240     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
241
242     if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
243         // FIXME: Do better cleanup here.
244         return;
245     }
246
247     for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
248         send(Messages::StorageProcess::CreateStorageToWebProcessConnection(false, { }), 0);
249     
250     m_numPendingConnectionRequests = 0;
251 }
252
253 #if ENABLE(SERVICE_WORKER)
254 void StorageProcessProxy::establishWorkerContextConnectionToStorageProcess(SecurityOriginData&& origin)
255 {
256     m_processPool.establishWorkerContextConnectionToStorageProcess(*this, WTFMove(origin), std::nullopt);
257 }
258
259 void StorageProcessProxy::establishWorkerContextConnectionToStorageProcessForExplicitSession(SecurityOriginData&& origin, PAL::SessionID sessionID)
260 {
261     m_processPool.establishWorkerContextConnectionToStorageProcess(*this, WTFMove(origin), sessionID);
262 }
263 #endif
264
265 } // namespace WebKit