2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "NetworkResourceLoader.h"
29 #include "DataReference.h"
31 #include "NetworkBlobRegistry.h"
32 #include "NetworkCache.h"
33 #include "NetworkConnectionToWebProcess.h"
34 #include "NetworkLoad.h"
35 #include "NetworkProcess.h"
36 #include "NetworkProcessConnectionMessages.h"
37 #include "SessionTracker.h"
38 #include "WebCoreArgumentCoders.h"
39 #include "WebErrors.h"
40 #include "WebResourceLoaderMessages.h"
41 #include <WebCore/BlobDataFileReference.h>
42 #include <WebCore/CertificateInfo.h>
43 #include <WebCore/DiagnosticLoggingKeys.h>
44 #include <WebCore/HTTPHeaderNames.h>
45 #include <WebCore/ProtectionSpace.h>
46 #include <WebCore/SharedBuffer.h>
47 #include <WebCore/SynchronousLoaderClient.h>
48 #include <wtf/CurrentTime.h>
49 #include <wtf/RunLoop.h>
51 using namespace WebCore;
53 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - NetworkResourceLoader::" fmt, this, ##__VA_ARGS__)
54 #define RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), Network, "%p - NetworkResourceLoader::" fmt, this, ##__VA_ARGS__)
58 struct NetworkResourceLoader::SynchronousLoadData {
59 SynchronousLoadData(RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply)
60 : delayedReply(WTFMove(reply))
64 ResourceRequest currentRequest;
65 RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> delayedReply;
66 ResourceResponse response;
70 static void sendReplyToSynchronousRequest(NetworkResourceLoader::SynchronousLoadData& data, const SharedBuffer* buffer)
72 ASSERT(data.delayedReply);
73 ASSERT(!data.response.isNull() || !data.error.isNull());
75 Vector<char> responseBuffer;
76 if (buffer && buffer->size())
77 responseBuffer.append(buffer->data(), buffer->size());
79 data.delayedReply->send(data.error, data.response, responseBuffer);
80 data.delayedReply = nullptr;
83 NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess& connection, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& synchronousReply)
84 : m_parameters(parameters)
85 , m_connection(connection)
86 , m_defersLoading(parameters.defersLoading)
87 , m_bufferingTimer(*this, &NetworkResourceLoader::bufferingTimerFired)
89 ASSERT(RunLoop::isMain());
90 // FIXME: This is necessary because of the existence of EmptyFrameLoaderClient in WebCore.
91 // Once bug 116233 is resolved, this ASSERT can just be "m_webPageID && m_webFrameID"
92 ASSERT((m_parameters.webPageID && m_parameters.webFrameID) || m_parameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials);
94 if (originalRequest().httpBody()) {
95 for (const auto& element : originalRequest().httpBody()->elements()) {
96 if (element.m_type == FormDataElement::Type::EncodedBlob)
97 m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, element.m_url));
101 #if !USE(NETWORK_SESSION)
102 if (originalRequest().url().protocolIsBlob()) {
103 ASSERT(!m_parameters.resourceSandboxExtension);
104 m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, originalRequest().url()));
109 if (synchronousReply)
110 m_synchronousLoadData = std::make_unique<SynchronousLoadData>(WTFMove(synchronousReply));
113 NetworkResourceLoader::~NetworkResourceLoader()
115 ASSERT(RunLoop::isMain());
116 ASSERT(!m_networkLoad);
117 ASSERT(!isSynchronous() || !m_synchronousLoadData->delayedReply);
120 #if ENABLE(NETWORK_CACHE)
121 bool NetworkResourceLoader::canUseCache(const ResourceRequest& request) const
123 if (!NetworkCache::singleton().isEnabled())
125 if (sessionID().isEphemeral())
127 if (!request.url().protocolIsInHTTPFamily())
129 if (originalRequest().cachePolicy() == WebCore::DoNotUseAnyCache)
135 bool NetworkResourceLoader::canUseCachedRedirect(const ResourceRequest& request) const
137 if (!canUseCache(request))
139 // Limit cached redirects to avoid cycles and other trouble.
140 // Networking layer follows over 30 redirects but caching that many seems unnecessary.
141 static const unsigned maximumCachedRedirectCount { 5 };
142 if (m_redirectCount > maximumCachedRedirectCount)
149 bool NetworkResourceLoader::isSynchronous() const
151 return !!m_synchronousLoadData;
154 void NetworkResourceLoader::start()
156 ASSERT(RunLoop::isMain());
158 if (m_defersLoading) {
159 RELEASE_LOG_IF_ALLOWED("start: Loading is deferred (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
163 #if ENABLE(NETWORK_CACHE)
164 if (canUseCache(originalRequest())) {
165 RELEASE_LOG_IF_ALLOWED("start: Retrieving resource from cache (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
166 retrieveCacheEntry(originalRequest());
171 startNetworkLoad(originalRequest());
174 #if ENABLE(NETWORK_CACHE)
175 void NetworkResourceLoader::retrieveCacheEntry(const ResourceRequest& request)
177 ASSERT(canUseCache(request));
179 RefPtr<NetworkResourceLoader> loader(this);
180 NetworkCache::singleton().retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [loader, request](auto entry) {
181 if (loader->hasOneRef()) {
182 // The loader has been aborted and is only held alive by this lambda.
186 loader->startNetworkLoad(request);
189 if (entry->redirectRequest()) {
190 loader->dispatchWillSendRequestForCacheEntry(WTFMove(entry));
193 if (loader->m_parameters.needsCertificateInfo && !entry->response().certificateInfo()) {
194 loader->startNetworkLoad(request);
197 if (entry->needsValidation() || request.cachePolicy() == WebCore::RefreshAnyCacheData) {
198 loader->validateCacheEntry(WTFMove(entry));
201 loader->didRetrieveCacheEntry(WTFMove(entry));
206 void NetworkResourceLoader::startNetworkLoad(const ResourceRequest& request)
208 RELEASE_LOG_IF_ALLOWED("startNetworkLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isMainResource = %d, isSynchronous = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, isMainResource(), isSynchronous());
210 consumeSandboxExtensions();
212 if (isSynchronous() || m_parameters.maximumBufferingTime > 0ms)
213 m_bufferedData = SharedBuffer::create();
215 #if ENABLE(NETWORK_CACHE)
216 if (canUseCache(request))
217 m_bufferedDataForCache = SharedBuffer::create();
220 NetworkLoadParameters parameters = m_parameters;
221 parameters.defersLoading = m_defersLoading;
222 parameters.request = request;
224 #if USE(NETWORK_SESSION)
225 if (request.url().protocolIsBlob())
226 parameters.blobFileReferences = NetworkBlobRegistry::singleton().filesInBlob(m_connection, originalRequest().url());
228 auto* networkSession = SessionTracker::networkSession(parameters.sessionID);
229 if (!networkSession) {
230 WTFLogAlways("Attempted to create a NetworkLoad with a session (id=%" PRIu64 ") that does not exist.", parameters.sessionID.sessionID());
231 RELEASE_LOG_ERROR_IF_ALLOWED("startNetworkLoad: Attempted to create a NetworkLoad with a session that does not exist (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", sessionID=%" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, parameters.sessionID.sessionID());
232 NetworkProcess::singleton().logDiagnosticMessage(m_parameters.webPageID, WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::invalidSessionIDKey(), WebCore::ShouldSample::No);
233 didFailLoading(internalError(request.url()));
236 m_networkLoad = std::make_unique<NetworkLoad>(*this, WTFMove(parameters), *networkSession);
238 m_networkLoad = std::make_unique<NetworkLoad>(*this, WTFMove(parameters));
241 if (m_defersLoading) {
242 RELEASE_LOG_IF_ALLOWED("startNetworkLoad: Created, but deferred (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")",
243 m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
247 void NetworkResourceLoader::setDefersLoading(bool defers)
249 if (m_defersLoading == defers)
251 m_defersLoading = defers;
254 RELEASE_LOG_IF_ALLOWED("setDefersLoading: Deferring resource load (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
256 RELEASE_LOG_IF_ALLOWED("setDefersLoading: Resuming deferred resource load (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
259 m_networkLoad->setDefersLoading(defers);
263 if (!m_defersLoading)
266 RELEASE_LOG_IF_ALLOWED("setDefersLoading: defers = TRUE, but nothing to stop (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
269 void NetworkResourceLoader::cleanup()
271 ASSERT(RunLoop::isMain());
273 m_bufferingTimer.stop();
275 invalidateSandboxExtensions();
277 m_networkLoad = nullptr;
279 // This will cause NetworkResourceLoader to be destroyed and therefore we do it last.
280 m_connection->didCleanupResourceLoader(*this);
283 void NetworkResourceLoader::convertToDownload(DownloadID downloadID, const ResourceRequest& request, const ResourceResponse& response)
285 ASSERT(m_networkLoad);
286 NetworkProcess::singleton().downloadManager().convertNetworkLoadToDownload(downloadID, WTFMove(m_networkLoad), WTFMove(m_fileReferences), request, response);
289 void NetworkResourceLoader::abort()
291 ASSERT(RunLoop::isMain());
293 RELEASE_LOG_IF_ALLOWED("abort: Canceling resource load (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")",
294 m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
297 #if ENABLE(NETWORK_CACHE)
298 if (canUseCache(m_networkLoad->currentRequest())) {
299 // We might already have used data from this incomplete load. Ensure older versions don't remain in the cache after cancel.
300 if (!m_response.isNull())
301 NetworkCache::singleton().remove(m_networkLoad->currentRequest());
304 m_networkLoad->cancel();
310 auto NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedResponse) -> ShouldContinueDidReceiveResponse
312 RELEASE_LOG_IF_ALLOWED("didReceiveResponse: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", httpStatusCode = %d, length = %" PRId64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, receivedResponse.httpStatusCode(), receivedResponse.expectedContentLength());
314 m_response = WTFMove(receivedResponse);
316 // For multipart/x-mixed-replace didReceiveResponseAsync gets called multiple times and buffering would require special handling.
317 if (!isSynchronous() && m_response.isMultipart())
318 m_bufferedData = nullptr;
320 bool shouldSendDidReceiveResponse = true;
321 #if ENABLE(NETWORK_CACHE)
322 if (m_response.isMultipart())
323 m_bufferedDataForCache = nullptr;
325 if (m_cacheEntryForValidation) {
326 bool validationSucceeded = m_response.httpStatusCode() == 304; // 304 Not Modified
327 if (validationSucceeded) {
328 m_cacheEntryForValidation = NetworkCache::singleton().update(originalRequest(), { m_parameters.webPageID, m_parameters.webFrameID }, *m_cacheEntryForValidation, m_response);
329 // If the request was conditional then this revalidation was not triggered by the network cache and we pass the 304 response to WebCore.
330 if (originalRequest().isConditional())
331 m_cacheEntryForValidation = nullptr;
333 m_cacheEntryForValidation = nullptr;
335 shouldSendDidReceiveResponse = !m_cacheEntryForValidation;
338 bool shouldWaitContinueDidReceiveResponse = isMainResource();
339 if (shouldSendDidReceiveResponse) {
341 m_synchronousLoadData->response = m_response;
343 send(Messages::WebResourceLoader::DidReceiveResponse(m_response, shouldWaitContinueDidReceiveResponse));
346 // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message.
347 bool shouldContinueDidReceiveResponse = !shouldWaitContinueDidReceiveResponse;
348 #if ENABLE(NETWORK_CACHE)
349 shouldContinueDidReceiveResponse = shouldContinueDidReceiveResponse || m_cacheEntryForValidation;
352 if (shouldContinueDidReceiveResponse) {
353 RELEASE_LOG_IF_ALLOWED("didReceiveResponse: Should not wait for message from WebContent process before continuing resource load (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
354 return ShouldContinueDidReceiveResponse::Yes;
357 RELEASE_LOG_IF_ALLOWED("didReceiveResponse: Should wait for message from WebContent process before continuing resource load (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
358 return ShouldContinueDidReceiveResponse::No;
361 void NetworkResourceLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedEncodedDataLength)
363 if (!m_hasReceivedData) {
364 RELEASE_LOG_IF_ALLOWED("didReceiveBuffer: Started receiving data (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
365 m_hasReceivedData = true;
368 #if ENABLE(NETWORK_CACHE)
369 ASSERT(!m_cacheEntryForValidation);
371 if (m_bufferedDataForCache) {
372 // Prevent memory growth in case of streaming data.
373 const size_t maximumCacheBufferSize = 10 * 1024 * 1024;
374 if (m_bufferedDataForCache->size() + buffer->size() <= maximumCacheBufferSize)
375 m_bufferedDataForCache->append(buffer.get());
377 m_bufferedDataForCache = nullptr;
380 // FIXME: At least on OS X Yosemite we always get -1 from the resource handle.
381 unsigned encodedDataLength = reportedEncodedDataLength >= 0 ? reportedEncodedDataLength : buffer->size();
383 m_bytesReceived += buffer->size();
384 if (m_bufferedData) {
385 m_bufferedData->append(buffer.get());
386 m_bufferedDataEncodedDataLength += encodedDataLength;
387 startBufferingTimerIfNeeded();
390 sendBuffer(buffer, encodedDataLength);
393 void NetworkResourceLoader::didFinishLoading(double finishTime)
395 RELEASE_LOG_IF_ALLOWED("didFinishLoading: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
397 #if ENABLE(NETWORK_CACHE)
398 if (m_cacheEntryForValidation) {
400 ASSERT(m_response.httpStatusCode() == 304);
401 LOG(NetworkCache, "(NetworkProcess) revalidated");
402 didRetrieveCacheEntry(WTFMove(m_cacheEntryForValidation));
408 sendReplyToSynchronousRequest(*m_synchronousLoadData, m_bufferedData.get());
410 if (m_bufferedData && !m_bufferedData->isEmpty()) {
411 // FIXME: Pass a real value or remove the encoded data size feature.
412 sendBuffer(*m_bufferedData, -1);
414 send(Messages::WebResourceLoader::DidFinishResourceLoad(finishTime));
417 #if ENABLE(NETWORK_CACHE)
418 tryStoreAsCacheEntry();
424 void NetworkResourceLoader::didFailLoading(const ResourceError& error)
426 RELEASE_LOG_IF_ALLOWED("didFailLoading: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", isTimeout = %d, isCancellation = %d, errCode = %d)", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier, error.isTimeout(), error.isCancellation(), error.errorCode());
428 ASSERT(!error.isNull());
430 #if ENABLE(NETWORK_CACHE)
431 m_cacheEntryForValidation = nullptr;
434 if (isSynchronous()) {
435 m_synchronousLoadData->error = error;
436 sendReplyToSynchronousRequest(*m_synchronousLoadData, nullptr);
437 } else if (auto* connection = messageSenderConnection())
438 connection->send(Messages::WebResourceLoader::DidFailResourceLoad(error), messageSenderDestinationID());
443 void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request, WebCore::ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse)
447 if (isSynchronous()) {
448 ResourceRequest overridenRequest = redirectRequest;
449 // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
450 // This includes at least updating host records, and comparing the current request instead of the original request here.
451 if (!protocolHostAndPortAreEqual(originalRequest().url(), redirectRequest.url())) {
452 ASSERT(m_synchronousLoadData->error.isNull());
453 m_synchronousLoadData->error = SynchronousLoaderClient::platformBadResponseError();
454 m_networkLoad->clearCurrentRequest();
455 overridenRequest = ResourceRequest();
457 continueWillSendRequest(WTFMove(overridenRequest));
460 send(Messages::WebResourceLoader::WillSendRequest(redirectRequest, redirectResponse));
462 #if ENABLE(NETWORK_CACHE)
463 if (canUseCachedRedirect(request))
464 NetworkCache::singleton().storeRedirect(request, redirectResponse, redirectRequest);
466 UNUSED_PARAM(request);
470 void NetworkResourceLoader::continueWillSendRequest(ResourceRequest&& newRequest)
472 RELEASE_LOG_IF_ALLOWED("continueWillSendRequest: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
474 // If there is a match in the network cache, we need to reuse the original cache policy.
475 newRequest.setCachePolicy(originalRequest().cachePolicy());
477 #if ENABLE(NETWORK_CACHE)
478 if (m_isWaitingContinueWillSendRequestForCachedRedirect) {
479 LOG(NetworkCache, "(NetworkProcess) Retrieving cached redirect");
481 if (canUseCachedRedirect(newRequest))
482 retrieveCacheEntry(newRequest);
484 startNetworkLoad(newRequest);
486 m_isWaitingContinueWillSendRequestForCachedRedirect = false;
492 m_networkLoad->continueWillSendRequest(WTFMove(newRequest));
495 void NetworkResourceLoader::continueDidReceiveResponse()
497 // FIXME: Remove this check once BlobResourceHandle implements didReceiveResponseAsync correctly.
498 // Currently, it does not wait for response, so the load is likely to finish before continueDidReceiveResponse.
500 m_networkLoad->continueDidReceiveResponse();
503 void NetworkResourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
505 if (!isSynchronous())
506 send(Messages::WebResourceLoader::DidSendData(bytesSent, totalBytesToBeSent));
509 void NetworkResourceLoader::startBufferingTimerIfNeeded()
513 if (m_bufferingTimer.isActive())
515 m_bufferingTimer.startOneShot(m_parameters.maximumBufferingTime);
518 void NetworkResourceLoader::bufferingTimerFired()
520 ASSERT(m_bufferedData);
521 ASSERT(m_networkLoad);
523 if (m_bufferedData->isEmpty())
526 IPC::SharedBufferDataReference dataReference(m_bufferedData.get());
527 size_t encodedLength = m_bufferedDataEncodedDataLength;
529 m_bufferedData = SharedBuffer::create();
530 m_bufferedDataEncodedDataLength = 0;
532 send(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedLength));
535 void NetworkResourceLoader::sendBuffer(SharedBuffer& buffer, size_t encodedDataLength)
537 ASSERT(!isSynchronous());
539 IPC::SharedBufferDataReference dataReference(&buffer);
540 send(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedDataLength));
543 #if ENABLE(NETWORK_CACHE)
544 void NetworkResourceLoader::tryStoreAsCacheEntry()
546 if (!canUseCache(m_networkLoad->currentRequest()))
548 if (!m_bufferedDataForCache)
551 NetworkCache::singleton().store(m_networkLoad->currentRequest(), m_response, WTFMove(m_bufferedDataForCache), [loader = makeRef(*this)](auto& mappedBody) mutable {
552 #if ENABLE(SHAREABLE_RESOURCE)
553 if (mappedBody.shareableResourceHandle.isNull())
555 LOG(NetworkCache, "(NetworkProcess) sending DidCacheResource");
556 loader->send(Messages::NetworkProcessConnection::DidCacheResource(loader->originalRequest(), mappedBody.shareableResourceHandle, loader->sessionID()));
561 void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
563 if (isSynchronous()) {
564 m_synchronousLoadData->response = entry->response();
565 sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer());
567 bool needsContinueDidReceiveResponseMessage = isMainResource();
568 send(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage));
570 #if ENABLE(SHAREABLE_RESOURCE)
571 if (!entry->shareableResourceHandle().isNull())
572 send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime()));
575 sendBuffer(*entry->buffer(), entry->buffer()->size());
576 send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime()));
577 #if ENABLE(SHAREABLE_RESOURCE)
585 void NetworkResourceLoader::validateCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
587 ASSERT(!m_networkLoad);
589 // If the request is already conditional then the revalidation was not triggered by the disk cache
590 // and we should not overwrite the existing conditional headers.
591 ResourceRequest revalidationRequest = originalRequest();
592 if (!revalidationRequest.isConditional()) {
593 String eTag = entry->response().httpHeaderField(HTTPHeaderName::ETag);
594 String lastModified = entry->response().httpHeaderField(HTTPHeaderName::LastModified);
596 revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag);
597 if (!lastModified.isEmpty())
598 revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified);
601 m_cacheEntryForValidation = WTFMove(entry);
603 startNetworkLoad(revalidationRequest);
606 void NetworkResourceLoader::dispatchWillSendRequestForCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
608 ASSERT(entry->redirectRequest());
609 LOG(NetworkCache, "(NetworkProcess) Executing cached redirect");
612 send(Messages::WebResourceLoader::WillSendRequest(*entry->redirectRequest(), entry->response()));
613 m_isWaitingContinueWillSendRequestForCachedRedirect = true;
617 IPC::Connection* NetworkResourceLoader::messageSenderConnection()
619 return &connectionToWebProcess().connection();
622 void NetworkResourceLoader::consumeSandboxExtensions()
624 ASSERT(!m_didConsumeSandboxExtensions);
626 for (auto& extension : m_parameters.requestBodySandboxExtensions)
627 extension->consume();
629 if (auto& extension = m_parameters.resourceSandboxExtension)
630 extension->consume();
632 for (auto& fileReference : m_fileReferences)
633 fileReference->prepareForFileAccess();
635 m_didConsumeSandboxExtensions = true;
638 void NetworkResourceLoader::invalidateSandboxExtensions()
640 if (m_didConsumeSandboxExtensions) {
641 for (auto& extension : m_parameters.requestBodySandboxExtensions)
643 if (auto& extension = m_parameters.resourceSandboxExtension)
645 for (auto& fileReference : m_fileReferences)
646 fileReference->revokeFileAccess();
648 m_didConsumeSandboxExtensions = false;
651 m_fileReferences.clear();
654 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
655 void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(const ProtectionSpace& protectionSpace)
657 NetworkProcess::singleton().canAuthenticateAgainstProtectionSpace(*this, protectionSpace);
660 void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result)
663 m_networkLoad->continueCanAuthenticateAgainstProtectionSpace(result);
667 bool NetworkResourceLoader::isAlwaysOnLoggingAllowed() const
669 return sessionID().isAlwaysOnLoggingAllowed();
672 } // namespace WebKit