void ResourceLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewRequest, const WebURLResponse& passedRedirectResponse) { ASSERT(m_state != Terminated); ResourceRequest& newRequest(applyOptions(passedNewRequest.toMutableResourceRequest())); ASSERT(!newRequest.isNull()); const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse()); ASSERT(!redirectResponse.isNull()); newRequest.setFollowedRedirect(true); if (!isManualRedirectFetchRequest(m_resource->resourceRequest()) && !m_fetcher->canAccessRedirect(m_resource, newRequest, redirectResponse, m_options)) { cancel(ResourceError::cancelledDueToAccessCheckError(newRequest.url())); return; } ASSERT(m_state != Terminated); applyOptions(newRequest); // canAccessRedirect() can modify m_options so we should re-apply it. m_fetcher->redirectReceived(m_resource, redirectResponse); ASSERT(m_state != Terminated); m_resource->willFollowRedirect(newRequest, redirectResponse); if (newRequest.isNull() || m_state == Terminated) return; m_fetcher->willSendRequest(m_resource->identifier(), newRequest, redirectResponse, m_options.initiatorInfo); ASSERT(m_state != Terminated); ASSERT(!newRequest.isNull()); m_resource->updateRequest(newRequest); m_request = newRequest; }
void BeaconLoader::willSendRequest(WebURLLoader*, WebURLRequest& passedNewRequest, const WebURLResponse& passedRedirectResponse) { passedNewRequest.setAllowStoredCredentials(true); ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse()); ASSERT(!newRequest.isNull()); ASSERT(!redirectResponse.isNull()); String errorDescription; StoredCredentials withCredentials = AllowStoredCredentials; ResourceLoaderOptions options; if (!CrossOriginAccessControl::handleRedirect(m_beaconOrigin.get(), newRequest, redirectResponse, withCredentials, options, errorDescription)) { if (page() && page()->mainFrame()) { if (page()->mainFrame()->isLocalFrame()) { LocalFrame* localFrame = toLocalFrame(page()->mainFrame()); if (localFrame->document()) localFrame->document()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, errorDescription)); } } // Cancel the load and self destruct. dispose(); return; } // FIXME: http://crbug.com/427429 is needed to correctly propagate // updates of Origin: following this successful redirect. }
void ResourceLoader::didReceiveResponse( const WebURLResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) { DCHECK(!response.isNull()); m_fetcher->didReceiveResponse(m_resource.get(), response.toResourceResponse(), std::move(handle)); }
void ResourceHandleInternal::willSendRequest( WebURLLoader*, WebURLRequest& request, const WebURLResponse& response) { ASSERT(m_client); ASSERT(!request.isNull()); ASSERT(!response.isNull()); m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse()); }
void PingLoader::didReceiveResponse(WebURLLoader*, const WebURLResponse& response) { if (LocalFrame* frame = this->frame()) { TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceFinish", TRACE_EVENT_SCOPE_THREAD, "data", InspectorResourceFinishEvent::data(m_identifier, 0, true)); const ResourceResponse& resourceResponse = response.toResourceResponse(); InspectorInstrumentation::didReceiveResourceResponse(frame, m_identifier, 0, resourceResponse, 0); didFailLoading(frame); } dispose(); }
void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response) { ASSERT(m_client); ASSERT(!response.isNull()); bool isMultipart = response.isMultipartPayload(); bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse); // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved. if (!isMultipart && !isValidStateTransition) CRASH(); m_state = ConnectionStateReceivedResponse; m_client->didReceiveResponse(m_owner, response.toResourceResponse()); }
bool ResourceLoader::willFollowRedirect( WebURLRequest& passedNewRequest, const WebURLResponse& passedRedirectResponse) { DCHECK(!passedNewRequest.isNull()); DCHECK(!passedRedirectResponse.isNull()); if (m_isCacheAwareLoadingActivated) { // Fail as cache miss if cached response is a redirect. didFail( ResourceError::cacheMissError(m_resource->lastResourceRequest().url())); return false; } 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; } // ResourceFetcher::willFollowRedirect() may rewrite the URL to // something else not for rejecting redirect but for other reasons. // E.g. WebFrameTestClient::willSendRequest() and // RenderFrameImpl::willSendRequest(). We should reflect the // rewriting but currently we cannot. So, return false to make the // redirect fail. if (newRequest.url() != originalURL) { cancelForRedirectAccessCheckError(newRequest.url(), ResourceRequestBlockedReason::Other); return false; } if (!m_resource->willFollowRedirect(newRequest, redirectResponse)) { cancelForRedirectAccessCheckError(newRequest.url(), ResourceRequestBlockedReason::Other); return false; } return true; }
void ResourceLoader::requestSynchronously() { OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(loader); // downloadToFile is not supported for synchronous requests. ASSERT(!m_request.downloadToFile()); ResourcePtr<Resource> protectResource(m_resource); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; WrappedResourceRequest requestIn(m_request); WebURLResponse responseOut; responseOut.initialize(); WebURLError errorOut; WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { if (m_state == Terminated) { // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. ASSERT(!m_resource); return; } didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); if (m_state == Terminated) return; RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : WebURLLoaderClient::kUnknownEncodedDataLength; // Follow the async case convention of not calling didReceiveData or // appending data to m_resource if the response body is empty. Copying the // 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, dataOut.data(), dataOut.size(), encodedDataLength); m_resource->setResourceBuffer(dataOut); } didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); }
void ResourceLoader::requestSynchronously(const ResourceRequest& request) { // downloadToFile is not supported for synchronous requests. DCHECK(!request.downloadToFile()); DCHECK(m_loader); DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); WrappedResourceRequest requestIn(request); WebURLResponse responseOut; WebURLError errorOut; WebData dataOut; int64_t encodedDataLength = WebURLLoaderClient::kUnknownEncodedDataLength; int64_t encodedBodyLength = 0; m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut, encodedDataLength, encodedBodyLength); // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. if (!m_loader) return; if (errorOut.reason) { didFail(errorOut, encodedDataLength, encodedBodyLength); return; } didReceiveResponse(responseOut); if (!m_loader) return; DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); // Follow the async case convention of not calling didReceiveData or // appending data to m_resource if the response body is empty. Copying the // 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()); m_resource->setResourceBuffer(dataOut); } didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, encodedBodyLength); }
void ResourceLoader::requestSynchronously() { OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(loader); // downloadToFile is not supported for synchronous requests. ASSERT(!m_request.downloadToFile()); ResourcePtr<Resource> protectResource(m_resource); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; WrappedResourceRequest requestIn(m_request); WebURLResponse responseOut; responseOut.initialize(); WebURLError errorOut; WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { if (m_state == Terminated) { // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. ASSERT(!m_resource); return; } didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); if (m_state == Terminated) return; RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : WebURLLoaderClient::kUnknownEncodedDataLength; m_fetcher->didReceiveData(m_resource, dataOut.data(), dataOut.size(), encodedDataLength); m_resource->setResourceBuffer(dataOut); didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); }
void WebDevToolsAgentImpl::didReceiveResponse(unsigned long resourceId, const WebURLResponse& response) { if (InspectorController* ic = inspectorController()) ic->didReceiveResponse(resourceId, response.toResourceResponse()); }
void ResourceLoader::didReceiveResponse(WebURLLoader*, const WebURLResponse& response, WebDataConsumerHandle* rawHandle) { ASSERT(!response.isNull()); ASSERT(m_state == Initialized); // |rawHandle|'s ownership is transferred to the callee. OwnPtr<WebDataConsumerHandle> handle = adoptPtr(rawHandle); bool isMultipartPayload = response.isMultipartPayload(); bool isValidStateTransition = (m_connectionState == ConnectionStateStarted || m_connectionState == ConnectionStateReceivedResponse); // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved. RELEASE_ASSERT(isMultipartPayload || isValidStateTransition); m_connectionState = ConnectionStateReceivedResponse; const ResourceResponse& resourceResponse = response.toResourceResponse(); if (responseNeedsAccessControlCheck()) { if (response.wasFetchedViaServiceWorker()) { if (response.wasFallbackRequiredByServiceWorker()) { m_loader->cancel(); m_loader.clear(); m_connectionState = ConnectionStateStarted; m_loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(m_loader); ASSERT(!m_request.skipServiceWorker()); m_request.setSkipServiceWorker(true); WrappedResourceRequest wrappedRequest(m_request); m_loader->loadAsynchronously(wrappedRequest, this); return; } } else { // If the response successfully validated a cached resource, perform // the access control with respect to it. Need to do this right here // before the resource switches clients over to that validated resource. Resource* resource = m_resource; if (!resource->isCacheValidator() || resourceResponse.httpStatusCode() != 304) m_resource->setResponse(resourceResponse); if (!m_fetcher->canAccessResource(resource, m_options.securityOrigin.get(), response.url(), ResourceFetcher::ShouldLogAccessControlErrors)) { m_fetcher->didReceiveResponse(m_resource, resourceResponse); cancel(ResourceError::cancelledDueToAccessCheckError(KURL(response.url()))); return; } } } m_resource->responseReceived(resourceResponse, handle.release()); if (m_state == Terminated) return; m_fetcher->didReceiveResponse(m_resource, resourceResponse); if (m_state == Terminated) return; if (response.toResourceResponse().isMultipart()) { // We only support multipart for images, though the image may be loaded // as a main resource that we end up displaying through an ImageDocument. if (!m_resource->isImage() && m_resource->type() != Resource::MainResource) { cancel(); return; } m_loadingMultipartContent = true; } else if (isMultipartPayload) { // Since a subresource loader does not load multipart sections progressively, data was delivered to the loader all at once. // After the first multipart section is complete, signal to delegates that this load is "finished" m_fetcher->subresourceLoaderFinishedLoadingOnePart(this); didFinishLoadingOnePart(0, WebURLLoaderClient::kUnknownEncodedDataLength); } if (m_state == Terminated) return; if (m_resource->response().httpStatusCode() < 400 || m_resource->shouldIgnoreHTTPStatusCodeErrors()) return; m_state = Finishing; if (!m_notifiedLoadComplete) { m_notifiedLoadComplete = true; m_fetcher->didFailLoading(m_resource, ResourceError::cancelledError(m_request.url())); } ASSERT(m_state != Terminated); m_resource->error(Resource::LoadError); cancel(); }