root/Source/web/tests/AssociatedURLLoaderTest.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. m_runningMessageLoop
  2. RegisterMockedUrl
  3. SetUp
  4. TearDown
  5. serveRequests
  6. createAssociatedURLLoader
  7. willSendRequest
  8. didSendData
  9. didReceiveResponse
  10. didDownloadData
  11. didReceiveData
  12. didReceiveCachedMetadata
  13. didFinishLoading
  14. didFail
  15. CheckMethodFails
  16. CheckHeaderFails
  17. CheckHeaderFails
  18. CheckFails
  19. CheckAccessControlHeaders
  20. mainFrame
  21. TEST_F
  22. TEST_F
  23. TEST_F
  24. TEST_F
  25. TEST_F
  26. TEST_F
  27. TEST_F
  28. TEST_F
  29. TEST_F
  30. TEST_F
  31. TEST_F
  32. TEST_F
  33. TEST_F

/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "FrameTestHelpers.h"
#include "URLTestHelpers.h"
#include "WebFrame.h"
#include "WebURLLoaderOptions.h"
#include "WebView.h"
#include "public/platform/Platform.h"
#include "public/platform/WebString.h"
#include "public/platform/WebThread.h"
#include "public/platform/WebURL.h"
#include "public/platform/WebURLLoader.h"
#include "public/platform/WebURLLoaderClient.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/WebURLResponse.h"
#include "public/platform/WebUnitTestSupport.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"

#include <gtest/gtest.h>

using namespace blink;
using blink::URLTestHelpers::toKURL;

namespace {

class AssociatedURLLoaderTest : public testing::Test,
                                public WebURLLoaderClient {
public:
    AssociatedURLLoaderTest()
        :  m_willSendRequest(false)
        ,  m_didSendData(false)
        ,  m_didReceiveResponse(false)
        ,  m_didReceiveData(false)
        ,  m_didReceiveCachedMetadata(false)
        ,  m_didFinishLoading(false)
        ,  m_didFail(false)
        ,  m_runningMessageLoop(false)
    {
        // Reuse one of the test files from WebFrameTest.
        m_baseFilePath = Platform::current()->unitTestSupport()->webKitRootDir();
        m_baseFilePath.append("/Source/web/tests/data/");
        m_frameFilePath = m_baseFilePath;
        m_frameFilePath.append("iframes_test.html");
    }

    WebCore::KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename)
    {
        WebURLResponse response;
        response.initialize();
        response.setMIMEType("text/html");
        WTF::String localPath = m_baseFilePath;
        localPath.append(filename);
        WebCore::KURL url = toKURL(urlRoot + filename.utf8().data());
        Platform::current()->unitTestSupport()->registerMockedURL(url, response, localPath);
        return url;
    }

    void SetUp()
    {
        m_helper.initialize();

        std::string urlRoot = "http://www.test.com/";
        WebCore::KURL url = RegisterMockedUrl(urlRoot, "iframes_test.html");
        const char* iframeSupportFiles[] = {
            "invisible_iframe.html",
            "visible_iframe.html",
            "zero_sized_iframe.html",
        };
        for (size_t i = 0; i < arraysize(iframeSupportFiles); ++i) {
            RegisterMockedUrl(urlRoot, iframeSupportFiles[i]);
        }

        WebURLRequest request;
        request.initialize();
        request.setURL(url);
        mainFrame()->loadRequest(request);
        serveRequests();

        Platform::current()->unitTestSupport()->unregisterMockedURL(url);
    }

    void TearDown()
    {
        Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
    }

    void serveRequests()
    {
        Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
    }

    PassOwnPtr<WebURLLoader> createAssociatedURLLoader(const WebURLLoaderOptions options = WebURLLoaderOptions())
    {
        return adoptPtr(mainFrame()->createAssociatedURLLoader(options));
    }

    // WebURLLoaderClient implementation.
    void willSendRequest(WebURLLoader* loader, WebURLRequest& newRequest, const WebURLResponse& redirectResponse)
    {
        m_willSendRequest = true;
        EXPECT_EQ(m_expectedLoader, loader);
        EXPECT_EQ(m_expectedNewRequest.url(), newRequest.url());
        EXPECT_EQ(m_expectedRedirectResponse.url(), redirectResponse.url());
        EXPECT_EQ(m_expectedRedirectResponse.httpStatusCode(), redirectResponse.httpStatusCode());
        EXPECT_EQ(m_expectedRedirectResponse.mimeType(), redirectResponse.mimeType());
    }

