Migrate some layout timer-related code from std::chrono to Seconds and MonotonicTime
[WebKit-https.git] / Source / WebKit2 / UIProcess / Network / NetworkProcessProxy.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 "NetworkProcessProxy.h"
28
29 #include "AuthenticationChallengeProxy.h"
30 #include "CustomProtocolManagerProxyMessages.h"
31 #include "DatabaseProcessMessages.h"
32 #include "DownloadProxyMessages.h"
33 #include "Logging.h"
34 #include "NetworkProcessCreationParameters.h"
35 #include "NetworkProcessMessages.h"
36 #include "SandboxExtension.h"
37 #include "WebProcessMessages.h"
38 #include "WebProcessPool.h"
39 #include "WebsiteData.h"
40
41 #if ENABLE(SEC_ITEM_SHIM)
42 #include "SecItemShimProxy.h"
43 #endif
44
45 #if PLATFORM(IOS)
46 #include <wtf/spi/darwin/XPCSPI.h>
47 #endif
48
49 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
50
51 using namespace WebCore;
52
53 namespace WebKit {
54
55 static uint64_t generateCallbackID()
56 {
57     static uint64_t callbackID;
58
59     return ++callbackID;
60 }
61
62 Ref<NetworkProcessProxy> NetworkProcessProxy::create(WebProcessPool& processPool)
63 {
64     return adoptRef(*new NetworkProcessProxy(processPool));
65 }
66
67 NetworkProcessProxy::NetworkProcessProxy(WebProcessPool& processPool)
68     : m_processPool(processPool)
69     , m_numPendingConnectionRequests(0)
70     , m_customProtocolManagerProxy(this, processPool)
71     , m_throttler(*this)
72 {
73     connect();
74 }
75
76 NetworkProcessProxy::~NetworkProcessProxy()
77 {
78     ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
79     ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
80     ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
81 }
82
83 void NetworkProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
84 {
85     launchOptions.processType = ProcessLauncher::ProcessType::Network;
86     ChildProcessProxy::getLaunchOptions(launchOptions);
87 }
88
89 void NetworkProcessProxy::connectionWillOpen(IPC::Connection& connection)
90 {
91 #if ENABLE(SEC_ITEM_SHIM)
92     SecItemShimProxy::singleton().initializeConnection(connection);
93 #else
94     UNUSED_PARAM(connection);
95 #endif
96 }
97
98 void NetworkProcessProxy::processWillShutDown(IPC::Connection& connection)
99 {
100     ASSERT_UNUSED(connection, this->connection() == &connection);
101 }
102
103 void NetworkProcessProxy::getNetworkProcessConnection(RefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>&& reply)
104 {
105     m_pendingConnectionReplies.append(reply);
106
107     if (state() == State::Launching) {
108         m_numPendingConnectionRequests++;
109         return;
110     }
111
112     connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
113 }
114
115 DownloadProxy* NetworkProcessProxy::createDownloadProxy(const ResourceRequest& resourceRequest)
116 {
117     if (!m_downloadProxyMap)
118         m_downloadProxyMap = std::make_unique<DownloadProxyMap>(this);
119
120     return m_downloadProxyMap->createDownloadProxy(m_processPool, resourceRequest);
121 }
122
123 void NetworkProcessProxy::fetchWebsiteData(SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, std::function<void (WebsiteData)> completionHandler)
124 {
125     ASSERT(canSendMessage());
126
127     uint64_t callbackID = generateCallbackID();
128     auto token = throttler().backgroundActivityToken();
129     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is fetching Website data", this);
130
131     m_pendingFetchWebsiteDataCallbacks.add(callbackID, [this, token, completionHandler, sessionID](WebsiteData websiteData) {
132         completionHandler(WTFMove(websiteData));
133         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done fetching Website data", this);
134     });
135
136     send(Messages::NetworkProcess::FetchWebsiteData(sessionID, dataTypes, fetchOptions, callbackID), 0);
137 }
138
139 void NetworkProcessProxy::deleteWebsiteData(WebCore::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, std::chrono::system_clock::time_point modifiedSince,  std::function<void ()> completionHandler)
140 {
141     auto callbackID = generateCallbackID();
142     auto token = throttler().backgroundActivityToken();
143     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is deleting Website data", this);
144
145     m_pendingDeleteWebsiteDataCallbacks.add(callbackID, [this, token, completionHandler, sessionID] {
146         completionHandler();
147         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data", this);
148     });
149     send(Messages::NetworkProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
150 }
151
152 void NetworkProcessProxy::deleteWebsiteDataForOrigins(SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, std::function<void()> completionHandler)
153 {
154     ASSERT(canSendMessage());
155
156     uint64_t callbackID = generateCallbackID();
157     auto token = throttler().backgroundActivityToken();
158     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is deleting Website data for several origins", this);
159
160     m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, [this, token, completionHandler, sessionID] {
161         completionHandler();
162         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data for several origins", this);
163     });
164
165     send(Messages::NetworkProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, cookieHostNames, callbackID), 0);
166 }
167
168 void NetworkProcessProxy::networkProcessCrashedOrFailedToLaunch()
169 {
170     // The network process must have crashed or exited, send any pending sync replies we might have.
171     while (!m_pendingConnectionReplies.isEmpty()) {
172         RefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
173
174 #if USE(UNIX_DOMAIN_SOCKETS)
175         reply->send(IPC::Attachment());
176 #elif OS(DARWIN)
177         reply->send(IPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
178 #else
179         notImplemented();
180 #endif
181     }
182
183     for (const auto& callback : m_pendingFetchWebsiteDataCallbacks.values())
184         callback(WebsiteData());
185     m_pendingFetchWebsiteDataCallbacks.clear();
186
187     for (const auto& callback : m_pendingDeleteWebsiteDataCallbacks.values())
188         callback();
189     m_pendingDeleteWebsiteDataCallbacks.clear();
190
191     for (const auto& callback : m_pendingDeleteWebsiteDataForOriginsCallbacks.values())
192         callback();
193     m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
194
195     // Tell the network process manager to forget about this network process proxy. This may cause us to be deleted.
196     m_processPool.networkProcessCrashed(this);
197 }
198
199 void NetworkProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
200 {
201     if (dispatchMessage(connection, decoder))
202         return;
203
204     if (m_processPool.dispatchMessage(connection, decoder))
205         return;
206
207     didReceiveNetworkProcessProxyMessage(connection, decoder);
208 }
209
210 void NetworkProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
211 {
212     if (dispatchSyncMessage(connection, decoder, replyEncoder))
213         return;
214
215     ASSERT_NOT_REACHED();
216 }
217
218 void NetworkProcessProxy::didClose(IPC::Connection&)
219 {
220     if (m_downloadProxyMap)
221         m_downloadProxyMap->processDidClose();
222     m_customProtocolManagerProxy.processDidClose();
223
224     m_tokenForHoldingLockedFiles = nullptr;
225
226     // This may cause us to be deleted.
227     networkProcessCrashedOrFailedToLaunch();
228 }
229
230 void NetworkProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
231 {
232 }
233
234 void NetworkProcessProxy::didCreateNetworkConnectionToWebProcess(const IPC::Attachment& connectionIdentifier)
235 {
236     ASSERT(!m_pendingConnectionReplies.isEmpty());
237
238     // Grab the first pending connection reply.
239     RefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
240
241 #if USE(UNIX_DOMAIN_SOCKETS)
242     reply->send(connectionIdentifier);
243 #elif OS(DARWIN)
244     reply->send(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
245 #else
246     notImplemented();
247 #endif
248 }
249
250 void NetworkProcessProxy::didReceiveAuthenticationChallenge(uint64_t pageID, uint64_t frameID, const WebCore::AuthenticationChallenge& coreChallenge, uint64_t challengeID)
251 {
252     WebPageProxy* page = WebProcessProxy::webPage(pageID);
253     MESSAGE_CHECK(page);
254
255     auto authenticationChallenge = AuthenticationChallengeProxy::create(coreChallenge, challengeID, connection());
256     page->didReceiveAuthenticationChallengeProxy(frameID, WTFMove(authenticationChallenge));
257 }
258
259 void NetworkProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
260 {
261     auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
262     callback(websiteData);
263 }
264
265 void NetworkProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
266 {
267     auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
268     callback();
269 }
270
271 void NetworkProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
272 {
273     auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
274     callback();
275 }
276
277 void NetworkProcessProxy::grantSandboxExtensionsToDatabaseProcessForBlobs(uint64_t requestID, const Vector<String>& paths)
278 {
279 #if ENABLE(DATABASE_PROCESS)
280 #if ENABLE(SANDBOX_EXTENSIONS)
281     SandboxExtension::HandleArray extensions;
282     extensions.allocate(paths.size());
283     for (size_t i = 0; i < paths.size(); ++i) {
284         // ReadWrite is required for creating hard links as well as deleting the temporary file, which the DatabaseProcess will do.
285         SandboxExtension::createHandle(paths[i], SandboxExtension::ReadWrite, extensions[i]);
286     }
287
288     m_processPool.sendToDatabaseProcessRelaunchingIfNecessary(Messages::DatabaseProcess::GrantSandboxExtensionsForBlobs(paths, extensions));
289 #endif
290     connection()->send(Messages::NetworkProcess::DidGrantSandboxExtensionsToDatabaseProcessForBlobs(requestID), 0);
291 #endif
292 }
293
294 void NetworkProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
295 {
296     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
297
298     if (IPC::Connection::identifierIsNull(connectionIdentifier)) {
299         networkProcessCrashedOrFailedToLaunch();
300         return;
301     }
302
303     for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
304         connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(), 0);
305     
306     m_numPendingConnectionRequests = 0;
307
308 #if PLATFORM(COCOA)
309     if (m_processPool.processSuppressionEnabled())
310         setProcessSuppressionEnabled(true);
311 #endif
312     
313 #if PLATFORM(IOS)
314     if (xpc_connection_t connection = this->connection()->xpcConnection())
315         m_throttler.didConnectToProcess(xpc_connection_get_pid(connection));
316 #endif
317 }
318
319 void NetworkProcessProxy::logSampledDiagnosticMessage(uint64_t pageID, const String& message, const String& description)
320 {
321     WebPageProxy* page = WebProcessProxy::webPage(pageID);
322     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
323     // but for now we simply drop the message in the rare case this happens.
324     if (!page)
325         return;
326
327     page->logSampledDiagnosticMessage(message, description);
328 }
329
330 void NetworkProcessProxy::logSampledDiagnosticMessageWithResult(uint64_t pageID, const String& message, const String& description, uint32_t result)
331 {
332     WebPageProxy* page = WebProcessProxy::webPage(pageID);
333     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
334     // but for now we simply drop the message in the rare case this happens.
335     if (!page)
336         return;
337
338     page->logSampledDiagnosticMessageWithResult(message, description, result);
339 }
340
341 void NetworkProcessProxy::logSampledDiagnosticMessageWithValue(uint64_t pageID, const String& message, const String& description, const String& value)
342 {
343     WebPageProxy* page = WebProcessProxy::webPage(pageID);
344     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
345     // but for now we simply drop the message in the rare case this happens.
346     if (!page)
347         return;
348
349     page->logSampledDiagnosticMessageWithValue(message, description, value);
350 }
351
352 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
353 void NetworkProcessProxy::canAuthenticateAgainstProtectionSpace(uint64_t loaderID, uint64_t pageID, uint64_t frameID, const WebCore::ProtectionSpace& protectionSpace)
354 {
355     WebPageProxy* page = WebProcessProxy::webPage(pageID);
356     if (!page)
357         return;
358     
359     page->canAuthenticateAgainstProtectionSpace(loaderID, frameID, protectionSpace);
360 }
361 #endif
362
363 void NetworkProcessProxy::sendProcessWillSuspendImminently()
364 {
365     if (!canSendMessage())
366         return;
367
368     bool handled = false;
369     sendSync(Messages::NetworkProcess::ProcessWillSuspendImminently(), Messages::NetworkProcess::ProcessWillSuspendImminently::Reply(handled), 0, 1_s);
370 }
371     
372 void NetworkProcessProxy::sendPrepareToSuspend()
373 {
374     if (canSendMessage())
375         send(Messages::NetworkProcess::PrepareToSuspend(), 0);
376 }
377
378 void NetworkProcessProxy::sendCancelPrepareToSuspend()
379 {
380     if (canSendMessage())
381         send(Messages::NetworkProcess::CancelPrepareToSuspend(), 0);
382 }
383
384 void NetworkProcessProxy::sendProcessDidResume()
385 {
386     if (canSendMessage())
387         send(Messages::NetworkProcess::ProcessDidResume(), 0);
388 }
389
390 bool NetworkProcessProxy::alwaysRunsAtBackgroundPriority()
391 {
392     return m_processPool.alwaysRunsAtBackgroundPriority();
393 }
394
395 void NetworkProcessProxy::processReadyToSuspend()
396 {
397     m_throttler.processReadyToSuspend();
398 }
399
400 void NetworkProcessProxy::didSetAssertionState(AssertionState)
401 {
402 }
403     
404 void NetworkProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
405 {
406     if (!isHoldingLockedFiles) {
407         RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the Network process is no longer holding locked files");
408         m_tokenForHoldingLockedFiles = nullptr;
409         return;
410     }
411     if (!m_tokenForHoldingLockedFiles) {
412         RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the Network process is holding locked files");
413         m_tokenForHoldingLockedFiles = m_throttler.backgroundActivityToken();
414     }
415 }
416
417 } // namespace WebKit