void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) { // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it. URL previousURL = request().url(); Ref<SubresourceLoader> protectedThis(*this); if (!newRequest.url().isValid()) { cancel(cannotShowURLError()); return; } ASSERT(!newRequest.isNull()); if (!redirectResponse.isNull()) { if (options().redirect != FetchOptions::Redirect::Follow) { if (options().redirect == FetchOptions::Redirect::Error) { cancel(); return; } ResourceResponse opaqueRedirectedResponse; opaqueRedirectedResponse.setType(ResourceResponse::Type::Opaqueredirect); m_resource->responseReceived(opaqueRedirectedResponse); didFinishLoading(currentTime()); return; } // CachedResources are keyed off their original request URL. // Requesting the same original URL a second time can redirect to a unique second resource. // Therefore, if a redirect to a different destination URL occurs, we should no longer consider this a revalidation of the first resource. // Doing so would have us reusing the resource from the first request if the second request's revalidation succeeds. if (newRequest.isConditional() && m_resource->resourceToRevalidate() && newRequest.url() != m_resource->resourceToRevalidate()->response().url()) { newRequest.makeUnconditional(); MemoryCache::singleton().revalidationFailed(*m_resource); if (m_frame && m_frame->page()) m_frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), emptyString(), DiagnosticLoggingResultFail, ShouldSample::Yes); } if (!m_documentLoader->cachedResourceLoader().canRequest(m_resource->type(), newRequest.url(), options(), false /* forPreload */, true /* didReceiveRedirectResponse */)) { cancel(); return; } if (!checkRedirectionCrossOriginAccessControl(request(), redirectResponse, newRequest)) { cancel(); return; } if (m_resource->isImage() && m_documentLoader->cachedResourceLoader().shouldDeferImageLoad(newRequest.url())) { cancel(); return; } m_resource->redirectReceived(newRequest, redirectResponse); } if (newRequest.isNull() || reachedTerminalState()) return; ResourceLoader::willSendRequestInternal(newRequest, redirectResponse); if (newRequest.isNull()) cancel(); ResourceLoadObserver::sharedObserver().logSubresourceLoading(m_frame.get(), newRequest, redirectResponse); }
void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) { // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it. URL previousURL = request().url(); Ref<SubresourceLoader> protectedThis(*this); if (!newRequest.url().isValid()) { cancel(cannotShowURLError()); return; } if (newRequest.requester() != ResourceRequestBase::Requester::Main) ResourceLoadObserver::sharedObserver().logSubresourceLoading(m_frame.get(), newRequest, redirectResponse); ASSERT(!newRequest.isNull()); if (!redirectResponse.isNull()) { if (options().redirect != FetchOptions::Redirect::Follow) { if (options().redirect == FetchOptions::Redirect::Error) { cancel(); return; } ResourceResponse opaqueRedirectedResponse; opaqueRedirectedResponse.setURL(redirectResponse.url()); opaqueRedirectedResponse.setType(ResourceResponse::Type::Opaqueredirect); m_resource->responseReceived(opaqueRedirectedResponse); didFinishLoading(currentTime()); return; } else if (m_redirectCount++ >= options().maxRedirectCount) { cancel(ResourceError(String(), 0, request().url(), ASCIILiteral("Too many redirections"), ResourceError::Type::General)); return; } // CachedResources are keyed off their original request URL. // Requesting the same original URL a second time can redirect to a unique second resource. // Therefore, if a redirect to a different destination URL occurs, we should no longer consider this a revalidation of the first resource. // Doing so would have us reusing the resource from the first request if the second request's revalidation succeeds. if (newRequest.isConditional() && m_resource->resourceToRevalidate() && newRequest.url() != m_resource->resourceToRevalidate()->response().url()) { newRequest.makeUnconditional(); MemoryCache::singleton().revalidationFailed(*m_resource); if (m_frame && m_frame->page()) m_frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), emptyString(), DiagnosticLoggingResultFail, ShouldSample::Yes); } if (!m_documentLoader->cachedResourceLoader().updateRequestAfterRedirection(m_resource->type(), newRequest, options())) { cancel(); return; } String errorDescription; if (!checkRedirectionCrossOriginAccessControl(request(), redirectResponse, newRequest, errorDescription)) { String errorMessage = "Cross-origin redirection to " + newRequest.url().string() + " denied by Cross-Origin Resource Sharing policy: " + errorDescription; if (m_frame && m_frame->document()) m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, errorMessage); cancel(ResourceError(String(), 0, request().url(), errorMessage, ResourceError::Type::AccessControl)); return; } if (m_resource->isImage() && m_documentLoader->cachedResourceLoader().shouldDeferImageLoad(newRequest.url())) { cancel(); return; } m_loadTiming.addRedirect(redirectResponse.url(), newRequest.url()); m_resource->redirectReceived(newRequest, redirectResponse); } if (newRequest.isNull() || reachedTerminalState()) return; ResourceLoader::willSendRequestInternal(newRequest, redirectResponse); if (newRequest.isNull()) { cancel(); return; } if (m_resource->type() == CachedResource::MainResource && !redirectResponse.isNull()) m_documentLoader->willContinueMainResourceLoadAfterRedirect(newRequest); }