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();
}
Exemplo n.º 3
0
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();
}