    void didSendData(WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
    {
        m_didSendData = true;
        EXPECT_EQ(m_expectedLoader, loader);
    }

    void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response)
    {
        m_didReceiveResponse = true;
        m_actualResponse = WebURLResponse(response);
        EXPECT_EQ(m_expectedLoader, loader);
        EXPECT_EQ(m_expectedResponse.url(), response.url());
        EXPECT_EQ(m_expectedResponse.httpStatusCode(), response.httpStatusCode());
    }

    void didDownloadData(WebURLLoader* loader, int dataLength, int encodedDataLength)
    {
        m_didDownloadData = true;
        EXPECT_EQ(m_expectedLoader, loader);
    }

    void didReceiveData(WebURLLoader* loader, const char* data, int dataLength, int encodedDataLength)
    {
        m_didReceiveData = true;
        EXPECT_EQ(m_expectedLoader, loader);
        EXPECT_TRUE(data);
        EXPECT_GT(dataLength, 0);
    }

    void didReceiveCachedMetadata(WebURLLoader* loader, const char* data, int dataLength)
    {
        m_didReceiveCachedMetadata = true;
        EXPECT_EQ(m_expectedLoader, loader);
    }

    void didFinishLoading(WebURLLoader* loader, double finishTime, int64_t encodedDataLength)
    {
        m_didFinishLoading = true;
        EXPECT_EQ(m_expectedLoader, loader);
    }

    void didFail(WebURLLoader* loader, const WebURLError& error)
    {
        m_didFail = true;
        EXPECT_EQ(m_expectedLoader, loader);
        if (m_runningMessageLoop) {
            m_runningMessageLoop = false;
            Platform::current()->currentThread()->exitRunLoop();
        }
    }

    void CheckMethodFails(const char* unsafeMethod)
    {
        WebURLRequest request;
        request.initialize();
        request.setURL(toKURL("http://www.test.com/success.html"));
        request.setHTTPMethod(WebString::fromUTF8(unsafeMethod));
        WebURLLoaderOptions options;
        options.untrustedHTTP = true;
        CheckFails(request, options);
    }

    void CheckHeaderFails(const char* headerField)
    {
        CheckHeaderFails(headerField, "foo");
    }

    void CheckHeaderFails(const char* headerField, const char* headerValue)
    {
        WebURLRequest request;
        request.initialize();
        request.setURL(toKURL("http://www.test.com/success.html"));
        if (equalIgnoringCase(WebString::fromUTF8(headerField), "referer"))
            request.setHTTPReferrer(WebString::fromUTF8(headerValue), blink::WebReferrerPolicyDefault);
        else
            request.setHTTPHeaderField(WebString::fromUTF8(headerField), WebString::fromUTF8(headerValue));
        WebURLLoaderOptions options;
        options.untrustedHTTP = true;
        CheckFails(request, options);
    }

    void CheckFails(const WebURLRequest& request, WebURLLoaderOptions options = WebURLLoaderOptions())
    {
        m_expectedLoader = createAssociatedURLLoader(options);
        EXPECT_TRUE(m_expectedLoader);
        m_didFail = false;
        m_expectedLoader->loadAsynchronously(request, this);
        // Failure should not be reported synchronously.
        EXPECT_FALSE(m_didFail);
        // Allow the loader to return the error.
        m_runningMessageLoop = true;
        Platform::current()->currentThread()->enterRunLoop();
        EXPECT_TRUE(m_didFail);
        EXPECT_FALSE(m_didReceiveResponse);
    }

    bool CheckAccessControlHeaders(const char* headerName, bool exposed)
    {
        std::string id("http://www.other.com/CheckAccessControlExposeHeaders_");
        id.append(headerName);
        if (exposed)
            id.append("-Exposed");
        id.append(".html");

        WebCore::KURL url = toKURL(id);
        WebURLRequest request;
        request.initialize();
        request.setURL(url);

        WebString headerNameString(WebString::fromUTF8(headerName));
        m_expectedResponse = WebURLResponse();
        m_expectedResponse.initialize();
        m_expectedResponse.setMIMEType("text/html");
        m_expectedResponse.setHTTPStatusCode(200);
        m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
        if (exposed)
            m_expectedResponse.addHTTPHeaderField("access-control-expose-headers", headerNameString);
        m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
        Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

        WebURLLoaderOptions options;
        options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
        m_expectedLoader = createAssociatedURLLoader(options);
        EXPECT_TRUE(m_expectedLoader);
        m_expectedLoader->loadAsynchronously(request, this);
        serveRequests();
        EXPECT_TRUE(m_didReceiveResponse);
        EXPECT_TRUE(m_didReceiveData);
        EXPECT_TRUE(m_didFinishLoading);

        return !m_actualResponse.httpHeaderField(headerNameString).isEmpty();
    }

