15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * Copyright (C) 2013, Intel Corporation
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/DocumentThreadableLoader.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include "core/fetch/CrossOriginAccessControl.h"
37e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/FetchRequest.h"
388abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include "core/fetch/Resource.h"
39e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/ResourceFetcher.h"
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/frame/ContentSecurityPolicy.h"
41bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/frame/Frame.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/CrossOriginPreflightResultCache.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/DocumentThreadableLoaderClient.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoader.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/ThreadableLoaderClient.h"
471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/SharedBuffer.h"
48bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/network/ResourceRequest.h"
4951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/SchemeRegistry.h"
5051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/SecurityOrigin.h"
51e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "wtf/Assertions.h"
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The loader will be deleted as soon as this function exits.
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options));
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(loader->hasOneRef());
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options));
65e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (!loader->resource())
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        loader = 0;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return loader.release();
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_client(client)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_document(document)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_options(options)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_sameOriginRequest(securityOrigin()->canRequest(request.url()))
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_simpleRequest(true)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_async(blockingBehavior == LoadAsynchronously)
77521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(document);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(client);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Setting an outgoing referer is only supported in the async code path.
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_async || request.httpReferrer().isEmpty());
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        loadRequest(request, DoSecurityCheck);
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) {
90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are not supported."));
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    makeCrossOriginAccessRequest(request);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceRequest& request)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceRequest(request));
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1030019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    if ((m_options.preflightPolicy == ConsiderPreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight) {
1040019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        updateRequestForAccessControl(*crossOriginRequest, securityOrigin(), m_options.allowCredentials);
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        makeSimpleCrossOriginAccessRequest(*crossOriginRequest);
1060019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    } else {
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_simpleRequest = false;
1080019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        // Do not set the Origin header for preflight requests.
1090019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        updateRequestForAccessControl(*crossOriginRequest, 0, m_options.allowCredentials);
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_actualRequest = crossOriginRequest.release();
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()))
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            preflightSuccess();
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            makeCrossOriginAccessRequestWithPreflight(*m_actualRequest);
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_options.preflightPolicy != ForcePreflight);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_options.preflightPolicy == PreventPreflight || isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()));
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Cross-origin requests are only allowed for HTTP and registered schemes. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) {
126a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are only supported for HTTP."));
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadRequest(request, DoSecurityCheck);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ResourceRequest preflightRequest = createAccessControlPreflightRequest(request, securityOrigin());
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadRequest(preflightRequest, DoSecurityCheck);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DocumentThreadableLoader::~DocumentThreadableLoader()
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::cancel()
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
145521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    cancelWithError(ResourceError());
146521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
147521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
148521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void DocumentThreadableLoader::cancelWithError(const ResourceError& error)
149521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<DocumentThreadableLoader> protect(this);
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Cancel can re-enter and m_resource might be null here as a result.
153e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (m_client && resource()) {
154521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        ResourceError errorForCallback = error;
155521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (errorForCallback.isNull()) {
156521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            // FIXME: This error is sent to the client in didFail(), so it should not be an internal one. Use FrameLoaderClient::cancelledError() instead.
157e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)            errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resource()->url().string(), "Load cancelled");
158521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            errorForCallback.setIsCancellation(true);
159521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
160e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        didFail(resource()->identifier(), errorForCallback);
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearResource();
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_client = 0;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::setDefersLoading(bool value)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
168e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (resource())
169e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        resource()->setDefersLoading(value);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
172fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_client);
175e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT_UNUSED(resource, resource == this->resource());
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<DocumentThreadableLoader> protect(this);
178e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    if (!isAllowedByPolicy(request.url())) {
179e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        m_client->didFailRedirectCheck();
180e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        request = ResourceRequest();
181e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        return;
182e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    }
183e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Allow same origin requests to continue after allowing clients to audit the redirect.
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isAllowedRedirect(request.url())) {
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_client->isDocumentThreadableLoaderClient())
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequest(request, redirectResponse);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // When using access control, only simple cross origin requests are allowed to redirect. The new request URL must have a supported
192e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    // scheme and not contain the userinfo production. In addition, the redirect response must pass the access control check if the
193e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    // original request was not same-origin.
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_options.crossOriginRequestPolicy == UseAccessControl) {
195c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
196f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        InspectorInstrumentation::didReceiveCORSRedirectResponse(m_document->frame(), resource->identifier(), m_document->frame()->loader().documentLoader(), redirectResponse, 0);
197c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool allowRedirect = false;
199c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        String accessControlErrorDescription;
200c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_simpleRequest) {
202c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)            allowRedirect = checkCrossOriginAccessRedirectionUrl(request.url(), accessControlErrorDescription)
203e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                            && (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription));
204c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        } else {
205c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)            accessControlErrorDescription = "The request was redirected to '"+ request.url().string() + "', which is disallowed for cross-origin requests that require preflight.";
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (allowRedirect) {
209e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)            clearResource();
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redirectResponse.url());
21293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(request.url());
213e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            // If the original request wasn't same-origin, then if the request URL origin is not same origin with the original URL origin,
214e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            // set the source origin to a globally unique identifier. (If the original request was same-origin, the origin of the new request
215e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            // should be the original URL origin.)
216e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            if (!m_sameOriginRequest && !originalOrigin->isSameSchemeHostPort(requestOrigin.get()))
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_options.securityOrigin = SecurityOrigin::createUnique();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Force any subsequent requests to use these checks.
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_sameOriginRequest = false;
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
221e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            // Since the request is no longer same-origin, if the user didn't request credentials in
222e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            // the first place, update our state so we neither request them nor expect they must be allowed.
223e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            if (m_options.credentialsRequested == ClientDidNotRequestCredentials)
224e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                m_options.allowCredentials = DoNotAllowStoredCredentials;
225e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Remove any headers that may have been added by the network layer that cause access control to fail.
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            request.clearHTTPContentType();
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            request.clearHTTPReferrer();
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            request.clearHTTPOrigin();
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            request.clearHTTPUserAgent();
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            request.clearHTTPAccept();
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            makeCrossOriginAccessRequest(request);
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
236a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url().string(), accessControlErrorDescription);
237c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        m_client->didFailAccessControlCheck(error);
238c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    } else {
239c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        m_client->didFailRedirectCheck();
240c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    }
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    request = ResourceRequest();
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
244fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_client);
247e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT_UNUSED(resource, resource == this->resource());
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_client->didSendData(bytesSent, totalBytesToBeSent);
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
251fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength)
25253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
25353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ASSERT(m_client);
254e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT_UNUSED(resource, resource == this->resource());
25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ASSERT(!m_actualRequest);
25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
25753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_client->didDownloadData(dataLength);
25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
25953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
260fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::responseReceived(Resource* resource, const ResourceResponse& response)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
262e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT_UNUSED(resource, resource == this->resource());
263e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    didReceiveResponse(resource->identifier(), response);
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_client);
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    String accessControlErrorDescription;
271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_actualRequest) {
272f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        DocumentLoader* loader = m_document->frame()->loader().documentLoader();
273e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        InspectorInstrumentation::didReceiveResourceResponse(m_document->frame(), identifier, loader, response, resource() ? resource()->loader() : 0);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!passesAccessControlCheck(response, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)) {
27693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            preflightFailure(identifier, response.url().string(), accessControlErrorDescription);
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
280f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) {
281f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            preflightFailure(identifier, response.url().string(), accessControlErrorDescription);
282f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            return;
283f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        }
284f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new CrossOriginPreflightResultCacheItem(m_options.allowCredentials));
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!preflightResult->parse(response, accessControlErrorDescription)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod(), accessControlErrorDescription)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeaderFields(), accessControlErrorDescription)) {
28993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            preflightFailure(identifier, response.url().string(), accessControlErrorDescription);
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release());
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!passesAccessControlCheck(response, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)) {
297a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription));
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_client->didReceiveResponse(identifier, response);
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
306fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::dataReceived(Resource* resource, const char* data, int dataLength)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
308e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT(resource == this->resource());
309e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    didReceiveData(resource->identifier(), data, dataLength);
310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DocumentThreadableLoader::didReceiveData(unsigned long identifier, const char* data, int dataLength)
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(m_client);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Preflight data should be invisible to clients.
317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_actualRequest) {
318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        InspectorInstrumentation::didReceiveData(m_document->frame(), identifier, 0, 0, dataLength);
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_client->didReceiveData(data, dataLength);
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid DocumentThreadableLoader::notifyFinished(Resource* resource)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_client);
328e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT(resource == this->resource());
329521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
330521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_timeoutTimer.stop();
33102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
332e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (resource->errorOccurred())
333e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        didFail(resource->identifier(), resource->resourceError());
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
335e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        didFinishLoading(resource->identifier(), resource->loadFinishTime());
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_actualRequest) {
341f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        InspectorInstrumentation::didFinishLoading(m_document->frame(), identifier, m_document->frame()->loader().documentLoader(), finishTime);
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!m_sameOriginRequest);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        preflightSuccess();
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_client->didFinishLoading(identifier, finishTime);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DocumentThreadableLoader::didFail(unsigned long identifier, const ResourceError& error)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_actualRequest)
352f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        InspectorInstrumentation::didFailLoading(m_document->frame(), identifier, m_document->frame()->loader().documentLoader(), error);
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_client->didFail(error);
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
357521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer)
358521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
359521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT_UNUSED(timer, timer == &m_timeoutTimer);
360521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
361521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Using values from net/base/net_error_list.h ERR_TIMED_OUT,
362521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Same as existing FIXME above - this error should be coming from FrameLoaderClient to be identifiable.
363521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    static const int timeoutError = -7;
364e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ResourceError error("net", timeoutError, resource()->url(), String());
365521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    error.setIsTimeout(true);
366521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    cancelWithError(error);
367521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
368521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::preflightSuccess()
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<ResourceRequest> actualRequest;
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    actualRequest.swap(m_actualRequest);
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    actualRequest->setHTTPOrigin(securityOrigin()->toString());
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearResource();
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // It should be ok to skip the security check since we already asked about the preflight request.
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadRequest(*actualRequest, SkipSecurityCheck);
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DocumentThreadableLoader::preflightFailure(unsigned long identifier, const String& url, const String& errorDescription)
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
384a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription);
385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_actualRequest)
386f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        InspectorInstrumentation::didFailLoading(m_document->frame(), identifier, m_document->frame()->loader().documentLoader(), error);
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_actualRequest = nullptr; // Prevent didFinishLoading() from bypassing access check.
388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_client->didFailAccessControlCheck(error);
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck)
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Any credential should have been removed from the cross-site requests.
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const KURL& requestURL = request.url();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_options.securityCheck = securityCheck;
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_sameOriginRequest || requestURL.user().isEmpty());
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty());
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3998abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ThreadableLoaderOptions options = m_options;
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_async) {
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        options.crossOriginCredentialPolicy = DoNotAskClientForCrossOriginCredentials;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_actualRequest) {
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Don't sniff content or send load callbacks for the preflight request.
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            options.sendLoadCallbacks = DoNotSendCallbacks;
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            options.sniffContent = DoNotSniffContent;
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Keep buffering the data for the preflight request.
407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            options.dataBufferingPolicy = BufferData;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
410521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (m_options.timeoutMilliseconds > 0)
411521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            m_timeoutTimer.startOneShot(m_options.timeoutMilliseconds / 1000.0);
412521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
4133464d02a173573db42f8ee6bb07bb74fabf4f5f2Ben Murdoch        FetchRequest newRequest(request, m_options.initiator, options);
414e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        ASSERT(!resource());
415e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        setResource(m_document->fetcher()->fetchRawResource(newRequest));
416e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        if (resource() && resource()->loader()) {
417e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)            unsigned long identifier = resource()->identifier();
418e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)            InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
42281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
42306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    FetchRequest fetchRequest(request, m_options.initiator, options);
42406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ResourcePtr<Resource> resource = m_document->fetcher()->fetchSynchronously(fetchRequest);
42506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ResourceResponse response = resource ? resource->response() : ResourceResponse();
42606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    unsigned long identifier = resource ? resource->identifier() : std::numeric_limits<unsigned long>::max();
42706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ResourceError error = resource ? resource->resourceError() : ResourceError();
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client);
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
43106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (!resource) {
43206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        m_client->didFail(error);
43306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return;
43406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    }
43506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // No exception for file:/// resources, see <rdar://problem/4962298>.
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Also, if we have an HTTP response, then it wasn't a network error in fact.
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) {
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_client->didFail(error);
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials.
446e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || !isAllowedRedirect(response.url()))) {
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_client->didFailRedirectCheck();
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    didReceiveResponse(identifier, response);
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    SharedBuffer* data = resource->resourceBuffer();
45406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (data)
45506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        didReceiveData(identifier, data->data(), data->size());
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    didFinishLoading(identifier, 0.0);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
460e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) const
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests)
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_sameOriginRequest && securityOrigin()->canRequest(url);
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
468e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)bool DocumentThreadableLoader::isAllowedByPolicy(const KURL& url) const
469e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){
470e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    if (m_options.contentSecurityPolicyEnforcement != EnforceConnectSrcDirective)
471e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        return true;
472e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return m_document->contentSecurityPolicy()->allowConnectToSource(url);
473e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)}
474e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SecurityOrigin* DocumentThreadableLoader::securityOrigin() const
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_options.securityOrigin ? m_options.securityOrigin.get() : m_document->securityOrigin();
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
480c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)bool DocumentThreadableLoader::checkCrossOriginAccessRedirectionUrl(const KURL& requestUrl, String& errorDescription)
481c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles){
482c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(requestUrl.protocol())) {
483c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        errorDescription = "The request was redirected to a URL ('" + requestUrl.string() + "') which has a disallowed scheme for cross-origin requests.";
484c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        return false;
485c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    }
486c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
487c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    if (!(requestUrl.user().isEmpty() && requestUrl.pass().isEmpty())) {
488c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        errorDescription = "The request was redirected to a URL ('" + requestUrl.string() + "') containing userinfo, which is disallowed for cross-origin requests.";
489c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        return false;
490c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    }
491c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
492c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    return true;
493c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)}
494c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
496