void ResourceLoader::start() { ASSERT(!m_loader); ASSERT(!m_request.isNull()); ASSERT(m_deferredRequest.isNull()); if (responseNeedsAccessControlCheck() && m_fetcher->isControlledByServiceWorker()) { m_fallbackRequestForServiceWorker = adoptPtr(new ResourceRequest(m_request)); m_fallbackRequestForServiceWorker->setSkipServiceWorker(true); } m_fetcher->willStartLoadingResource(m_resource, m_request); if (m_options.synchronousPolicy == RequestSynchronously) { requestSynchronously(); return; } if (m_defersLoading) { m_deferredRequest = m_request; return; } if (m_state == Terminated) return; RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; m_loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(m_loader); WrappedResourceRequest wrappedRequest(m_request); m_loader->loadAsynchronously(wrappedRequest, this); }
void ResourceLoader::didReceiveResponse(blink::WebURLLoader*, const blink::WebURLResponse& response) { ASSERT(!response.isNull()); ASSERT(m_state == Initialized); 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 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) resource = m_resource->resourceToRevalidate(); else m_resource->setResponse(resourceResponse); if (!m_host->canAccessResource(resource, m_options.securityOrigin.get(), response.url())) { cancel(); return; } } // Reference the object in this method since the additional processing can do // anything including removing the last reference to this object. RefPtr<ResourceLoader> protect(this); m_resource->responseReceived(resourceResponse); if (m_state == Terminated) return; m_host->didReceiveResponse(m_resource, resourceResponse); if (response.toResourceResponse().isMultipart()) { // We don't count multiParts in a ResourceFetcher's request count m_requestCountTracker.clear(); if (!m_resource->isImage()) { cancel(); return; } } 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_host->subresourceLoaderFinishedLoadingOnePart(this); didFinishLoadingOnePart(0, blink::WebURLLoaderClient::kUnknownEncodedDataLength); } if (m_resource->response().httpStatusCode() < 400 || m_resource->shouldIgnoreHTTPStatusCodeErrors()) return; m_state = Finishing; if (!m_notifiedLoadComplete) { m_notifiedLoadComplete = true; m_host->didFailLoading(m_resource, ResourceError::cancelledError(m_request.url())); } m_resource->error(Resource::LoadError); cancel(); }
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(); }