Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2011 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #include "public/platform/Platform.h"
     34 #include "public/platform/WebString.h"
     35 #include "public/platform/WebThread.h"
     36 #include "public/platform/WebURL.h"
     37 #include "public/platform/WebURLLoader.h"
     38 #include "public/platform/WebURLLoaderClient.h"
     39 #include "public/platform/WebURLRequest.h"
     40 #include "public/platform/WebURLResponse.h"
     41 #include "public/platform/WebUnitTestSupport.h"
     42 #include "public/web/WebFrame.h"
     43 #include "public/web/WebURLLoaderOptions.h"
     44 #include "public/web/WebView.h"
     45 #include "web/tests/FrameTestHelpers.h"
     46 #include "web/tests/URLTestHelpers.h"
     47 #include "wtf/text/CString.h"
     48 #include "wtf/text/WTFString.h"
     49 
     50 #include <gtest/gtest.h>
     51 
     52 using namespace blink;
     53 using blink::URLTestHelpers::toKURL;
     54 
     55 namespace {
     56 
     57 class AssociatedURLLoaderTest : public testing::Test,
     58                                 public WebURLLoaderClient {
     59 public:
     60     AssociatedURLLoaderTest()
     61         :  m_willSendRequest(false)
     62         ,  m_didSendData(false)
     63         ,  m_didReceiveResponse(false)
     64         ,  m_didReceiveData(false)
     65         ,  m_didReceiveCachedMetadata(false)
     66         ,  m_didFinishLoading(false)
     67         ,  m_didFail(false)
     68         ,  m_runningMessageLoop(false)
     69     {
     70         // Reuse one of the test files from WebFrameTest.
     71         m_baseFilePath = Platform::current()->unitTestSupport()->webKitRootDir();
     72         m_baseFilePath.append("/Source/web/tests/data/");
     73         m_frameFilePath = m_baseFilePath;
     74         m_frameFilePath.append("iframes_test.html");
     75     }
     76 
     77     WebCore::KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename)
     78     {
     79         WebURLResponse response;
     80         response.initialize();
     81         response.setMIMEType("text/html");
     82         WTF::String localPath = m_baseFilePath;
     83         localPath.append(filename);
     84         WebCore::KURL url = toKURL(urlRoot + filename.utf8().data());
     85         Platform::current()->unitTestSupport()->registerMockedURL(url, response, localPath);
     86         return url;
     87     }
     88 
     89     void SetUp()
     90     {
     91         m_helper.initialize();
     92 
     93         std::string urlRoot = "http://www.test.com/";
     94         WebCore::KURL url = RegisterMockedUrl(urlRoot, "iframes_test.html");
     95         const char* iframeSupportFiles[] = {
     96             "invisible_iframe.html",
     97             "visible_iframe.html",
     98             "zero_sized_iframe.html",
     99         };
    100         for (size_t i = 0; i < arraysize(iframeSupportFiles); ++i) {
    101             RegisterMockedUrl(urlRoot, iframeSupportFiles[i]);
    102         }
    103 
    104         FrameTestHelpers::loadFrame(mainFrame(), url.string().utf8().data());
    105 
    106         Platform::current()->unitTestSupport()->unregisterMockedURL(url);
    107     }
    108 
    109     void TearDown()
    110     {
    111         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
    112     }
    113 
    114     void serveRequests()
    115     {
    116         Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
    117     }
    118 
    119     PassOwnPtr<WebURLLoader> createAssociatedURLLoader(const WebURLLoaderOptions options = WebURLLoaderOptions())
    120     {
    121         return adoptPtr(mainFrame()->createAssociatedURLLoader(options));
    122     }
    123 
    124     // WebURLLoaderClient implementation.
    125     void willSendRequest(WebURLLoader* loader, WebURLRequest& newRequest, const WebURLResponse& redirectResponse)
    126     {
    127         m_willSendRequest = true;
    128         EXPECT_EQ(m_expectedLoader, loader);
    129         EXPECT_EQ(m_expectedNewRequest.url(), newRequest.url());
    130         // Check that CORS simple headers are transferred to the new request.
    131         EXPECT_EQ(m_expectedNewRequest.httpHeaderField("accept"), newRequest.httpHeaderField("accept"));
    132         EXPECT_EQ(m_expectedRedirectResponse.url(), redirectResponse.url());
    133         EXPECT_EQ(m_expectedRedirectResponse.httpStatusCode(), redirectResponse.httpStatusCode());
    134         EXPECT_EQ(m_expectedRedirectResponse.mimeType(), redirectResponse.mimeType());
    135     }
    136 
    137     void didSendData(WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
    138     {
    139         m_didSendData = true;
    140         EXPECT_EQ(m_expectedLoader, loader);
    141     }
    142 
    143     void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response)
    144     {
    145         m_didReceiveResponse = true;
    146         m_actualResponse = WebURLResponse(response);
    147         EXPECT_EQ(m_expectedLoader, loader);
    148         EXPECT_EQ(m_expectedResponse.url(), response.url());
    149         EXPECT_EQ(m_expectedResponse.httpStatusCode(), response.httpStatusCode());
    150     }
    151 
    152     void didDownloadData(WebURLLoader* loader, int dataLength, int encodedDataLength)
    153     {
    154         m_didDownloadData = true;
    155         EXPECT_EQ(m_expectedLoader, loader);
    156     }
    157 
    158     void didReceiveData(WebURLLoader* loader, const char* data, int dataLength, int encodedDataLength)
    159     {
    160         m_didReceiveData = true;
    161         EXPECT_EQ(m_expectedLoader, loader);
    162         EXPECT_TRUE(data);
    163         EXPECT_GT(dataLength, 0);
    164     }
    165 
    166     void didReceiveCachedMetadata(WebURLLoader* loader, const char* data, int dataLength)
    167     {
    168         m_didReceiveCachedMetadata = true;
    169         EXPECT_EQ(m_expectedLoader, loader);
    170     }
    171 
    172     void didFinishLoading(WebURLLoader* loader, double finishTime, int64_t encodedDataLength)
    173     {
    174         m_didFinishLoading = true;
    175         EXPECT_EQ(m_expectedLoader, loader);
    176     }
    177 
    178     void didFail(WebURLLoader* loader, const WebURLError& error)
    179     {
    180         m_didFail = true;
    181         EXPECT_EQ(m_expectedLoader, loader);
    182         if (m_runningMessageLoop) {
    183             m_runningMessageLoop = false;
    184             Platform::current()->currentThread()->exitRunLoop();
    185         }
    186     }
    187 
    188     void CheckMethodFails(const char* unsafeMethod)
    189     {
    190         WebURLRequest request;
    191         request.initialize();
    192         request.setURL(toKURL("http://www.test.com/success.html"));
    193         request.setHTTPMethod(WebString::fromUTF8(unsafeMethod));
    194         WebURLLoaderOptions options;
    195         options.untrustedHTTP = true;
    196         CheckFails(request, options);
    197     }
    198 
    199     void CheckHeaderFails(const char* headerField)
    200     {
    201         CheckHeaderFails(headerField, "foo");
    202     }
    203 
    204     void CheckHeaderFails(const char* headerField, const char* headerValue)
    205     {
    206         WebURLRequest request;
    207         request.initialize();
    208         request.setURL(toKURL("http://www.test.com/success.html"));
    209         if (equalIgnoringCase(WebString::fromUTF8(headerField), "referer"))
    210             request.setHTTPReferrer(WebString::fromUTF8(headerValue), blink::WebReferrerPolicyDefault);
    211         else
    212             request.setHTTPHeaderField(WebString::fromUTF8(headerField), WebString::fromUTF8(headerValue));
    213         WebURLLoaderOptions options;
    214         options.untrustedHTTP = true;
    215         CheckFails(request, options);
    216     }
    217 
    218     void CheckFails(const WebURLRequest& request, WebURLLoaderOptions options = WebURLLoaderOptions())
    219     {
    220         m_expectedLoader = createAssociatedURLLoader(options);
    221         EXPECT_TRUE(m_expectedLoader);
    222         m_didFail = false;
    223         m_expectedLoader->loadAsynchronously(request, this);
    224         // Failure should not be reported synchronously.
    225         EXPECT_FALSE(m_didFail);
    226         // Allow the loader to return the error.
    227         m_runningMessageLoop = true;
    228         Platform::current()->currentThread()->enterRunLoop();
    229         EXPECT_TRUE(m_didFail);
    230         EXPECT_FALSE(m_didReceiveResponse);
    231     }
    232 
    233     bool CheckAccessControlHeaders(const char* headerName, bool exposed)
    234     {
    235         std::string id("http://www.other.com/CheckAccessControlExposeHeaders_");
    236         id.append(headerName);
    237         if (exposed)
    238             id.append("-Exposed");
    239         id.append(".html");
    240 
    241         WebCore::KURL url = toKURL(id);
    242         WebURLRequest request;
    243         request.initialize();
    244         request.setURL(url);
    245 
    246         WebString headerNameString(WebString::fromUTF8(headerName));
    247         m_expectedResponse = WebURLResponse();
    248         m_expectedResponse.initialize();
    249         m_expectedResponse.setMIMEType("text/html");
    250         m_expectedResponse.setHTTPStatusCode(200);
    251         m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
    252         if (exposed)
    253             m_expectedResponse.addHTTPHeaderField("access-control-expose-headers", headerNameString);
    254         m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
    255         Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    256 
    257         WebURLLoaderOptions options;
    258         options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    259         m_expectedLoader = createAssociatedURLLoader(options);
    260         EXPECT_TRUE(m_expectedLoader);
    261         m_expectedLoader->loadAsynchronously(request, this);
    262         serveRequests();
    263         EXPECT_TRUE(m_didReceiveResponse);
    264         EXPECT_TRUE(m_didReceiveData);
    265         EXPECT_TRUE(m_didFinishLoading);
    266 
    267         return !m_actualResponse.httpHeaderField(headerNameString).isEmpty();
    268     }
    269 
    270     WebFrame* mainFrame() const { return m_helper.webView()->mainFrame(); }
    271 
    272 protected:
    273     WTF::String m_baseFilePath;
    274     WTF::String m_frameFilePath;
    275     FrameTestHelpers::WebViewHelper m_helper;
    276 
    277     OwnPtr<WebURLLoader> m_expectedLoader;
    278     WebURLResponse m_actualResponse;
    279     WebURLResponse m_expectedResponse;
    280     WebURLRequest m_expectedNewRequest;
    281     WebURLResponse m_expectedRedirectResponse;
    282     bool m_willSendRequest;
    283     bool m_didSendData;
    284     bool m_didReceiveResponse;
    285     bool m_didDownloadData;
    286     bool m_didReceiveData;
    287     bool m_didReceiveCachedMetadata;
    288     bool m_didFinishLoading;
    289     bool m_didFail;
    290     bool m_runningMessageLoop;
    291 };
    292 
    293 // Test a successful same-origin URL load.
    294 TEST_F(AssociatedURLLoaderTest, SameOriginSuccess)
    295 {
    296     WebCore::KURL url = toKURL("http://www.test.com/SameOriginSuccess.html");
    297     WebURLRequest request;
    298     request.initialize();
    299     request.setURL(url);
    300 
    301     m_expectedResponse = WebURLResponse();
    302     m_expectedResponse.initialize();
    303     m_expectedResponse.setMIMEType("text/html");
    304     m_expectedResponse.setHTTPStatusCode(200);
    305     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    306 
    307     m_expectedLoader = createAssociatedURLLoader();
    308     EXPECT_TRUE(m_expectedLoader);
    309     m_expectedLoader->loadAsynchronously(request, this);
    310     serveRequests();
    311     EXPECT_TRUE(m_didReceiveResponse);
    312     EXPECT_TRUE(m_didReceiveData);
    313     EXPECT_TRUE(m_didFinishLoading);
    314 }
    315 
    316 // Test that the same-origin restriction is the default.
    317 TEST_F(AssociatedURLLoaderTest, SameOriginRestriction)
    318 {
    319     // This is cross-origin since the frame was loaded from www.test.com.
    320     WebCore::KURL url = toKURL("http://www.other.com/SameOriginRestriction.html");
    321     WebURLRequest request;
    322     request.initialize();
    323     request.setURL(url);
    324     CheckFails(request);
    325 }
    326 
    327 // Test a successful cross-origin load.
    328 TEST_F(AssociatedURLLoaderTest, CrossOriginSuccess)
    329 {
    330     // This is cross-origin since the frame was loaded from www.test.com.
    331     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginSuccess.html");
    332     WebURLRequest request;
    333     request.initialize();
    334     request.setURL(url);
    335 
    336     m_expectedResponse = WebURLResponse();
    337     m_expectedResponse.initialize();
    338     m_expectedResponse.setMIMEType("text/html");
    339     m_expectedResponse.setHTTPStatusCode(200);
    340     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    341 
    342     WebURLLoaderOptions options;
    343     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
    344     m_expectedLoader = createAssociatedURLLoader(options);
    345     EXPECT_TRUE(m_expectedLoader);
    346     m_expectedLoader->loadAsynchronously(request, this);
    347     serveRequests();
    348     EXPECT_TRUE(m_didReceiveResponse);
    349     EXPECT_TRUE(m_didReceiveData);
    350     EXPECT_TRUE(m_didFinishLoading);
    351 }
    352 
    353 // Test a successful cross-origin load using CORS.
    354 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess)
    355 {
    356     // This is cross-origin since the frame was loaded from www.test.com.
    357     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html");
    358     WebURLRequest request;
    359     request.initialize();
    360     request.setURL(url);
    361 
    362     m_expectedResponse = WebURLResponse();
    363     m_expectedResponse.initialize();
    364     m_expectedResponse.setMIMEType("text/html");
    365     m_expectedResponse.setHTTPStatusCode(200);
    366     m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    367     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    368 
    369     WebURLLoaderOptions options;
    370     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    371     m_expectedLoader = createAssociatedURLLoader(options);
    372     EXPECT_TRUE(m_expectedLoader);
    373     m_expectedLoader->loadAsynchronously(request, this);
    374     serveRequests();
    375     EXPECT_TRUE(m_didReceiveResponse);
    376     EXPECT_TRUE(m_didReceiveData);
    377     EXPECT_TRUE(m_didFinishLoading);
    378 }
    379 
    380 // Test an unsuccessful cross-origin load using CORS.
    381 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailure)
    382 {
    383     // This is cross-origin since the frame was loaded from www.test.com.
    384     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
    385     WebURLRequest request;
    386     request.initialize();
    387     request.setURL(url);
    388 
    389     m_expectedResponse = WebURLResponse();
    390     m_expectedResponse.initialize();
    391     m_expectedResponse.setMIMEType("text/html");
    392     m_expectedResponse.setHTTPStatusCode(200);
    393     m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    394     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    395 
    396     WebURLLoaderOptions options;
    397     // Send credentials. This will cause the CORS checks to fail, because credentials can't be
    398     // sent to a server which returns the header "access-control-allow-origin" with "*" as its value.
    399     options.allowCredentials = true;
    400     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    401     m_expectedLoader = createAssociatedURLLoader(options);
    402     EXPECT_TRUE(m_expectedLoader);
    403     m_expectedLoader->loadAsynchronously(request, this);
    404 
    405     // Failure should not be reported synchronously.
    406     EXPECT_FALSE(m_didFail);
    407     // The loader needs to receive the response, before doing the CORS check.
    408     serveRequests();
    409     EXPECT_TRUE(m_didFail);
    410     EXPECT_FALSE(m_didReceiveResponse);
    411 }
    412 
    413 // Test an unsuccessful cross-origin load using CORS.
    414 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailureBadStatusCode)
    415 {
    416     // This is cross-origin since the frame was loaded from www.test.com.
    417     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
    418     WebURLRequest request;
    419     request.initialize();
    420     request.setURL(url);
    421 
    422     m_expectedResponse = WebURLResponse();
    423     m_expectedResponse.initialize();
    424     m_expectedResponse.setMIMEType("text/html");
    425     m_expectedResponse.setHTTPStatusCode(0);
    426     m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    427     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    428 
    429     WebURLLoaderOptions options;
    430     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    431     m_expectedLoader = createAssociatedURLLoader(options);
    432     EXPECT_TRUE(m_expectedLoader);
    433     m_expectedLoader->loadAsynchronously(request, this);
    434 
    435     // Failure should not be reported synchronously.
    436     EXPECT_FALSE(m_didFail);
    437     // The loader needs to receive the response, before doing the CORS check.
    438     serveRequests();
    439     EXPECT_TRUE(m_didFail);
    440     EXPECT_FALSE(m_didReceiveResponse);
    441 }
    442 
    443 // Test a same-origin URL redirect and load.
    444 TEST_F(AssociatedURLLoaderTest, RedirectSuccess)
    445 {
    446     WebCore::KURL url = toKURL("http://www.test.com/RedirectSuccess.html");
    447     char redirect[] = "http://www.test.com/RedirectSuccess2.html";  // Same-origin
    448     WebCore::KURL redirectURL = toKURL(redirect);
    449 
    450     WebURLRequest request;
    451     request.initialize();
    452     request.setURL(url);
    453 
    454     m_expectedRedirectResponse = WebURLResponse();
    455     m_expectedRedirectResponse.initialize();
    456     m_expectedRedirectResponse.setMIMEType("text/html");
    457     m_expectedRedirectResponse.setHTTPStatusCode(301);
    458     m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    459     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
    460 
    461     m_expectedNewRequest = WebURLRequest();
    462     m_expectedNewRequest.initialize();
    463     m_expectedNewRequest.setURL(redirectURL);
    464 
    465     m_expectedResponse = WebURLResponse();
    466     m_expectedResponse.initialize();
    467     m_expectedResponse.setMIMEType("text/html");
    468     m_expectedResponse.setHTTPStatusCode(200);
    469     Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);
    470 
    471     m_expectedLoader = createAssociatedURLLoader();
    472     EXPECT_TRUE(m_expectedLoader);
    473     m_expectedLoader->loadAsynchronously(request, this);
    474     serveRequests();
    475     EXPECT_TRUE(m_willSendRequest);
    476     EXPECT_TRUE(m_didReceiveResponse);
    477     EXPECT_TRUE(m_didReceiveData);
    478     EXPECT_TRUE(m_didFinishLoading);
    479 }
    480 
    481 // Test that a cross origin redirect response without CORS headers fails.
    482 // Disabled, http://crbug.com/240912 .
    483 TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlFailure)
    484 {
    485     WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html");
    486     char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html";  // Cross-origin
    487     WebCore::KURL redirectURL = toKURL(redirect);
    488 
    489     WebURLRequest request;
    490     request.initialize();
    491     request.setURL(url);
    492 
    493     // Create a redirect response without CORS headers.
    494     m_expectedRedirectResponse = WebURLResponse();
    495     m_expectedRedirectResponse.initialize();
    496     m_expectedRedirectResponse.setMIMEType("text/html");
    497     m_expectedRedirectResponse.setHTTPStatusCode(301);
    498     m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    499     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
    500 
    501     WebURLLoaderOptions options;
    502     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    503     m_expectedLoader = createAssociatedURLLoader(options);
    504     EXPECT_TRUE(m_expectedLoader);
    505     m_expectedLoader->loadAsynchronously(request, this);
    506     serveRequests();
    507     // We should not receive a notification for the redirect or any response.
    508     EXPECT_FALSE(m_willSendRequest);
    509     EXPECT_FALSE(m_didReceiveResponse);
    510     EXPECT_FALSE(m_didReceiveData);
    511     EXPECT_FALSE(m_didFail);
    512 }
    513 
    514 // Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
    515 TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess)
    516 {
    517     WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html");
    518     char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html";  // Cross-origin
    519     WebCore::KURL redirectURL = toKURL(redirect);
    520 
    521     WebURLRequest request;
    522     request.initialize();
    523     request.setURL(url);
    524     // Add a CORS simple header.
    525     request.setHTTPHeaderField("accept", "application/json");
    526 
    527     // Create a redirect response that allows the redirect to pass the access control checks.
    528     m_expectedRedirectResponse = WebURLResponse();
    529     m_expectedRedirectResponse.initialize();
    530     m_expectedRedirectResponse.setMIMEType("text/html");
    531     m_expectedRedirectResponse.setHTTPStatusCode(301);
    532     m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
    533     m_expectedRedirectResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    534     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
    535 
    536     m_expectedNewRequest = WebURLRequest();
    537     m_expectedNewRequest.initialize();
    538     m_expectedNewRequest.setURL(redirectURL);
    539     m_expectedNewRequest.setHTTPHeaderField("accept", "application/json");
    540 
    541     m_expectedResponse = WebURLResponse();
    542     m_expectedResponse.initialize();
    543     m_expectedResponse.setMIMEType("text/html");
    544     m_expectedResponse.setHTTPStatusCode(200);
    545     m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
    546     Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);
    547 
    548     WebURLLoaderOptions options;
    549     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    550     m_expectedLoader = createAssociatedURLLoader(options);
    551     EXPECT_TRUE(m_expectedLoader);
    552     m_expectedLoader->loadAsynchronously(request, this);
    553     serveRequests();
    554     // We should not receive a notification for the redirect.
    555     EXPECT_FALSE(m_willSendRequest);
    556     EXPECT_TRUE(m_didReceiveResponse);
    557     EXPECT_TRUE(m_didReceiveData);
    558     EXPECT_TRUE(m_didFinishLoading);
    559 }
    560 
    561 // Test that untrusted loads can't use a forbidden method.
    562 TEST_F(AssociatedURLLoaderTest, UntrustedCheckMethods)
    563 {
    564     // Check non-token method fails.
    565     CheckMethodFails("GET()");
    566     CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234");
    567 
    568     // Forbidden methods should fail regardless of casing.
    569     CheckMethodFails("CoNneCt");
    570     CheckMethodFails("TrAcK");
    571     CheckMethodFails("TrAcE");
    572 }
    573 
    574 // Test that untrusted loads can't use a forbidden header field.
    575 TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders)
    576 {
    577     // Check non-token header fails.
    578     CheckHeaderFails("foo()");
    579 
    580     // Check forbidden headers fail.
    581     CheckHeaderFails("accept-charset");
    582     CheckHeaderFails("accept-encoding");
    583     CheckHeaderFails("connection");
    584     CheckHeaderFails("content-length");
    585     CheckHeaderFails("cookie");
    586     CheckHeaderFails("cookie2");
    587     CheckHeaderFails("content-transfer-encoding");
    588     CheckHeaderFails("date");
    589     CheckHeaderFails("expect");
    590     CheckHeaderFails("host");
    591     CheckHeaderFails("keep-alive");
    592     CheckHeaderFails("origin");
    593     CheckHeaderFails("referer");
    594     CheckHeaderFails("te");
    595     CheckHeaderFails("trailer");
    596     CheckHeaderFails("transfer-encoding");
    597     CheckHeaderFails("upgrade");
    598     CheckHeaderFails("user-agent");
    599     CheckHeaderFails("via");
    600 
    601     CheckHeaderFails("proxy-");
    602     CheckHeaderFails("proxy-foo");
    603     CheckHeaderFails("sec-");
    604     CheckHeaderFails("sec-foo");
    605 
    606     // Check that validation is case-insensitive.
    607     CheckHeaderFails("AcCePt-ChArSeT");
    608     CheckHeaderFails("ProXy-FoO");
    609 
    610     // Check invalid header values.
    611     CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
    612 }
    613 
    614 // Test that the loader filters response headers according to the CORS standard.
    615 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting)
    616 {
    617     // Test that whitelisted headers are returned without exposing them.
    618     EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false));
    619     EXPECT_TRUE(CheckAccessControlHeaders("content-language", false));
    620     EXPECT_TRUE(CheckAccessControlHeaders("content-type", false));
    621     EXPECT_TRUE(CheckAccessControlHeaders("expires", false));
    622     EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false));
    623     EXPECT_TRUE(CheckAccessControlHeaders("pragma", false));
    624 
    625     // Test that non-whitelisted headers aren't returned.
    626     EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));
    627 
    628     // Test that Set-Cookie headers aren't returned.
    629     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
    630     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));
    631 
    632     // Test that exposed headers that aren't whitelisted are returned.
    633     EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));
    634 
    635     // Test that Set-Cookie headers aren't returned, even if exposed.
    636     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
    637 }
    638 
    639 // Test that the loader can allow non-whitelisted response headers for trusted CORS loads.
    640 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders)
    641 {
    642     WebURLRequest request;
    643     request.initialize();
    644     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
    645     request.setURL(url);
    646 
    647     WebString headerNameString(WebString::fromUTF8("non-whitelisted"));
    648     m_expectedResponse = WebURLResponse();
    649     m_expectedResponse.initialize();
    650     m_expectedResponse.setMIMEType("text/html");
    651     m_expectedResponse.setHTTPStatusCode(200);
    652     m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
    653     m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
    654     Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
    655 
    656     WebURLLoaderOptions options;
    657     options.exposeAllResponseHeaders = true; // This turns off response whitelisting.
    658     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
    659     m_expectedLoader = createAssociatedURLLoader(options);
    660     EXPECT_TRUE(m_expectedLoader);
    661     m_expectedLoader->loadAsynchronously(request, this);
    662     serveRequests();
    663     EXPECT_TRUE(m_didReceiveResponse);
    664     EXPECT_TRUE(m_didReceiveData);
    665     EXPECT_TRUE(m_didFinishLoading);
    666 
    667     EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty());
    668 }
    669 
    670 }
    671