diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/loader/ResourceLoader.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/loader/ResourceLoader.cpp')
-rw-r--r-- | Source/WebCore/loader/ResourceLoader.cpp | 321 |
1 files changed, 81 insertions, 240 deletions
diff --git a/Source/WebCore/loader/ResourceLoader.cpp b/Source/WebCore/loader/ResourceLoader.cpp index d0c820ad4..ebef76f47 100644 --- a/Source/WebCore/loader/ResourceLoader.cpp +++ b/Source/WebCore/loader/ResourceLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007, 2010-2011, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. * (C) 2007 Graham Dennis (graham.dennis@gmail.com) * * Redistribution and use in source and binary forms, with or without @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -31,32 +31,26 @@ #include "ResourceLoader.h" #include "ApplicationCacheHost.h" +#include "AsyncFileStream.h" #include "AuthenticationChallenge.h" -#include "DataURLDecoder.h" -#include "DiagnosticLoggingClient.h" -#include "DiagnosticLoggingKeys.h" #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" #include "InspectorInstrumentation.h" #include "LoaderStrategy.h" -#include "MainFrame.h" #include "Page.h" #include "PlatformStrategies.h" #include "ProgressTracker.h" +#include "ResourceBuffer.h" #include "ResourceError.h" #include "ResourceHandle.h" +#include "ResourceLoadScheduler.h" #include "SecurityOrigin.h" #include "Settings.h" #include "SharedBuffer.h" #include <wtf/Ref.h> -#if ENABLE(CONTENT_EXTENSIONS) -#include "ResourceLoadInfo.h" -#include "UserContentController.h" -#endif - namespace WebCore { ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options) @@ -66,12 +60,8 @@ ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options) , m_reachedTerminalState(false) , m_notifiedLoadComplete(false) , m_cancellationStatus(NotCancelled) - , m_defersLoading(options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && frame->page()->defersLoading()) + , m_defersLoading(frame->page()->defersLoading()) , m_options(options) - , m_isQuickLookResource(false) -#if ENABLE(CONTENT_EXTENSIONS) - , m_resourceType(ResourceType::Invalid) -#endif { } @@ -80,17 +70,6 @@ ResourceLoader::~ResourceLoader() ASSERT(m_reachedTerminalState); } -void ResourceLoader::finishNetworkLoad() -{ - platformStrategies()->loaderStrategy()->remove(this); - - if (m_handle) { - ASSERT(m_handle->client() == this); - m_handle->clearClient(); - m_handle = nullptr; - } -} - void ResourceLoader::releaseResources() { ASSERT(!m_reachedTerminalState); @@ -101,18 +80,25 @@ void ResourceLoader::releaseResources() // has been deallocated and also to avoid reentering this method. Ref<ResourceLoader> protect(*this); - m_frame = nullptr; - m_documentLoader = nullptr; + m_frame = 0; + m_documentLoader = 0; // We need to set reachedTerminalState to true before we release // the resources to prevent a double dealloc of WebView <rdar://problem/4372628> m_reachedTerminalState = true; - finishNetworkLoad(); - + platformStrategies()->loaderStrategy()->resourceLoadScheduler()->remove(this); m_identifier = 0; - m_resourceData = nullptr; + if (m_handle) { + // Clear out the ResourceHandle's client so that it doesn't try to call + // us back after we release it, unless it has been replaced by someone else. + if (m_handle->client() == this) + m_handle->setClient(0); + m_handle = 0; + } + + m_resourceData = 0; m_deferredRequest = ResourceRequest(); } @@ -134,9 +120,8 @@ bool ResourceLoader::init(const ResourceRequest& r) } #endif - m_defersLoading = m_options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && m_frame->page()->defersLoading(); - - if (m_options.securityCheck() == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) { + m_defersLoading = m_frame->page()->defersLoading(); + if (m_options.securityCheck == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) { FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string()); releaseResources(); return false; @@ -152,7 +137,7 @@ bool ResourceLoader::init(const ResourceRequest& r) clientRequest.setFirstPartyForCookies(document->firstPartyForCookies()); } - willSendRequestInternal(clientRequest, ResourceResponse()); + willSendRequest(clientRequest, ResourceResponse()); #if PLATFORM(IOS) // If this ResourceLoader was stopped as a result of willSendRequest, bail out. @@ -169,30 +154,11 @@ bool ResourceLoader::init(const ResourceRequest& r) return true; } -void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer) -{ - Ref<ResourceLoader> protect(*this); - - didReceiveResponse(response); - if (reachedTerminalState()) - return; - - if (buffer) { - unsigned size = buffer->size(); - didReceiveBuffer(buffer.release(), size, DataPayloadWholeResource); - if (reachedTerminalState()) - return; - } - - didFinishLoading(0); -} - void ResourceLoader::start() { ASSERT(!m_handle); ASSERT(!m_request.isNull()); ASSERT(m_deferredRequest.isNull()); - ASSERT(frameLoader()); #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML) if (m_documentLoader->scheduleArchiveLoad(this, m_request)) @@ -207,22 +173,12 @@ void ResourceLoader::start() return; } - if (m_reachedTerminalState) - return; - - if (m_request.url().protocolIsData()) { - loadDataURL(); - return; - } - - m_handle = ResourceHandle::create(frameLoader()->networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent() == SniffContent); + if (!m_reachedTerminalState) + m_handle = ResourceHandle::create(m_frame->loader().networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent == SniffContent); } void ResourceLoader::setDefersLoading(bool defers) { - if (m_options.defersLoadingPolicy() == DefersLoadingPolicy::DisallowDefersLoading) - return; - m_defersLoading = defers; if (m_handle) m_handle->setDefersLoading(defers); @@ -231,80 +187,37 @@ void ResourceLoader::setDefersLoading(bool defers) m_deferredRequest = ResourceRequest(); start(); } - - platformStrategies()->loaderStrategy()->setDefersLoading(this, defers); } FrameLoader* ResourceLoader::frameLoader() const { if (!m_frame) - return nullptr; + return 0; return &m_frame->loader(); } -void ResourceLoader::loadDataURL() -{ - auto url = m_request.url(); - ASSERT(url.protocolIsData()); - - RefPtr<ResourceLoader> loader(this); - DataURLDecoder::ScheduleContext scheduleContext; -#if HAVE(RUNLOOP_TIMER) - if (auto* scheduledPairs = m_frame->page()->scheduledRunLoopPairs()) - scheduleContext.scheduledPairs = *scheduledPairs; -#endif - DataURLDecoder::decode(url, scheduleContext, [loader, url] (Optional<DataURLDecoder::Result> decodeResult) { - if (loader->reachedTerminalState()) - return; - if (!decodeResult) { - loader->didFail(ResourceError(errorDomainWebKitInternal, 0, url, "Data URL decoding failed")); - return; - } - if (loader->wasCancelled()) - return; - auto& result = decodeResult.value(); - auto dataSize = result.data->size(); - - ResourceResponse dataResponse { url, result.mimeType, dataSize, result.charset }; - loader->didReceiveResponse(dataResponse); - - if (!loader->reachedTerminalState() && dataSize) - loader->didReceiveBuffer(result.data.get(), dataSize, DataPayloadWholeResource); - - if (!loader->reachedTerminalState()) - loader->didFinishLoading(currentTime()); - }); -} - void ResourceLoader::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy) { - m_options.setDataBufferingPolicy(dataBufferingPolicy); + m_options.dataBufferingPolicy = dataBufferingPolicy; // Reset any already buffered data if (dataBufferingPolicy == DoNotBufferData) - m_resourceData = nullptr; + m_resourceData = 0; } -void ResourceLoader::willSwitchToSubstituteResource() -{ - ASSERT(!m_documentLoader->isSubstituteLoadPending(this)); - platformStrategies()->loaderStrategy()->remove(this); - if (m_handle) - m_handle->cancel(); -} void ResourceLoader::addDataOrBuffer(const char* data, unsigned length, SharedBuffer* buffer, DataPayloadType dataPayloadType) { - if (m_options.dataBufferingPolicy() == DoNotBufferData) + if (m_options.dataBufferingPolicy == DoNotBufferData) return; if (dataPayloadType == DataPayloadWholeResource) { - m_resourceData = buffer ? buffer : SharedBuffer::create(data, length); + m_resourceData = buffer ? ResourceBuffer::adoptSharedBuffer(buffer) : ResourceBuffer::create(data, length); return; } if (!m_resourceData) - m_resourceData = buffer ? buffer : SharedBuffer::create(data, length); + m_resourceData = buffer ? ResourceBuffer::adoptSharedBuffer(buffer) : ResourceBuffer::create(data, length); else { if (buffer) m_resourceData->append(buffer); @@ -324,15 +237,26 @@ bool ResourceLoader::isSubresourceLoader() return false; } -void ResourceLoader::willSendRequestInternal(ResourceRequest& request, const ResourceResponse& redirectResponse) +void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse) { // Protect this in this delegate method since the additional processing can do // anything including possibly derefing this; one example of this is Radar 3266216. Ref<ResourceLoader> protect(*this); ASSERT(!m_reachedTerminalState); -#if ENABLE(CONTENT_EXTENSIONS) - ASSERT(m_resourceType != ResourceType::Invalid); + +#if PLATFORM(IOS) + // Ensure an identifier is always set. This ensures that this assetion is not hit: + // <rdar://problem/11059794> ASSERTION FAILED: !HashTranslator::equal(KeyTraits::emptyValue(), key) in WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace loading the attached web archive + // This is not needed in WebKit2, as it doesn't use m_identifier in WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace + if (!m_identifier) { + m_identifier = m_frame->page()->progress().createUniqueIdentifier(); + frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request); + + // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out + if (m_reachedTerminalState) + return; + } #endif // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests). @@ -342,91 +266,30 @@ void ResourceLoader::willSendRequestInternal(ResourceRequest& request, const Res createdResourceIdentifier = true; } -#if ENABLE(CONTENT_EXTENSIONS) - if (frameLoader()) { - Page* page = frameLoader()->frame().page(); - if (page && m_documentLoader) { - auto* userContentController = page->userContentController(); - if (userContentController && userContentController->processContentExtensionRulesForLoad(request, m_resourceType, *m_documentLoader) == ContentExtensions::BlockedStatus::Blocked) - request = { }; - } - } -#endif - - if (request.isNull()) { - didFail(cannotShowURLError()); - return; - } - - if (m_options.sendLoadCallbacks() == SendCallbacks) { + if (m_options.sendLoadCallbacks == SendCallbacks) { if (createdResourceIdentifier) frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request); -#if PLATFORM(IOS) - // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out - if (m_reachedTerminalState) - return; -#endif - frameLoader()->notifier().willSendRequest(this, request, redirectResponse); } +#if ENABLE(INSPECTOR) else InspectorInstrumentation::willSendRequest(m_frame.get(), m_identifier, m_frame->loader().documentLoader(), request, redirectResponse); +#endif - bool isRedirect = !redirectResponse.isNull(); - if (isRedirect) - platformStrategies()->loaderStrategy()->crossOriginRedirectReceived(this, request.url()); + if (!redirectResponse.isNull()) + platformStrategies()->loaderStrategy()->resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url()); m_request = request; - if (isRedirect) { - auto& redirectURL = request.url(); - if (!m_documentLoader->isCommitted()) - frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad(); - - if (redirectURL.protocolIsData()) { - // Handle data URL decoding locally. - finishNetworkLoad(); - loadDataURL(); - } - } -} - -void ResourceLoader::willSendRequest(ResourceRequest&& request, const ResourceResponse& redirectResponse, std::function<void(ResourceRequest&&)>&& callback) -{ - willSendRequestInternal(request, redirectResponse); - callback(WTFMove(request)); + if (!redirectResponse.isNull() && !m_documentLoader->isCommitted()) + frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad(); } void ResourceLoader::didSendData(unsigned long long, unsigned long long) { } -static void logResourceResponseSource(Frame* frame, ResourceResponse::Source source) -{ - if (!frame) - return; - - String sourceKey; - switch (source) { - case ResourceResponse::Source::Network: - sourceKey = DiagnosticLoggingKeys::networkKey(); - break; - case ResourceResponse::Source::DiskCache: - sourceKey = DiagnosticLoggingKeys::diskCacheKey(); - break; - case ResourceResponse::Source::DiskCacheAfterValidation: - sourceKey = DiagnosticLoggingKeys::diskCacheAfterValidationKey(); - break; - case ResourceResponse::Source::MemoryCache: - case ResourceResponse::Source::MemoryCacheAfterValidation: - case ResourceResponse::Source::Unknown: - return; - } - - frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceResponseKey(), DiagnosticLoggingKeys::sourceKey(), sourceKey, ShouldSample::Yes); -} - void ResourceLoader::didReceiveResponse(const ResourceResponse& r) { ASSERT(!m_reachedTerminalState); @@ -435,20 +298,12 @@ void ResourceLoader::didReceiveResponse(const ResourceResponse& r) // anything including possibly derefing this; one example of this is Radar 3266216. Ref<ResourceLoader> protect(*this); - logResourceResponseSource(m_frame.get(), r.source()); - m_response = r; - if (m_response.isHttpVersion0_9()) { - String message = "Sandboxing '" + m_response.url().string() + "' because it is using HTTP/0.9."; - m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, m_identifier); - frameLoader()->forceSandboxFlags(SandboxScripts | SandboxPlugins); - } - if (FormData* data = m_request.httpBody()) data->removeGeneratedFilesIfNeeded(); - if (m_options.sendLoadCallbacks() == SendCallbacks) + if (m_options.sendLoadCallbacks == SendCallbacks) frameLoader()->notifier().didReceiveResponse(this, m_response); } @@ -483,10 +338,19 @@ void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, P // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. // However, with today's computers and networking speeds, this won't happen in practice. // Could be an issue with a giant local file. - if (m_options.sendLoadCallbacks() == SendCallbacks && m_frame) + if (m_options.sendLoadCallbacks == SendCallbacks && m_frame) frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength)); } +void ResourceLoader::willStopBufferingData(const char* data, unsigned length) +{ + if (m_options.dataBufferingPolicy == DoNotBufferData) + return; + + ASSERT(!m_resourceData); + m_resourceData = ResourceBuffer::create(data, length); +} + void ResourceLoader::didFinishLoading(double finishTime) { didFinishLoadingOnePart(finishTime); @@ -509,7 +373,7 @@ void ResourceLoader::didFinishLoadingOnePart(double finishTime) if (m_notifiedLoadComplete) return; m_notifiedLoadComplete = true; - if (m_options.sendLoadCallbacks() == SendCallbacks) + if (m_options.sendLoadCallbacks == SendCallbacks) frameLoader()->notifier().didFinishLoad(this, finishTime); } @@ -535,10 +399,16 @@ void ResourceLoader::cleanupForError(const ResourceError& error) if (m_notifiedLoadComplete) return; m_notifiedLoadComplete = true; - if (m_options.sendLoadCallbacks() == SendCallbacks && m_identifier) + if (m_options.sendLoadCallbacks == SendCallbacks && m_identifier) frameLoader()->notifier().didFailToLoad(this, error); } +void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority) +{ + if (handle()) + handle()->didChangePriority(loadPriority); +} + void ResourceLoader::cancel() { cancel(ResourceError()); @@ -575,7 +445,7 @@ void ResourceLoader::cancel(const ResourceError& error) m_documentLoader->cancelPendingSubstituteLoad(this); if (m_handle) { m_handle->cancel(); - m_handle = nullptr; + m_handle = 0; } cleanupForError(nonNullError); } @@ -613,7 +483,7 @@ void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, { if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse)) return; - willSendRequestInternal(request, redirectResponse); + willSendRequest(request, redirectResponse); } void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) @@ -630,12 +500,16 @@ void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength) { + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier(), encodedDataLength); didReceiveData(data, length, encodedDataLength, DataPayloadBytes); + InspectorInstrumentation::didReceiveResourceData(cookie); } void ResourceLoader::didReceiveBuffer(ResourceHandle*, PassRefPtr<SharedBuffer> buffer, int encodedDataLength) { + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier(), encodedDataLength); didReceiveBuffer(buffer, encodedDataLength, DataPayloadBytes); + InspectorInstrumentation::didReceiveResourceData(cookie); } void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime) @@ -662,37 +536,32 @@ void ResourceLoader::cannotShowURL(ResourceHandle*) bool ResourceLoader::shouldUseCredentialStorage() { - if (m_options.allowCredentials() == DoNotAllowStoredCredentials) + if (m_options.allowCredentials == DoNotAllowStoredCredentials) return false; Ref<ResourceLoader> protect(*this); return frameLoader()->client().shouldUseCredentialStorage(documentLoader(), identifier()); } -bool ResourceLoader::isAllowedToAskUserForCredentials() const -{ - return m_options.clientCredentialPolicy() == AskClientForAllCredentials || (m_options.clientCredentialPolicy() == DoNotAskClientForCrossOriginCredentials && m_frame->document()->securityOrigin()->canRequest(originalRequest().url())); -} - void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) { - ASSERT(m_handle->hasAuthenticationChallenge()); + ASSERT(handle()->hasAuthenticationChallenge()); // Protect this in this delegate method since the additional processing can do // anything including possibly derefing this; one example of this is Radar 3266216. Ref<ResourceLoader> protect(*this); - if (m_options.allowCredentials() == AllowStoredCredentials) { - if (isAllowedToAskUserForCredentials()) { + if (m_options.allowCredentials == AllowStoredCredentials) { + if (m_options.clientCredentialPolicy == AskClientForAllCredentials || (m_options.clientCredentialPolicy == DoNotAskClientForCrossOriginCredentials && m_frame->document()->securityOrigin()->canRequest(originalRequest().url()))) { frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge); return; } } // Only these platforms provide a way to continue without credentials. // If we can't continue with credentials, we need to cancel the load altogether. -#if PLATFORM(COCOA) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL) +#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL) challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge); - ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge()); + ASSERT(!handle() || !handle()->hasAuthenticationChallenge()); #else didFail(blockedError()); #endif @@ -707,22 +576,18 @@ void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChalle } #if USE(PROTECTION_SPACE_AUTH_CALLBACK) - bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) { Ref<ResourceLoader> protect(*this); return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace); } - #endif #if PLATFORM(IOS) - RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*) { return frameLoader()->connectionProperties(this); } - #endif void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) @@ -730,28 +595,4 @@ void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) cancel(); } -#if PLATFORM(COCOA) && !USE(CFNETWORK) - -void ResourceLoader::schedule(SchedulePair& pair) -{ - if (m_handle) - m_handle->schedule(pair); -} - -void ResourceLoader::unschedule(SchedulePair& pair) -{ - if (m_handle) - m_handle->unschedule(pair); -} - -#endif - -#if USE(QUICK_LOOK) -void ResourceLoader::didCreateQuickLookHandle(QuickLookHandle& handle) -{ - m_isQuickLookResource = true; - frameLoader()->client().didCreateQuickLookHandle(handle); -} -#endif - } |