2 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "ResourceLoader.h"
33 #include "ApplicationCacheHost.h"
34 #include "AuthenticationChallenge.h"
35 #include "DataURLDecoder.h"
36 #include "DiagnosticLoggingClient.h"
37 #include "DiagnosticLoggingKeys.h"
38 #include "DocumentLoader.h"
40 #include "FrameLoader.h"
41 #include "FrameLoaderClient.h"
42 #include "InspectorInstrumentation.h"
43 #include "LoaderStrategy.h"
44 #include "MainFrame.h"
46 #include "PlatformStrategies.h"
47 #include "ProgressTracker.h"
48 #include "ResourceError.h"
49 #include "ResourceHandle.h"
50 #include "ResourceLoadScheduler.h"
51 #include "SecurityOrigin.h"
53 #include "SharedBuffer.h"
56 #if ENABLE(CONTENT_EXTENSIONS)
57 #include "ResourceLoadInfo.h"
58 #include "UserContentController.h"
63 ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options)
65 , m_documentLoader(frame->loader().activeDocumentLoader())
67 , m_reachedTerminalState(false)
68 , m_notifiedLoadComplete(false)
69 , m_cancellationStatus(NotCancelled)
70 , m_defersLoading(frame->page()->defersLoading())
72 , m_isQuickLookResource(false)
73 #if ENABLE(CONTENT_EXTENSIONS)
74 , m_resourceType(ResourceType::Invalid)
79 ResourceLoader::~ResourceLoader()
81 ASSERT(m_reachedTerminalState);
84 void ResourceLoader::finishNetworkLoad()
86 platformStrategies()->loaderStrategy()->resourceLoadScheduler()->remove(this);
89 ASSERT(m_handle->client() == this);
90 m_handle->clearClient();
95 void ResourceLoader::releaseResources()
97 ASSERT(!m_reachedTerminalState);
99 // It's possible that when we release the handle, it will be
100 // deallocated and release the last reference to this object.
101 // We need to retain to avoid accessing the object after it
102 // has been deallocated and also to avoid reentering this method.
103 Ref<ResourceLoader> protect(*this);
106 m_documentLoader = nullptr;
108 // We need to set reachedTerminalState to true before we release
109 // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
110 m_reachedTerminalState = true;
116 m_resourceData = nullptr;
117 m_deferredRequest = ResourceRequest();
120 bool ResourceLoader::init(const ResourceRequest& r)
123 ASSERT(m_request.isNull());
124 ASSERT(m_deferredRequest.isNull());
125 ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
127 ResourceRequest clientRequest(r);
130 // If the documentLoader was detached while this ResourceLoader was waiting its turn
131 // in ResourceLoadScheduler queue, don't continue.
132 if (!m_documentLoader->frame()) {
138 m_defersLoading = m_frame->page()->defersLoading();
139 if (m_options.securityCheck() == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) {
140 FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string());
145 // https://bugs.webkit.org/show_bug.cgi?id=26391
146 // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
147 // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
148 // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that
149 // method, we need to make sure there is always a 1st party for cookies set.
150 if (clientRequest.firstPartyForCookies().isNull()) {
151 if (Document* document = m_frame->document())
152 clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
155 willSendRequestInternal(clientRequest, ResourceResponse());
158 // If this ResourceLoader was stopped as a result of willSendRequest, bail out.
159 if (m_reachedTerminalState)
163 if (clientRequest.isNull()) {
168 m_originalRequest = m_request = clientRequest;
172 void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer)
174 Ref<ResourceLoader> protect(*this);
176 didReceiveResponse(response);
177 if (reachedTerminalState())
181 unsigned size = buffer->size();
182 didReceiveBuffer(buffer.release(), size, DataPayloadWholeResource);
183 if (reachedTerminalState())
190 void ResourceLoader::start()
193 ASSERT(!m_request.isNull());
194 ASSERT(m_deferredRequest.isNull());
195 ASSERT(frameLoader());
197 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
198 if (m_documentLoader->scheduleArchiveLoad(this, m_request))
202 if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url()))
205 if (m_defersLoading) {
206 m_deferredRequest = m_request;
210 if (m_reachedTerminalState)
213 if (m_request.url().protocolIsData()) {
218 m_handle = ResourceHandle::create(frameLoader()->networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent() == SniffContent);
221 void ResourceLoader::setDefersLoading(bool defers)
223 m_defersLoading = defers;
225 m_handle->setDefersLoading(defers);
226 if (!defers && !m_deferredRequest.isNull()) {
227 m_request = m_deferredRequest;
228 m_deferredRequest = ResourceRequest();
232 platformStrategies()->loaderStrategy()->resourceLoadScheduler()->setDefersLoading(this, defers);
235 FrameLoader* ResourceLoader::frameLoader() const
239 return &m_frame->loader();
242 void ResourceLoader::loadDataURL()
244 auto url = m_request.url();
245 ASSERT(url.protocolIsData());
247 RefPtr<ResourceLoader> loader(this);
248 DataURLDecoder::decode(url, [loader, url] (Optional<DataURLDecoder::Result> decodeResult) {
249 if (loader->reachedTerminalState())
252 loader->didFail(ResourceError(errorDomainWebKitInternal, 0, url.string(), "Data URL decoding failed"));
255 auto& result = decodeResult.value();
256 auto dataSize = result.data->size();
258 ResourceResponse dataResponse { url, result.mimeType, dataSize, result.charset };
259 loader->didReceiveResponse(dataResponse);
261 if (!loader->reachedTerminalState() && dataSize)
262 loader->didReceiveBuffer(result.data.get(), dataSize, DataPayloadWholeResource);
264 if (!loader->reachedTerminalState())
265 loader->didFinishLoading(currentTime());
269 void ResourceLoader::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
271 m_options.setDataBufferingPolicy(dataBufferingPolicy);
273 // Reset any already buffered data
274 if (dataBufferingPolicy == DoNotBufferData)
275 m_resourceData = nullptr;
278 void ResourceLoader::willSwitchToSubstituteResource()
280 ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
281 platformStrategies()->loaderStrategy()->resourceLoadScheduler()->remove(this);
286 void ResourceLoader::addDataOrBuffer(const char* data, unsigned length, SharedBuffer* buffer, DataPayloadType dataPayloadType)
288 if (m_options.dataBufferingPolicy() == DoNotBufferData)
291 if (dataPayloadType == DataPayloadWholeResource) {
292 m_resourceData = buffer ? buffer : SharedBuffer::create(data, length);
297 m_resourceData = buffer ? buffer : SharedBuffer::create(data, length);
300 m_resourceData->append(buffer);
302 m_resourceData->append(data, length);
306 void ResourceLoader::clearResourceData()
309 m_resourceData->clear();
312 bool ResourceLoader::isSubresourceLoader()
317 void ResourceLoader::willSendRequestInternal(ResourceRequest& request, const ResourceResponse& redirectResponse)
319 // Protect this in this delegate method since the additional processing can do
320 // anything including possibly derefing this; one example of this is Radar 3266216.
321 Ref<ResourceLoader> protect(*this);
323 ASSERT(!m_reachedTerminalState);
324 #if ENABLE(CONTENT_EXTENSIONS)
325 ASSERT(m_resourceType != ResourceType::Invalid);
328 // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
329 bool createdResourceIdentifier = false;
331 m_identifier = m_frame->page()->progress().createUniqueIdentifier();
332 createdResourceIdentifier = true;
335 #if ENABLE(CONTENT_EXTENSIONS)
337 Page* page = frameLoader()->frame().page();
338 if (page && m_documentLoader) {
339 auto* userContentController = page->userContentController();
340 if (userContentController)
341 userContentController->processContentExtensionRulesForLoad(*page, request, m_resourceType, *m_documentLoader);
346 if (request.isNull()) {
347 didFail(cannotShowURLError());
351 if (m_options.sendLoadCallbacks() == SendCallbacks) {
352 if (createdResourceIdentifier)
353 frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
356 // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out
357 if (m_reachedTerminalState)
361 frameLoader()->notifier().willSendRequest(this, request, redirectResponse);
364 InspectorInstrumentation::willSendRequest(m_frame.get(), m_identifier, m_frame->loader().documentLoader(), request, redirectResponse);
366 bool isRedirect = !redirectResponse.isNull();
368 platformStrategies()->loaderStrategy()->resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url());
373 auto& redirectURL = request.url();
374 if (!m_documentLoader->isCommitted())
375 frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad();
377 if (redirectURL.protocolIsData()) {
378 // Handle data URL decoding locally.
385 void ResourceLoader::willSendRequest(ResourceRequest&& request, const ResourceResponse& redirectResponse, std::function<void(ResourceRequest&&)>&& callback)
387 willSendRequestInternal(request, redirectResponse);
388 callback(WTF::move(request));
391 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
395 static void logResourceResponseSource(Frame* frame, ResourceResponse::Source source)
402 case ResourceResponse::Source::Network:
403 sourceKey = DiagnosticLoggingKeys::networkKey();
405 case ResourceResponse::Source::DiskCache:
406 sourceKey = DiagnosticLoggingKeys::diskCacheKey();
408 case ResourceResponse::Source::DiskCacheAfterValidation:
409 sourceKey = DiagnosticLoggingKeys::diskCacheAfterValidationKey();
411 case ResourceResponse::Source::MemoryCache:
412 case ResourceResponse::Source::MemoryCacheAfterValidation:
413 case ResourceResponse::Source::Unknown:
417 frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceResponseKey(), DiagnosticLoggingKeys::sourceKey(), sourceKey, ShouldSample::Yes);
420 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
422 ASSERT(!m_reachedTerminalState);
424 // Protect this in this delegate method since the additional processing can do
425 // anything including possibly derefing this; one example of this is Radar 3266216.
426 Ref<ResourceLoader> protect(*this);
428 logResourceResponseSource(m_frame.get(), r.source());
432 if (FormData* data = m_request.httpBody())
433 data->removeGeneratedFilesIfNeeded();
435 if (m_options.sendLoadCallbacks() == SendCallbacks)
436 frameLoader()->notifier().didReceiveResponse(this, m_response);
439 void ResourceLoader::didReceiveData(const char* data, unsigned length, long long encodedDataLength, DataPayloadType dataPayloadType)
441 // The following assertions are not quite valid here, since a subclass
442 // might override didReceiveData in a way that invalidates them. This
443 // happens with the steps listed in 3266216
444 // ASSERT(con == connection);
445 // ASSERT(!m_reachedTerminalState);
447 didReceiveDataOrBuffer(data, length, 0, encodedDataLength, dataPayloadType);
450 void ResourceLoader::didReceiveBuffer(PassRefPtr<SharedBuffer> buffer, long long encodedDataLength, DataPayloadType dataPayloadType)
452 didReceiveDataOrBuffer(0, 0, buffer, encodedDataLength, dataPayloadType);
455 void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, PassRefPtr<SharedBuffer> prpBuffer, long long encodedDataLength, DataPayloadType dataPayloadType)
457 // This method should only get data+length *OR* a SharedBuffer.
458 ASSERT(!prpBuffer || (!data && !length));
460 // Protect this in this delegate method since the additional processing can do
461 // anything including possibly derefing this; one example of this is Radar 3266216.
462 Ref<ResourceLoader> protect(*this);
463 RefPtr<SharedBuffer> buffer = prpBuffer;
465 addDataOrBuffer(data, length, buffer.get(), dataPayloadType);
467 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
468 // However, with today's computers and networking speeds, this won't happen in practice.
469 // Could be an issue with a giant local file.
470 if (m_options.sendLoadCallbacks() == SendCallbacks && m_frame)
471 frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength));
474 void ResourceLoader::didFinishLoading(double finishTime)
476 didFinishLoadingOnePart(finishTime);
478 // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
479 // the resources a second time, they have been released by cancel.
485 void ResourceLoader::didFinishLoadingOnePart(double finishTime)
487 // If load has been cancelled after finishing (which could happen with a
488 // JavaScript that changes the window location), do nothing.
491 ASSERT(!m_reachedTerminalState);
493 if (m_notifiedLoadComplete)
495 m_notifiedLoadComplete = true;
496 if (m_options.sendLoadCallbacks() == SendCallbacks)
497 frameLoader()->notifier().didFinishLoad(this, finishTime);
500 void ResourceLoader::didFail(const ResourceError& error)
504 ASSERT(!m_reachedTerminalState);
506 // Protect this in this delegate method since the additional processing can do
507 // anything including possibly derefing this; one example of this is Radar 3266216.
508 Ref<ResourceLoader> protect(*this);
510 cleanupForError(error);
514 void ResourceLoader::cleanupForError(const ResourceError& error)
516 if (FormData* data = m_request.httpBody())
517 data->removeGeneratedFilesIfNeeded();
519 if (m_notifiedLoadComplete)
521 m_notifiedLoadComplete = true;
522 if (m_options.sendLoadCallbacks() == SendCallbacks && m_identifier)
523 frameLoader()->notifier().didFailToLoad(this, error);
526 void ResourceLoader::cancel()
528 cancel(ResourceError());
531 void ResourceLoader::cancel(const ResourceError& error)
533 // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
534 if (m_reachedTerminalState)
537 ResourceError nonNullError = error.isNull() ? cancelledError() : error;
539 // willCancel() and didFailToLoad() both call out to clients that might do
540 // something causing the last reference to this object to go away.
541 Ref<ResourceLoader> protect(*this);
543 // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left
544 // off without re-running willCancel()
545 if (m_cancellationStatus == NotCancelled) {
546 m_cancellationStatus = CalledWillCancel;
548 willCancel(nonNullError);
551 // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we
552 // left off without redoing any of this work.
553 if (m_cancellationStatus == CalledWillCancel) {
554 m_cancellationStatus = Cancelled;
557 m_handle->clearAuthentication();
559 m_documentLoader->cancelPendingSubstituteLoad(this);
564 cleanupForError(nonNullError);
567 // If cancel() completed from within the call to willCancel() or didFailToLoad(),
568 // we don't want to redo didCancel() or releasesResources().
569 if (m_reachedTerminalState)
572 didCancel(nonNullError);
574 if (m_cancellationStatus == FinishedCancel)
576 m_cancellationStatus = FinishedCancel;
581 ResourceError ResourceLoader::cancelledError()
583 return frameLoader()->cancelledError(m_request);
586 ResourceError ResourceLoader::blockedError()
588 return frameLoader()->client().blockedError(m_request);
591 ResourceError ResourceLoader::cannotShowURLError()
593 return frameLoader()->client().cannotShowURLError(m_request);
596 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
598 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
600 willSendRequestInternal(request, redirectResponse);
603 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
605 didSendData(bytesSent, totalBytesToBeSent);
608 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
610 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
612 didReceiveResponse(response);
615 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength)
617 didReceiveData(data, length, encodedDataLength, DataPayloadBytes);
620 void ResourceLoader::didReceiveBuffer(ResourceHandle*, PassRefPtr<SharedBuffer> buffer, int encodedDataLength)
622 didReceiveBuffer(buffer, encodedDataLength, DataPayloadBytes);
625 void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
627 didFinishLoading(finishTime);
630 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
632 if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
637 void ResourceLoader::wasBlocked(ResourceHandle*)
639 didFail(blockedError());
642 void ResourceLoader::cannotShowURL(ResourceHandle*)
644 didFail(cannotShowURLError());
647 bool ResourceLoader::shouldUseCredentialStorage()
649 if (m_options.allowCredentials() == DoNotAllowStoredCredentials)
652 Ref<ResourceLoader> protect(*this);
653 return frameLoader()->client().shouldUseCredentialStorage(documentLoader(), identifier());
656 bool ResourceLoader::isAllowedToAskUserForCredentials() const
658 return m_options.clientCredentialPolicy() == AskClientForAllCredentials || (m_options.clientCredentialPolicy() == DoNotAskClientForCrossOriginCredentials && m_frame->document()->securityOrigin()->canRequest(originalRequest().url()));
661 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
663 ASSERT(m_handle->hasAuthenticationChallenge());
665 // Protect this in this delegate method since the additional processing can do
666 // anything including possibly derefing this; one example of this is Radar 3266216.
667 Ref<ResourceLoader> protect(*this);
669 if (m_options.allowCredentials() == AllowStoredCredentials) {
670 if (isAllowedToAskUserForCredentials()) {
671 frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge);
675 // Only these platforms provide a way to continue without credentials.
676 // If we can't continue with credentials, we need to cancel the load altogether.
677 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL)
678 challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
679 ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge());
681 didFail(blockedError());
685 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
687 // Protect this in this delegate method since the additional processing can do
688 // anything including possibly derefing this; one example of this is Radar 3266216.
689 Ref<ResourceLoader> protect(*this);
690 frameLoader()->notifier().didCancelAuthenticationChallenge(this, challenge);
693 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
695 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
697 Ref<ResourceLoader> protect(*this);
698 return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
705 RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*)
707 return frameLoader()->connectionProperties(this);
712 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
719 void ResourceLoader::schedule(SchedulePair& pair)
722 m_handle->schedule(pair);
725 void ResourceLoader::unschedule(SchedulePair& pair)
728 m_handle->unschedule(pair);
734 void ResourceLoader::didCreateQuickLookHandle(QuickLookHandle& handle)
736 m_isQuickLookResource = true;
737 frameLoader()->client().didCreateQuickLookHandle(handle);