Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1231)

Unified Diff: third_party/WebKit/Source/core/fetch/ResourceLoader.cpp

Issue 2533683002: Move the code in ResourceFetcher handling calls from WebURLLoaderImpl to ResourceLoader (Closed)
Patch Set: Fix test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
index bc0dc1172332a9585ce47d6b59c4b93acc8410df..16f8e702d66df2726baa13430c9ee5c85d8f4ee2 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -29,11 +29,14 @@
#include "core/fetch/ResourceLoader.h"
+#include "core/fetch/CrossOriginAccessControl.h"
+#include "core/fetch/FetchContext.h"
#include "core/fetch/Resource.h"
#include "core/fetch/ResourceFetcher.h"
#include "platform/SharedBuffer.h"
#include "platform/exported/WrappedResourceRequest.h"
#include "platform/exported/WrappedResourceResponse.h"
+#include "platform/network/NetworkInstrumentation.h"
#include "platform/network/ResourceError.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCachePolicy.h"
@@ -59,6 +62,7 @@ ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource)
m_isCacheAwareLoadingActivated(false) {
DCHECK(m_resource);
DCHECK(m_fetcher);
+
m_resource->setLoader(this);
}
@@ -71,20 +75,19 @@ DEFINE_TRACE(ResourceLoader) {
visitor->trace(m_resource);
}
-void ResourceLoader::start(const ResourceRequest& request,
- WebTaskRunner* loadingTaskRunner,
- bool defersLoading) {
+void ResourceLoader::start(const ResourceRequest& request) {
DCHECK(!m_loader);
+
if (m_resource->options().synchronousPolicy == RequestSynchronously &&
- defersLoading) {
+ context().defersLoading()) {
cancel();
return;
}
m_loader = WTF::wrapUnique(Platform::current()->createURLLoader());
DCHECK(m_loader);
- m_loader->setDefersLoading(defersLoading);
- m_loader->setLoadingTaskRunner(loadingTaskRunner);
+ m_loader->setDefersLoading(context().defersLoading());
+ m_loader->setLoadingTaskRunner(context().loadingTaskRunner());
if (m_isCacheAwareLoadingActivated) {
// Override cache policy for cache-aware loading. If this request fails, a
@@ -102,22 +105,17 @@ void ResourceLoader::start(const ResourceRequest& request,
m_loader->loadAsynchronously(WrappedResourceRequest(request), this);
}
-void ResourceLoader::restart(const ResourceRequest& request,
- WebTaskRunner* loadingTaskRunner,
- bool defersLoading) {
+void ResourceLoader::restart(const ResourceRequest& request) {
CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously);
+
m_loader.reset();
- start(request, loadingTaskRunner, defersLoading);
+ start(request);
}
void ResourceLoader::setDefersLoading(bool defers) {
DCHECK(m_loader);
- m_loader->setDefersLoading(defers);
-}
-void ResourceLoader::didDownloadData(int length, int encodedDataLength) {
- m_fetcher->didDownloadData(m_resource.get(), length, encodedDataLength);
- m_resource->didDownloadData(length);
+ m_loader->setDefersLoading(defers);
}
void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority,
@@ -129,7 +127,7 @@ void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority,
}
void ResourceLoader::cancel() {
- didFail(
+ handleError(
ResourceError::cancelledError(m_resource->lastResourceRequest().url()));
}
@@ -138,10 +136,15 @@ void ResourceLoader::cancelForRedirectAccessCheckError(
ResourceRequestBlockedReason blockedReason) {
m_resource->willNotFollowRedirect();
- if (m_loader) {
- didFail(
+ if (m_loader)
+ handleError(
ResourceError::cancelledDueToAccessCheckError(newURL, blockedReason));
- }
+}
+
+static bool isManualRedirectFetchRequest(const ResourceRequest& request) {
+ return request.fetchRedirectMode() ==
+ WebURLRequest::FetchRedirectModeManual &&
+ request.requestContext() == WebURLRequest::RequestContextFetch;
}
bool ResourceLoader::willFollowRedirect(
@@ -152,7 +155,7 @@ bool ResourceLoader::willFollowRedirect(
if (m_isCacheAwareLoadingActivated) {
// Fail as cache miss if cached response is a redirect.
- didFail(
+ handleError(
ResourceError::cacheMissError(m_resource->lastResourceRequest().url()));
return false;
}
@@ -160,18 +163,63 @@ bool ResourceLoader::willFollowRedirect(
ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest());
const ResourceResponse& redirectResponse(
passedRedirectResponse.toResourceResponse());
+
newRequest.setRedirectStatus(
ResourceRequest::RedirectStatus::FollowedRedirect);
const KURL originalURL = newRequest.url();
- ResourceRequestBlockedReason blockedReason = m_fetcher->willFollowRedirect(
- m_resource.get(), newRequest, redirectResponse);
- if (blockedReason != ResourceRequestBlockedReason::None) {
- cancelForRedirectAccessCheckError(newRequest.url(), blockedReason);
- return false;
+ if (!isManualRedirectFetchRequest(m_resource->resourceRequest())) {
+ ResourceRequestBlockedReason blockedReason = context().canRequest(
+ m_resource->getType(), newRequest, newRequest.url(),
+ m_resource->options(), m_resource->isUnusedPreload(),
+ FetchRequest::UseDefaultOriginRestrictionForType);
+ if (blockedReason != ResourceRequestBlockedReason::None) {
+ cancelForRedirectAccessCheckError(newRequest.url(), blockedReason);
+ return false;
+ }
+
+ if (m_resource->options().corsEnabled == IsCORSEnabled) {
+ RefPtr<SecurityOrigin> sourceOrigin =
+ m_resource->options().securityOrigin;
+ if (!sourceOrigin.get())
+ sourceOrigin = context().getSecurityOrigin();
+
+ String errorMessage;
+ StoredCredentials withCredentials =
+ m_resource->lastResourceRequest().allowStoredCredentials()
+ ? AllowStoredCredentials
+ : DoNotAllowStoredCredentials;
+ if (!CrossOriginAccessControl::handleRedirect(
+ sourceOrigin, newRequest, redirectResponse, withCredentials,
+ m_resource->mutableOptions(), errorMessage)) {
+ m_resource->setCORSFailed();
+ context().addConsoleMessage(errorMessage);
+ cancelForRedirectAccessCheckError(newRequest.url(),
+ ResourceRequestBlockedReason::Other);
+ return false;
+ }
+ }
+ if (m_resource->getType() == Resource::Image &&
+ m_fetcher->shouldDeferImageLoad(newRequest.url())) {
+ cancelForRedirectAccessCheckError(newRequest.url(),
+ ResourceRequestBlockedReason::Other);
+ return false;
+ }
}
+ bool crossOrigin = !SecurityOrigin::areSameSchemeHostPort(
+ redirectResponse.url(), newRequest.url());
+ m_fetcher->recordResourceTimingOnRedirect(m_resource.get(), redirectResponse,
+ crossOrigin);
+
+ newRequest.setAllowStoredCredentials(m_resource->options().allowCredentials ==
+ AllowStoredCredentials);
+
+ context().dispatchWillSendRequest(m_resource->identifier(), newRequest,
+ redirectResponse,
+ m_resource->options().initiatorInfo);
+
// ResourceFetcher::willFollowRedirect() may rewrite the URL to
// something else not for rejecting redirect but for other reasons.
// E.g. WebFrameTestClient::willSendRequest() and
@@ -202,33 +250,155 @@ void ResourceLoader::didSendData(unsigned long long bytesSent,
m_resource->didSendData(bytesSent, totalBytesToBeSent);
}
+FetchContext& ResourceLoader::context() const {
+ return m_fetcher->context();
+}
+
+ResourceRequestBlockedReason ResourceLoader::canAccessResponse(
+ Resource* resource,
+ const ResourceResponse& response) const {
+ // Redirects can change the response URL different from one of request.
+ bool forPreload = resource->isUnusedPreload();
+ ResourceRequestBlockedReason blockedReason =
+ context().canRequest(resource->getType(), resource->resourceRequest(),
+ response.url(), resource->options(), forPreload,
+ FetchRequest::UseDefaultOriginRestrictionForType);
+ if (blockedReason != ResourceRequestBlockedReason::None)
+ return blockedReason;
+
+ SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get();
+ if (!sourceOrigin)
+ sourceOrigin = context().getSecurityOrigin();
+
+ if (sourceOrigin->canRequestNoSuborigin(response.url()))
+ return ResourceRequestBlockedReason::None;
+
+ // Use the original response instead of the 304 response for a successful
+ // revaldiation.
+ const ResourceResponse& responseForAccessControl =
+ (resource->isCacheValidator() && response.httpStatusCode() == 304)
+ ? resource->response()
+ : response;
+ String errorDescription;
+ if (!passesAccessControlCheck(
+ responseForAccessControl, resource->options().allowCredentials,
+ sourceOrigin, errorDescription,
+ resource->lastResourceRequest().requestContext())) {
+ resource->setCORSFailed();
+ if (!forPreload) {
+ String resourceType = Resource::resourceTypeToString(
+ resource->getType(), resource->options().initiatorInfo);
+ context().addConsoleMessage(
+ "Access to " + resourceType + " at '" + response.url().getString() +
+ "' from origin '" + sourceOrigin->toString() +
+ "' has been blocked by CORS policy: " + errorDescription);
+ }
+ return ResourceRequestBlockedReason::Other;
+ }
+ return ResourceRequestBlockedReason::None;
+}
+
void ResourceLoader::didReceiveResponse(
- const WebURLResponse& response,
+ const WebURLResponse& webURLResponse,
std::unique_ptr<WebDataConsumerHandle> handle) {
- DCHECK(!response.isNull());
- m_fetcher->didReceiveResponse(m_resource.get(), response.toResourceResponse(),
- std::move(handle));
+ DCHECK(!webURLResponse.isNull());
+
+ const ResourceResponse& response = webURLResponse.toResourceResponse();
+
+ if (response.wasFetchedViaServiceWorker()) {
+ if (m_resource->options().corsEnabled == IsCORSEnabled &&
+ response.wasFallbackRequiredByServiceWorker()) {
+ ResourceRequest request = m_resource->lastResourceRequest();
+ DCHECK_EQ(request.skipServiceWorker(),
+ WebURLRequest::SkipServiceWorker::None);
+ // This code handles the case when a regular controlling service worker
+ // doesn't handle a cross origin request. When this happens we still want
+ // to give foreign fetch a chance to handle the request, so only skip the
+ // controlling service worker for the fallback request. This is currently
+ // safe because of http://crbug.com/604084 the
+ // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch
+ // handled a request.
+ if (!context().shouldLoadNewResource(m_resource->getType())) {
+ // Cancel the request if we should not trigger a reload now.
+ handleError(ResourceError::cancelledError(response.url()));
+ return;
+ }
+ request.setSkipServiceWorker(
+ WebURLRequest::SkipServiceWorker::Controlling);
+ restart(request);
+ return;
+ }
+
+ // If the response is fetched via ServiceWorker, the original URL of the
+ // response could be different from the URL of the request. We check the URL
+ // not to load the resources which are forbidden by the page CSP.
+ // https://w3c.github.io/webappsec-csp/#should-block-response
+ const KURL& originalURL = response.originalURLViaServiceWorker();
+ if (!originalURL.isEmpty()) {
+ ResourceRequestBlockedReason blockedReason = context().allowResponse(
+ m_resource->getType(), m_resource->resourceRequest(), originalURL,
+ m_resource->options());
+ if (blockedReason != ResourceRequestBlockedReason::None) {
+ handleError(ResourceError::cancelledDueToAccessCheckError(
+ originalURL, blockedReason));
+ return;
+ }
+ }
+ } else if (m_resource->options().corsEnabled == IsCORSEnabled) {
+ ResourceRequestBlockedReason blockedReason =
+ canAccessResponse(m_resource, response);
+ if (blockedReason != ResourceRequestBlockedReason::None) {
+ handleError(ResourceError::cancelledDueToAccessCheckError(response.url(),
+ blockedReason));
+ return;
+ }
+ }
+
+ context().dispatchDidReceiveResponse(
+ m_resource->identifier(), response,
+ m_resource->resourceRequest().frameType(),
+ m_resource->resourceRequest().requestContext(), m_resource);
+
+ m_resource->responseReceived(response, std::move(handle));
+ if (!m_resource->loader())
+ return;
+
+ if (response.httpStatusCode() >= 400 &&
+ !m_resource->shouldIgnoreHTTPStatusCodeErrors())
+ handleError(ResourceError::cancelledError(response.url()));
}
void ResourceLoader::didReceiveResponse(const WebURLResponse& response) {
didReceiveResponse(response, nullptr);
}
+void ResourceLoader::didDownloadData(int length, int encodedDataLength) {
+ context().dispatchDidDownloadData(m_resource->identifier(), length,
+ encodedDataLength);
+ m_resource->didDownloadData(length);
+}
+
void ResourceLoader::didReceiveData(const char* data, int length) {
CHECK_GE(length, 0);
- m_fetcher->didReceiveData(m_resource.get(), data, length);
+
+ context().dispatchDidReceiveData(m_resource->identifier(), data, length);
m_resource->addToDecodedBodyLength(length);
m_resource->appendData(data, length);
}
void ResourceLoader::didReceiveTransferSizeUpdate(int transferSizeDiff) {
DCHECK_GT(transferSizeDiff, 0);
- m_fetcher->didReceiveTransferSizeUpdate(m_resource.get(), transferSizeDiff);
+ context().dispatchDidReceiveEncodedData(m_resource->identifier(),
+ transferSizeDiff);
}
void ResourceLoader::didFinishLoadingFirstPartInMultipart() {
- m_fetcher->didFinishLoading(m_resource.get(), 0,
- ResourceFetcher::DidFinishFirstPartInMultipart);
+ network_instrumentation::endResourceLoad(
+ m_resource->identifier(),
+ network_instrumentation::RequestOutcome::Success);
+
+ m_fetcher->handleLoaderFinish(m_resource.get(), 0,
+ ResourceFetcher::DidFinishFirstPartInMultipart);
}
void ResourceLoader::didFinishLoading(double finishTime,
@@ -236,9 +406,15 @@ void ResourceLoader::didFinishLoading(double finishTime,
int64_t encodedBodyLength) {
m_resource->setEncodedDataLength(encodedDataLength);
m_resource->addToEncodedBodyLength(encodedBodyLength);
+
m_loader.reset();
- m_fetcher->didFinishLoading(m_resource.get(), finishTime,
- ResourceFetcher::DidFinishLoading);
+
+ network_instrumentation::endResourceLoad(
+ m_resource->identifier(),
+ network_instrumentation::RequestOutcome::Success);
+
+ m_fetcher->handleLoaderFinish(m_resource.get(), finishTime,
+ ResourceFetcher::DidFinishLoading);
}
void ResourceLoader::didFail(const WebURLError& error,
@@ -246,22 +422,24 @@ void ResourceLoader::didFail(const WebURLError& error,
int64_t encodedBodyLength) {
m_resource->setEncodedDataLength(encodedDataLength);
m_resource->addToEncodedBodyLength(encodedBodyLength);
- didFail(error);
+ handleError(error);
}
-void ResourceLoader::didFail(const ResourceError& error) {
+void ResourceLoader::handleError(const ResourceError& error) {
if (m_isCacheAwareLoadingActivated && error.isCacheMiss() &&
- m_fetcher->context().shouldLoadNewResource(m_resource->getType())) {
+ context().shouldLoadNewResource(m_resource->getType())) {
m_resource->willReloadAfterDiskCacheMiss();
m_isCacheAwareLoadingActivated = false;
- restart(m_resource->resourceRequest(),
- m_fetcher->context().loadingTaskRunner(),
- m_fetcher->context().defersLoading());
+ restart(m_resource->resourceRequest());
return;
}
m_loader.reset();
- m_fetcher->didFailLoading(m_resource.get(), error);
+
+ network_instrumentation::endResourceLoad(
+ m_resource->identifier(), network_instrumentation::RequestOutcome::Fail);
+
+ m_fetcher->handleLoaderError(m_resource.get(), error);
}
void ResourceLoader::requestSynchronously(const ResourceRequest& request) {
@@ -297,7 +475,8 @@ void ResourceLoader::requestSynchronously(const ResourceRequest& request) {
// empty buffer is a noop in most cases, but is destructive in the case of
// a 304, where it will overwrite the cached data we should be reusing.
if (dataOut.size()) {
- m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size());
+ context().dispatchDidReceiveData(m_resource->identifier(), dataOut.data(),
+ dataOut.size());
m_resource->setResourceBuffer(dataOut);
}
didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength,

Powered by Google App Engine
This is Rietveld 408576698