25cda360bc97160eb048d0eda546d9c5a29e7aed
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkLoad.cpp
1 /*
2  * Copyright (C) 2015 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 "NetworkLoad.h"
28
29 #include "AuthenticationManager.h"
30 #include "DownloadProxyMessages.h"
31 #include "NetworkProcess.h"
32 #include "NetworkSession.h"
33 #include "SessionTracker.h"
34 #include "WebCoreArgumentCoders.h"
35 #include "WebErrors.h"
36 #include <WebCore/NotImplemented.h>
37 #include <WebCore/ResourceRequest.h>
38 #include <WebCore/SharedBuffer.h>
39 #include <pal/SessionID.h>
40 #include <wtf/MainThread.h>
41 #include <wtf/Seconds.h>
42
43 #if PLATFORM(COCOA)
44 #include "NetworkDataTaskCocoa.h"
45 #endif
46
47 #if ENABLE(NETWORK_CAPTURE)
48 #include "NetworkCaptureManager.h"
49 #endif
50
51 namespace WebKit {
52
53 using namespace WebCore;
54
55 struct NetworkLoad::Throttle {
56     Throttle(NetworkLoad& load, Seconds delay, ResourceResponse&& response, ResponseCompletionHandler&& handler)
57         : timer(load, &NetworkLoad::throttleDelayCompleted)
58         , response(WTFMove(response))
59         , responseCompletionHandler(WTFMove(handler))
60     {
61         timer.startOneShot(delay);
62     }
63     Timer timer;
64     ResourceResponse response;
65     ResponseCompletionHandler responseCompletionHandler;
66 };
67
68 NetworkLoad::NetworkLoad(NetworkLoadClient& client, NetworkLoadParameters&& parameters, NetworkSession& networkSession)
69     : m_client(client)
70     , m_parameters(WTFMove(parameters))
71     , m_currentRequest(m_parameters.request)
72 {
73 #if ENABLE(NETWORK_CAPTURE)
74     switch (NetworkCapture::Manager::singleton().mode()) {
75     case NetworkCapture::Manager::RecordReplayMode::Record:
76         initializeForRecord(networkSession);
77         break;
78     case NetworkCapture::Manager::RecordReplayMode::Replay:
79         initializeForReplay(networkSession);
80         break;
81     case NetworkCapture::Manager::RecordReplayMode::Disabled:
82         initialize(networkSession);
83         break;
84     }
85 #else
86     initialize(networkSession);
87 #endif
88 }
89
90 #if ENABLE(NETWORK_CAPTURE)
91 void NetworkLoad::initializeForRecord(NetworkSession& networkSession)
92 {
93     m_recorder = std::make_unique<NetworkCapture::Recorder>();
94     m_task = NetworkDataTask::create(networkSession, *this, m_parameters);
95     if (!m_parameters.defersLoading) {
96         m_task->resume();
97         m_recorder->recordRequestSent(m_parameters.request);
98     }
99 }
100
101 void NetworkLoad::initializeForReplay(NetworkSession& networkSession)
102 {
103     m_replayer = std::make_unique<NetworkCapture::Replayer>();
104     m_task = m_replayer->replayResource(networkSession, *this, m_parameters);
105     if (!m_parameters.defersLoading)
106         m_task->resume();
107 }
108 #endif
109
110 void NetworkLoad::initialize(NetworkSession& networkSession)
111 {
112     m_task = NetworkDataTask::create(networkSession, *this, m_parameters);
113     if (!m_parameters.defersLoading)
114         m_task->resume();
115 }
116
117 NetworkLoad::~NetworkLoad()
118 {
119     ASSERT(RunLoop::isMain());
120     if (m_redirectCompletionHandler)
121         m_redirectCompletionHandler({ });
122     if (m_responseCompletionHandler)
123         m_responseCompletionHandler(PolicyAction::Ignore);
124 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
125     if (m_challengeCompletionHandler)
126         m_challengeCompletionHandler(AuthenticationChallengeDisposition::Cancel, { });
127 #endif
128     if (m_task)
129         m_task->clearClient();
130 }
131
132 void NetworkLoad::setDefersLoading(bool defers)
133 {
134     if (m_task) {
135         if (defers)
136             m_task->suspend();
137         else {
138             m_task->resume();
139 #if ENABLE(NETWORK_CAPTURE)
140             if (m_recorder)
141                 m_recorder->recordRequestSent(m_parameters.request);
142 #endif
143         }
144     }
145 }
146
147 void NetworkLoad::cancel()
148 {
149     if (m_task)
150         m_task->cancel();
151 }
152
153 void NetworkLoad::continueWillSendRequest(WebCore::ResourceRequest&& newRequest)
154 {
155 #if PLATFORM(COCOA)
156     m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest.nsURLRequest(DoNotUpdateHTTPBody));
157 #elif USE(SOUP)
158     // FIXME: Implement ResourceRequest::updateFromDelegatePreservingOldProperties. See https://bugs.webkit.org/show_bug.cgi?id=126127.
159     m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest);
160 #endif
161
162 #if ENABLE(NETWORK_CAPTURE)
163     if (m_recorder)
164         m_recorder->recordRedirectSent(newRequest);
165 #endif
166
167     auto redirectCompletionHandler = std::exchange(m_redirectCompletionHandler, nullptr);
168     ASSERT(redirectCompletionHandler);
169     if (m_currentRequest.isNull()) {
170         NetworkLoadMetrics emptyMetrics;
171         didCompleteWithError(cancelledError(m_currentRequest), emptyMetrics);
172         if (redirectCompletionHandler)
173             redirectCompletionHandler({ });
174         return;
175     }
176
177     if (redirectCompletionHandler)
178         redirectCompletionHandler(ResourceRequest(m_currentRequest));
179 }
180
181 void NetworkLoad::continueDidReceiveResponse()
182 {
183     if (m_responseCompletionHandler) {
184         auto responseCompletionHandler = std::exchange(m_responseCompletionHandler, nullptr);
185         responseCompletionHandler(PolicyAction::Use);
186     }
187 }
188
189 bool NetworkLoad::shouldCaptureExtraNetworkLoadMetrics() const
190 {
191     return m_client.get().shouldCaptureExtraNetworkLoadMetrics();
192 }
193
194 bool NetworkLoad::isAllowedToAskUserForCredentials() const
195 {
196     return m_client.get().isAllowedToAskUserForCredentials();
197 }
198
199 void NetworkLoad::convertTaskToDownload(PendingDownload& pendingDownload, const ResourceRequest& updatedRequest, const ResourceResponse& response)
200 {
201     if (!m_task)
202         return;
203
204     m_client = pendingDownload;
205     m_currentRequest = updatedRequest;
206     m_task->setPendingDownload(pendingDownload);
207
208     if (m_responseCompletionHandler)
209         NetworkProcess::singleton().findPendingDownloadLocation(*m_task.get(), std::exchange(m_responseCompletionHandler, nullptr), response);
210 }
211
212 void NetworkLoad::setPendingDownloadID(DownloadID downloadID)
213 {
214     if (!m_task)
215         return;
216
217     m_task->setPendingDownloadID(downloadID);
218 }
219
220 void NetworkLoad::setSuggestedFilename(const String& suggestedName)
221 {
222     if (!m_task)
223         return;
224
225     m_task->setSuggestedFilename(suggestedName);
226 }
227
228 void NetworkLoad::setPendingDownload(PendingDownload& pendingDownload)
229 {
230     if (!m_task)
231         return;
232
233     m_task->setPendingDownload(pendingDownload);
234 }
235
236 void NetworkLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler)
237 {
238     ASSERT(!redirectResponse.isNull());
239     ASSERT(RunLoop::isMain());
240     ASSERT(!m_redirectCompletionHandler);
241
242     redirectResponse.setSource(ResourceResponse::Source::Network);
243     m_redirectCompletionHandler = WTFMove(completionHandler);
244
245 #if ENABLE(NETWORK_CAPTURE)
246     if (m_recorder)
247         m_recorder->recordRedirectReceived(request, redirectResponse);
248 #endif
249
250     auto oldRequest = WTFMove(m_currentRequest);
251     request.setRequester(oldRequest.requester());
252
253     m_currentRequest = request;
254     m_client.get().willSendRedirectedRequest(WTFMove(oldRequest), WTFMove(request), WTFMove(redirectResponse));
255 }
256
257 void NetworkLoad::didReceiveChallenge(const AuthenticationChallenge& challenge, ChallengeCompletionHandler&& completionHandler)
258 {
259     m_challenge = challenge;
260 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
261     m_challengeCompletionHandler = WTFMove(completionHandler);
262     m_client.get().canAuthenticateAgainstProtectionSpaceAsync(challenge.protectionSpace());
263 #else
264     completeAuthenticationChallenge(WTFMove(completionHandler));
265 #endif
266 }
267
268 void NetworkLoad::completeAuthenticationChallenge(ChallengeCompletionHandler&& completionHandler)
269 {
270     auto scheme = m_challenge->protectionSpace().authenticationScheme();
271     bool isTLSHandshake = scheme == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested
272         || scheme == ProtectionSpaceAuthenticationSchemeClientCertificateRequested;
273     if (!isAllowedToAskUserForCredentials() && !isTLSHandshake) {
274         m_client.get().didBlockAuthenticationChallenge();
275         completionHandler(AuthenticationChallengeDisposition::UseCredential, { });
276         return;
277     }
278
279     if (!m_task)
280         return;
281
282     if (auto* pendingDownload = m_task->pendingDownload())
283         NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(*pendingDownload, *m_challenge, WTFMove(completionHandler));
284     else
285         NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(m_parameters.webPageID, m_parameters.webFrameID, *m_challenge, WTFMove(completionHandler));
286 }
287
288 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
289 void NetworkLoad::continueCanAuthenticateAgainstProtectionSpace(bool result)
290 {
291     if (!m_challengeCompletionHandler) {
292         ASSERT_NOT_REACHED();
293         return;
294     }
295
296     auto completionHandler = std::exchange(m_challengeCompletionHandler, nullptr);
297     if (!result) {
298         if (NetworkSession::allowsSpecificHTTPSCertificateForHost(*m_challenge))
299             completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(*m_challenge));
300         else
301             completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, { });
302         return;
303     }
304
305     completeAuthenticationChallenge(WTFMove(completionHandler));
306 }
307 #endif
308
309 void NetworkLoad::didReceiveResponseNetworkSession(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
310 {
311     ASSERT(RunLoop::isMain());
312     ASSERT(!m_throttle);
313
314     if (m_task && m_task->isDownload()) {
315         NetworkProcess::singleton().findPendingDownloadLocation(*m_task.get(), WTFMove(completionHandler), response);
316         return;
317     }
318
319     auto delay = NetworkProcess::singleton().loadThrottleLatency();
320     if (delay > 0_s) {
321         m_throttle = std::make_unique<Throttle>(*this, delay, WTFMove(response), WTFMove(completionHandler));
322         return;
323     }
324
325     notifyDidReceiveResponse(WTFMove(response), WTFMove(completionHandler));
326 }
327
328 void NetworkLoad::notifyDidReceiveResponse(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
329 {
330     ASSERT(RunLoop::isMain());
331
332 #if ENABLE(NETWORK_CAPTURE)
333     if (m_recorder)
334         m_recorder->recordResponseReceived(response);
335 #endif
336
337     response.setSource(ResourceResponse::Source::Network);
338     if (m_parameters.needsCertificateInfo)
339         response.includeCertificateInfo();
340
341     if (m_client.get().didReceiveResponse(WTFMove(response)) == NetworkLoadClient::ShouldContinueDidReceiveResponse::No) {
342         m_responseCompletionHandler = WTFMove(completionHandler);
343         return;
344     }
345     completionHandler(PolicyAction::Use);
346 }
347
348 void NetworkLoad::didReceiveData(Ref<SharedBuffer>&& buffer)
349 {
350     ASSERT(!m_throttle);
351
352 #if ENABLE(NETWORK_CAPTURE)
353     if (m_recorder)
354         m_recorder->recordDataReceived(buffer.get());
355 #endif
356
357     // FIXME: This should be the encoded data length, not the decoded data length.
358     auto size = buffer->size();
359     m_client.get().didReceiveBuffer(WTFMove(buffer), size);
360 }
361
362 void NetworkLoad::didCompleteWithError(const ResourceError& error, const WebCore::NetworkLoadMetrics& networkLoadMetrics)
363 {
364     ASSERT(!m_throttle);
365
366 #if ENABLE(NETWORK_CAPTURE)
367     if (m_recorder)
368         m_recorder->recordFinish(error);
369 #endif
370
371     if (error.isNull())
372         m_client.get().didFinishLoading(networkLoadMetrics);
373     else
374         m_client.get().didFailLoading(error);
375 }
376
377 void NetworkLoad::throttleDelayCompleted()
378 {
379     ASSERT(m_throttle);
380
381     auto throttle = WTFMove(m_throttle);
382
383     notifyDidReceiveResponse(WTFMove(throttle->response), WTFMove(throttle->responseCompletionHandler));
384 }
385
386 void NetworkLoad::didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend)
387 {
388     m_client.get().didSendData(totalBytesSent, totalBytesExpectedToSend);
389 }
390
391 void NetworkLoad::wasBlocked()
392 {
393     m_client.get().didFailLoading(blockedError(m_currentRequest));
394 }
395
396 void NetworkLoad::cannotShowURL()
397 {
398     m_client.get().didFailLoading(cannotShowURLError(m_currentRequest));
399 }
400
401
402 String NetworkLoad::description() const
403 {
404     if (m_task.get())
405         return m_task->description();
406     return emptyString();
407 }
408
409 } // namespace WebKit