| Index: third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
|
| diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
|
| index f7c6c97c30a877720d2d680ef27a54a84ba31824..6ba68590afb945fbb8ceef7e0a8279a615ede9bd 100644
|
| --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
|
| +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
|
| @@ -239,25 +239,28 @@ Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const
|
| return resource.get();
|
| }
|
|
|
| -bool ResourceFetcher::canAccessResource(Resource* resource, SecurityOrigin* sourceOrigin, const KURL& url) const
|
| +bool ResourceFetcher::canAccessResponse(Resource* resource, const ResourceResponse& response) const
|
| {
|
| // Redirects can change the response URL different from one of request.
|
| bool forPreload = resource->isUnusedPreload();
|
| - if (!context().canRequest(resource->getType(), resource->resourceRequest(), url, resource->options(), forPreload, FetchRequest::UseDefaultOriginRestrictionForType))
|
| + if (!context().canRequest(resource->getType(), resource->resourceRequest(), response.url(), resource->options(), forPreload, FetchRequest::UseDefaultOriginRestrictionForType))
|
| return false;
|
|
|
| + SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get();
|
| if (!sourceOrigin)
|
| sourceOrigin = context().getSecurityOrigin();
|
|
|
| - if (sourceOrigin->canRequestNoSuborigin(url))
|
| + if (sourceOrigin->canRequestNoSuborigin(response.url()))
|
| return true;
|
|
|
| + // 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 (!resource->passesAccessControlCheck(sourceOrigin, 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(resourceType + " from origin '" + SecurityOrigin::create(url)->toString() + "' has been blocked from loading by Cross-Origin Resource Sharing policy: " + errorDescription);
|
| + context().addConsoleMessage(resourceType + " from origin '" + SecurityOrigin::create(response.url())->toString() + "' has been blocked from loading by Cross-Origin Resource Sharing policy: " + errorDescription);
|
| }
|
| return false;
|
| }
|
| @@ -945,21 +948,44 @@ void ResourceFetcher::didFailLoading(Resource* resource, const ResourceError& er
|
| context().didLoadResource(resource);
|
| }
|
|
|
| -void ResourceFetcher::didReceiveResponse(Resource* resource, const ResourceResponse& response)
|
| +void ResourceFetcher::didReceiveResponse(Resource* resource, const ResourceResponse& response, WebDataConsumerHandle* rawHandle)
|
| {
|
| - // 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
|
| + // |rawHandle|'s ownership is transferred to the callee.
|
| + std::unique_ptr<WebDataConsumerHandle> handle = wrapUnique(rawHandle);
|
| +
|
| if (response.wasFetchedViaServiceWorker()) {
|
| + if (resource->options().corsEnabled == IsCORSEnabled && response.wasFallbackRequiredByServiceWorker()) {
|
| + ResourceRequest request = 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.
|
| + request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::Controlling);
|
| + resource->loader()->restartForServiceWorkerFallback(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() && !context().allowResponse(resource->getType(), resource->resourceRequest(), originalURL, resource->options())) {
|
| - resource->loader()->cancel();
|
| - bool isInternalRequest = resource->options().initiatorInfo.name == FetchInitiatorTypeNames::internal;
|
| - context().dispatchDidFail(resource->identifier(), ResourceError(errorDomainBlinkInternal, 0, originalURL.getString(), "Unsafe attempt to load URL " + originalURL.elidedString() + " fetched by a ServiceWorker."), isInternalRequest);
|
| + resource->loader()->didFail(nullptr, ResourceError::cancelledDueToAccessCheckError(originalURL));
|
| return;
|
| }
|
| + } else if (resource->options().corsEnabled == IsCORSEnabled && !canAccessResponse(resource, response)) {
|
| + resource->loader()->didFail(nullptr, ResourceError::cancelledDueToAccessCheckError(response.url()));
|
| + return;
|
| }
|
| +
|
| context().dispatchDidReceiveResponse(resource->identifier(), response, resource->resourceRequest().frameType(), resource->resourceRequest().requestContext(), resource);
|
| + resource->responseReceived(response, std::move(handle));
|
| + if (resource->loader() && response.httpStatusCode() >= 400 && !resource->shouldIgnoreHTTPStatusCodeErrors())
|
| + resource->loader()->didFail(nullptr, ResourceError::cancelledError(response.url()));
|
| }
|
|
|
| void ResourceFetcher::didReceiveData(const Resource* resource, const char* data, int dataLength, int encodedDataLength)
|
|
|