Use auto for some of our lambda function parameters
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / NetworkConnectionToWebProcess.cpp
1 /*
2  * Copyright (C) 2012-2016 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 "NetworkConnectionToWebProcess.h"
28
29 #include "BlobDataFileReferenceWithSandboxExtension.h"
30 #include "NetworkBlobRegistry.h"
31 #include "NetworkConnectionToWebProcessMessages.h"
32 #include "NetworkLoad.h"
33 #include "NetworkProcess.h"
34 #include "NetworkProcessConnectionMessages.h"
35 #include "NetworkResourceLoadParameters.h"
36 #include "NetworkResourceLoader.h"
37 #include "NetworkResourceLoaderMessages.h"
38 #include "RemoteNetworkingContext.h"
39 #include "SessionTracker.h"
40 #include "WebCoreArgumentCoders.h"
41 #include <WebCore/NotImplemented.h>
42 #include <WebCore/PingHandle.h>
43 #include <WebCore/PlatformCookieJar.h>
44 #include <WebCore/ResourceLoaderOptions.h>
45 #include <WebCore/ResourceRequest.h>
46 #include <WebCore/SessionID.h>
47 #include <wtf/RunLoop.h>
48
49 #if USE(NETWORK_SESSION)
50 #include "PingLoad.h"
51 #endif
52
53 using namespace WebCore;
54
55 namespace WebKit {
56
57 Ref<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(IPC::Connection::Identifier connectionIdentifier)
58 {
59     return adoptRef(*new NetworkConnectionToWebProcess(connectionIdentifier));
60 }
61
62 NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(IPC::Connection::Identifier connectionIdentifier)
63 {
64     m_connection = IPC::Connection::createServerConnection(connectionIdentifier, *this);
65     m_connection->open();
66 }
67
68 NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess()
69 {
70 }
71
72 void NetworkConnectionToWebProcess::didCleanupResourceLoader(NetworkResourceLoader& loader)
73 {
74     ASSERT(m_networkResourceLoaders.get(loader.identifier()) == &loader);
75
76     m_networkResourceLoaders.remove(loader.identifier());
77 }
78     
79 void NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
80 {
81     if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
82         didReceiveNetworkConnectionToWebProcessMessage(connection, decoder);
83         return;
84     }
85
86     if (decoder.messageReceiverName() == Messages::NetworkResourceLoader::messageReceiverName()) {
87         HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator loaderIterator = m_networkResourceLoaders.find(decoder.destinationID());
88         if (loaderIterator != m_networkResourceLoaders.end())
89             loaderIterator->value->didReceiveNetworkResourceLoaderMessage(connection, decoder);
90         return;
91     }
92     
93     ASSERT_NOT_REACHED();
94 }
95
96 void NetworkConnectionToWebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& reply)
97 {
98     if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
99         didReceiveSyncNetworkConnectionToWebProcessMessage(connection, decoder, reply);
100         return;
101     }
102     ASSERT_NOT_REACHED();
103 }
104
105 void NetworkConnectionToWebProcess::didClose(IPC::Connection&)
106 {
107     // Protect ourself as we might be otherwise be deleted during this function.
108     Ref<NetworkConnectionToWebProcess> protector(*this);
109
110     Vector<RefPtr<NetworkResourceLoader>> loaders;
111     copyValuesToVector(m_networkResourceLoaders, loaders);
112     for (auto& loader : loaders)
113         loader->abort();
114     ASSERT(m_networkResourceLoaders.isEmpty());
115
116     NetworkBlobRegistry::singleton().connectionToWebProcessDidClose(this);
117     NetworkProcess::singleton().removeNetworkConnectionToWebProcess(this);
118 }
119
120 void NetworkConnectionToWebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
121 {
122 }
123
124 void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters)
125 {
126     auto loader = NetworkResourceLoader::create(loadParameters, *this);
127     m_networkResourceLoaders.add(loadParameters.identifier, loader.ptr());
128     loader->start();
129 }
130
131 void NetworkConnectionToWebProcess::performSynchronousLoad(const NetworkResourceLoadParameters& loadParameters, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply)
132 {
133     auto loader = NetworkResourceLoader::create(loadParameters, *this, WTFMove(reply));
134     m_networkResourceLoaders.add(loadParameters.identifier, loader.ptr());
135     loader->start();
136 }
137
138 void NetworkConnectionToWebProcess::loadPing(const NetworkResourceLoadParameters& loadParameters)
139 {
140 #if USE(NETWORK_SESSION)
141     // PingLoad manages its own lifetime, deleting itself when its purpose has been fulfilled.
142     new PingLoad(loadParameters);
143 #else
144     RefPtr<NetworkingContext> context = RemoteNetworkingContext::create(loadParameters.sessionID, loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect);
145
146     // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled.
147     new PingHandle(context.get(), loadParameters.request, loadParameters.allowStoredCredentials == AllowStoredCredentials, PingHandle::UsesAsyncCallbacks::Yes);
148 #endif
149 }
150
151 void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier)
152 {
153     RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier);
154
155     // It's possible we have no loader for this identifier if the NetworkProcess crashed and this was a respawned NetworkProcess.
156     if (!loader)
157         return;
158
159     // Abort the load now, as the WebProcess won't be able to respond to messages any more which might lead
160     // to leaked loader resources (connections, threads, etc).
161     loader->abort();
162     ASSERT(!m_networkResourceLoaders.contains(identifier));
163 }
164
165 void NetworkConnectionToWebProcess::setDefersLoading(ResourceLoadIdentifier identifier, bool defers)
166 {
167     RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier);
168     if (!loader)
169         return;
170
171     loader->setDefersLoading(defers);
172 }
173
174 void NetworkConnectionToWebProcess::prefetchDNS(const String& hostname)
175 {
176     NetworkProcess::singleton().prefetchDNS(hostname);
177 }
178
179 static NetworkStorageSession& storageSession(SessionID sessionID)
180 {
181     if (sessionID.isEphemeral()) {
182         NetworkStorageSession* privateStorageSession = SessionTracker::storageSession(sessionID);
183         if (privateStorageSession)
184             return *privateStorageSession;
185         // Some requests with private browsing mode requested may still be coming shortly after NetworkProcess was told to destroy its session.
186         // FIXME: Find a way to track private browsing sessions more rigorously.
187         LOG_ERROR("Private browsing was requested, but there was no session for it. Please file a bug unless you just disabled private browsing, in which case it's an expected race.");
188     }
189     return NetworkStorageSession::defaultStorageSession();
190 }
191
192 void NetworkConnectionToWebProcess::startDownload(SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedName)
193 {
194     NetworkProcess::singleton().downloadManager().startDownload(sessionID, downloadID, request, suggestedName);
195 }
196
197 void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(SessionID sessionID, uint64_t mainResourceLoadIdentifier, DownloadID downloadID, const ResourceRequest& request, const ResourceResponse& response)
198 {
199     auto& networkProcess = NetworkProcess::singleton();
200     if (!mainResourceLoadIdentifier) {
201         networkProcess.downloadManager().startDownload(sessionID, downloadID, request);
202         return;
203     }
204
205     NetworkResourceLoader* loader = m_networkResourceLoaders.get(mainResourceLoadIdentifier);
206     if (!loader) {
207         // If we're trying to download a blob here loader can be null.
208         return;
209     }
210
211 #if USE(NETWORK_SESSION)
212     loader->networkLoad()->convertTaskToDownload(downloadID, request);
213 #else
214     networkProcess.downloadManager().convertHandleToDownload(downloadID, loader->networkLoad()->handle(), request, response);
215
216     // Unblock the URL connection operation queue.
217     loader->networkLoad()->handle()->continueDidReceiveResponse();
218     
219 #endif
220     loader->didConvertToDownload();
221 }
222
223 void NetworkConnectionToWebProcess::cookiesForDOM(SessionID sessionID, const URL& firstParty, const URL& url, String& result)
224 {
225     result = WebCore::cookiesForDOM(storageSession(sessionID), firstParty, url);
226 }
227
228 void NetworkConnectionToWebProcess::setCookiesFromDOM(SessionID sessionID, const URL& firstParty, const URL& url, const String& cookieString)
229 {
230     WebCore::setCookiesFromDOM(storageSession(sessionID), firstParty, url, cookieString);
231 }
232
233 void NetworkConnectionToWebProcess::cookiesEnabled(SessionID sessionID, const URL& firstParty, const URL& url, bool& result)
234 {
235     result = WebCore::cookiesEnabled(storageSession(sessionID), firstParty, url);
236 }
237
238 void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(SessionID sessionID, const URL& firstParty, const URL& url, String& result)
239 {
240     result = WebCore::cookieRequestHeaderFieldValue(storageSession(sessionID), firstParty, url);
241 }
242
243 void NetworkConnectionToWebProcess::getRawCookies(SessionID sessionID, const URL& firstParty, const URL& url, Vector<Cookie>& result)
244 {
245     WebCore::getRawCookies(storageSession(sessionID), firstParty, url, result);
246 }
247
248 void NetworkConnectionToWebProcess::deleteCookie(SessionID sessionID, const URL& url, const String& cookieName)
249 {
250     WebCore::deleteCookie(storageSession(sessionID), url, cookieName);
251 }
252
253 void NetworkConnectionToWebProcess::addCookie(SessionID sessionID, const URL& url, const Cookie& cookie)
254 {
255     WebCore::addCookie(storageSession(sessionID), url, cookie);
256 }
257
258 void NetworkConnectionToWebProcess::registerFileBlobURL(const URL& url, const String& path, const SandboxExtension::Handle& extensionHandle, const String& contentType)
259 {
260     RefPtr<SandboxExtension> extension = SandboxExtension::create(extensionHandle);
261
262     NetworkBlobRegistry::singleton().registerFileBlobURL(this, url, path, WTFMove(extension), contentType);
263 }
264
265 void NetworkConnectionToWebProcess::registerBlobURL(const URL& url, Vector<BlobPart> blobParts, const String& contentType)
266 {
267     NetworkBlobRegistry::singleton().registerBlobURL(this, url, WTFMove(blobParts), contentType);
268 }
269
270 void NetworkConnectionToWebProcess::registerBlobURLFromURL(const URL& url, const URL& srcURL)
271 {
272     NetworkBlobRegistry::singleton().registerBlobURL(this, url, srcURL);
273 }
274
275 void NetworkConnectionToWebProcess::preregisterSandboxExtensionsForOptionallyFileBackedBlob(const Vector<String>& filePaths, const SandboxExtension::HandleArray& handles)
276 {
277     ASSERT(filePaths.size() == handles.size());
278
279     for (size_t i = 0; i < filePaths.size(); ++i)
280         m_blobDataFileReferences.add(filePaths[i], BlobDataFileReferenceWithSandboxExtension::create(filePaths[i], SandboxExtension::create(handles[i])));
281 }
282
283 RefPtr<WebCore::BlobDataFileReference> NetworkConnectionToWebProcess::getBlobDataFileReferenceForPath(const String& path)
284 {
285     ASSERT(m_blobDataFileReferences.contains(path));
286     return m_blobDataFileReferences.get(path);
287 }
288
289 void NetworkConnectionToWebProcess::registerBlobURLOptionallyFileBacked(const URL& url, const URL& srcURL, const String& fileBackedPath)
290 {
291     NetworkBlobRegistry::singleton().registerBlobURLOptionallyFileBacked(this, url, srcURL, fileBackedPath);
292 }
293
294 void NetworkConnectionToWebProcess::registerBlobURLForSlice(const URL& url, const URL& srcURL, int64_t start, int64_t end)
295 {
296     NetworkBlobRegistry::singleton().registerBlobURLForSlice(this, url, srcURL, start, end);
297 }
298
299 void NetworkConnectionToWebProcess::unregisterBlobURL(const URL& url)
300 {
301     NetworkBlobRegistry::singleton().unregisterBlobURL(this, url);
302 }
303
304 void NetworkConnectionToWebProcess::blobSize(const URL& url, uint64_t& resultSize)
305 {
306     resultSize = NetworkBlobRegistry::singleton().blobSize(this, url);
307 }
308
309 void NetworkConnectionToWebProcess::writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, uint64_t requestIdentifier)
310 {
311     RefPtr<NetworkConnectionToWebProcess> protector(this);
312
313     Vector<RefPtr<WebCore::BlobDataFileReference>> fileReferences;
314     for (auto& url : blobURLs)
315         fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(*this, { ParsedURLString, url }));
316
317     for (auto& file : fileReferences)
318         file->prepareForFileAccess();
319
320     NetworkBlobRegistry::singleton().writeBlobsToTemporaryFiles(blobURLs, [this, protector, requestIdentifier, fileReferences](auto& fileNames) {
321         for (auto& file : fileReferences)
322             file->revokeFileAccess();
323
324         NetworkProcess::singleton().grantSandboxExtensionsToDatabaseProcessForBlobs(fileNames, [this, protector, requestIdentifier, fileNames]() {
325             if (!m_connection || !m_connection->isValid())
326                 return;
327
328             m_connection->send(Messages::NetworkProcessConnection::DidWriteBlobsToTemporaryFiles(requestIdentifier, fileNames), 0);
329         });
330     });
331 }
332
333 void NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession()
334 {
335     NetworkProcess::singleton().ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
336 }
337
338 } // namespace WebKit