    WebFrame* mainFrame() const { return m_helper.webView()->mainFrame(); }

protected:
    WTF::String m_baseFilePath;
    WTF::String m_frameFilePath;
    FrameTestHelpers::WebViewHelper m_helper;

    OwnPtr<WebURLLoader> m_expectedLoader;
    WebURLResponse m_actualResponse;
    WebURLResponse m_expectedResponse;
    WebURLRequest m_expectedNewRequest;
    WebURLResponse m_expectedRedirectResponse;
    bool m_willSendRequest;
    bool m_didSendData;
    bool m_didReceiveResponse;
    bool m_didDownloadData;
    bool m_didReceiveData;
    bool m_didReceiveCachedMetadata;
    bool m_didFinishLoading;
    bool m_didFail;
    bool m_runningMessageLoop;
};

// Test a successful same-origin URL load.
TEST_F(AssociatedURLLoaderTest, SameOriginSuccess)
{
    WebCore::KURL url = toKURL("http://www.test.com/SameOriginSuccess.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    m_expectedLoader = createAssociatedURLLoader();
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);
}

// Test that the same-origin restriction is the default.
TEST_F(AssociatedURLLoaderTest, SameOriginRestriction)
{
    // This is cross-origin since the frame was loaded from www.test.com.
    WebCore::KURL url = toKURL("http://www.other.com/SameOriginRestriction.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);
    CheckFails(request);
}

// Test a successful cross-origin load.
TEST_F(AssociatedURLLoaderTest, CrossOriginSuccess)
{
    // This is cross-origin since the frame was loaded from www.test.com.
    WebCore::KURL url = toKURL("http://www.other.com/CrossOriginSuccess.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);
}

// Test a successful cross-origin load using CORS.
TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess)
{
    // This is cross-origin since the frame was loaded from www.test.com.
    WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);
}

// Test an unsuccessful cross-origin load using CORS.
TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailure)
{
    // This is cross-origin since the frame was loaded from www.test.com.
    WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    // Send credentials. This will cause the CORS checks to fail, because credentials can't be
    // sent to a server which returns the header "access-control-allow-origin" with "*" as its value.
    options.allowCredentials = true;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);

    // Failure should not be reported synchronously.
    EXPECT_FALSE(m_didFail);
    // The loader needs to receive the response, before doing the CORS check.
    serveRequests();
    EXPECT_TRUE(m_didFail);
    EXPECT_FALSE(m_didReceiveResponse);
}

// Test an unsuccessful cross-origin load using CORS.
TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailureBadStatusCode)
{
    // This is cross-origin since the frame was loaded from www.test.com.
    WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(0);
    m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);

    // Failure should not be reported synchronously.
    EXPECT_FALSE(m_didFail);
    // The loader needs to receive the response, before doing the CORS check.
    serveRequests();
    EXPECT_TRUE(m_didFail);
    EXPECT_FALSE(m_didReceiveResponse);
}

// Test a same-origin URL redirect and load.
TEST_F(AssociatedURLLoaderTest, RedirectSuccess)
{
    WebCore::KURL url = toKURL("http://www.test.com/RedirectSuccess.html");
    char redirect[] = "http://www.test.com/RedirectSuccess2.html";  // Same-origin
    WebCore::KURL redirectURL = toKURL(redirect);

    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    m_expectedRedirectResponse = WebURLResponse();
    m_expectedRedirectResponse.initialize();
    m_expectedRedirectResponse.setMIMEType("text/html");
    m_expectedRedirectResponse.setHTTPStatusCode(301);
    m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);

    m_expectedNewRequest = WebURLRequest();
    m_expectedNewRequest.initialize();
    m_expectedNewRequest.setURL(redirectURL);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);

    m_expectedLoader = createAssociatedURLLoader();
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    EXPECT_TRUE(m_willSendRequest);
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);
}

// Test that a cross origin redirect response without CORS headers fails.
// Disabled, http://crbug.com/240912 .
TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlFailure)
{
    WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html");
    char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html";  // Cross-origin
    WebCore::KURL redirectURL = toKURL(redirect);

    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    // Create a redirect response without CORS headers.
    m_expectedRedirectResponse = WebURLResponse();
    m_expectedRedirectResponse.initialize();
    m_expectedRedirectResponse.setMIMEType("text/html");
    m_expectedRedirectResponse.setHTTPStatusCode(301);
    m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    // We should not receive a notification for the redirect or any response.
    EXPECT_FALSE(m_willSendRequest);
    EXPECT_FALSE(m_didReceiveResponse);
    EXPECT_FALSE(m_didReceiveData);
    EXPECT_FALSE(m_didFail);
}

// Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess)
{
    WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html");
    char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html";  // Cross-origin
    WebCore::KURL redirectURL = toKURL(redirect);

    WebURLRequest request;
    request.initialize();
    request.setURL(url);

    // Create a redirect response that allows the redirect to pass the access control checks.
    m_expectedRedirectResponse = WebURLResponse();
    m_expectedRedirectResponse.initialize();
    m_expectedRedirectResponse.setMIMEType("text/html");
    m_expectedRedirectResponse.setHTTPStatusCode(301);
    m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    m_expectedRedirectResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);

    m_expectedNewRequest = WebURLRequest();
    m_expectedNewRequest.initialize();
    m_expectedNewRequest.setURL(redirectURL);

    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    // We should not receive a notification for the redirect.
    EXPECT_FALSE(m_willSendRequest);
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);
}

// Test that untrusted loads can't use a forbidden method.
TEST_F(AssociatedURLLoaderTest, UntrustedCheckMethods)
{
    // Check non-token method fails.
    CheckMethodFails("GET()");
    CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234");

    // Forbidden methods should fail regardless of casing.
    CheckMethodFails("CoNneCt");
    CheckMethodFails("TrAcK");
    CheckMethodFails("TrAcE");
}

// Test that untrusted loads can't use a forbidden header field.
TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders)
{
    // Check non-token header fails.
    CheckHeaderFails("foo()");

    // Check forbidden headers fail.
    CheckHeaderFails("accept-charset");
    CheckHeaderFails("accept-encoding");
    CheckHeaderFails("connection");
    CheckHeaderFails("content-length");
    CheckHeaderFails("cookie");
    CheckHeaderFails("cookie2");
    CheckHeaderFails("content-transfer-encoding");
    CheckHeaderFails("date");
    CheckHeaderFails("expect");
    CheckHeaderFails("host");
    CheckHeaderFails("keep-alive");
    CheckHeaderFails("origin");
    CheckHeaderFails("referer");
    CheckHeaderFails("te");
    CheckHeaderFails("trailer");
    CheckHeaderFails("transfer-encoding");
    CheckHeaderFails("upgrade");
    CheckHeaderFails("user-agent");
    CheckHeaderFails("via");

    CheckHeaderFails("proxy-");
    CheckHeaderFails("proxy-foo");
    CheckHeaderFails("sec-");
    CheckHeaderFails("sec-foo");

    // Check that validation is case-insensitive.
    CheckHeaderFails("AcCePt-ChArSeT");
    CheckHeaderFails("ProXy-FoO");

    // Check invalid header values.
    CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
}

// Test that the loader filters response headers according to the CORS standard.
TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting)
{
    // Test that whitelisted headers are returned without exposing them.
    EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false));
    EXPECT_TRUE(CheckAccessControlHeaders("content-language", false));
    EXPECT_TRUE(CheckAccessControlHeaders("content-type", false));
    EXPECT_TRUE(CheckAccessControlHeaders("expires", false));
    EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false));
    EXPECT_TRUE(CheckAccessControlHeaders("pragma", false));

    // Test that non-whitelisted headers aren't returned.
    EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));

    // Test that Set-Cookie headers aren't returned.
    EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
    EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));

    // Test that exposed headers that aren't whitelisted are returned.
    EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));

    // Test that Set-Cookie headers aren't returned, even if exposed.
    EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
}

// Test that the loader can allow non-whitelisted response headers for trusted CORS loads.
TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders)
{
    WebURLRequest request;
    request.initialize();
    WebCore::KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
    request.setURL(url);

    WebString headerNameString(WebString::fromUTF8("non-whitelisted"));
    m_expectedResponse = WebURLResponse();
    m_expectedResponse.initialize();
    m_expectedResponse.setMIMEType("text/html");
    m_expectedResponse.setHTTPStatusCode(200);
    m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
    m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
    Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);

    WebURLLoaderOptions options;
    options.exposeAllResponseHeaders = true; // This turns off response whitelisting.
    options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    m_expectedLoader = createAssociatedURLLoader(options);
    EXPECT_TRUE(m_expectedLoader);
    m_expectedLoader->loadAsynchronously(request, this);
    serveRequests();
    EXPECT_TRUE(m_didReceiveResponse);
    EXPECT_TRUE(m_didReceiveData);
    EXPECT_TRUE(m_didFinishLoading);

    EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty());
}

}

/* [<][>][^][v][top][bottom][index][help] */