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 "URLTestHelpers.h" 34 #include "WebFrame.h" 35 #include "WebFrameClient.h" 36 #include "WebURLLoaderOptions.h" 37 #include "WebView.h" 38 #include "public/platform/Platform.h" 39 #include "public/platform/WebString.h" 40 #include "public/platform/WebThread.h" 41 #include "public/platform/WebURL.h" 42 #include "public/platform/WebURLLoader.h" 43 #include "public/platform/WebURLLoaderClient.h" 44 #include "public/platform/WebURLRequest.h" 45 #include "public/platform/WebURLResponse.h" 46 #include "public/platform/WebUnitTestSupport.h" 47 #include "wtf/text/WTFString.h" 48 49 #include <gtest/gtest.h> 50 51 using namespace WebKit; 52 using WebKit::URLTestHelpers::toKURL; 53 54 namespace { 55 56 class TestWebFrameClient : public WebFrameClient { 57 }; 58 59 class AssociatedURLLoaderTest : public testing::Test, 60 public WebURLLoaderClient { 61 public: 62 AssociatedURLLoaderTest() 63 : m_willSendRequest(false) 64 , m_didSendData(false) 65 , m_didReceiveResponse(false) 66 , m_didReceiveData(false) 67 , m_didReceiveCachedMetadata(false) 68 , m_didFinishLoading(false) 69 , m_didFail(false) 70 , m_runningMessageLoop(false) 71 { 72 // Reuse one of the test files from WebFrameTest. 73 m_baseFilePath = Platform::current()->unitTestSupport()->webKitRootDir(); 74 m_baseFilePath.append("/Source/web/tests/data/"); 75 m_frameFilePath = m_baseFilePath; 76 m_frameFilePath.append("iframes_test.html"); 77 } 78 79 WebCore::KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename) 80 { 81 WebURLResponse response; 82 response.initialize(); 83 response.setMIMEType("text/html"); 84 WTF::String localPath = m_baseFilePath; 85 localPath.append(filename); 86 WebCore::KURL url = toKURL(urlRoot + filename.utf8().data()); 87 Platform::current()->unitTestSupport()->registerMockedURL(url, response, localPath); 88 return url; 89 } 90 91 void SetUp() 92 { 93 m_webView = WebView::create(0); 94 m_webView->initializeMainFrame(&m_webFrameClient); 95 96 std::string urlRoot = "http://www.test.com/"; 97 WebCore::KURL url = RegisterMockedUrl(urlRoot, "iframes_test.html"); 98 const char* iframeSupportFiles[] = { 99 "invisible_iframe.html", 100 "visible_iframe.html", 101 "zero_sized_iframe.html", 102 }; 103 for (size_t i = 0; i < arraysize(iframeSupportFiles); ++i) { 104 RegisterMockedUrl(urlRoot, iframeSupportFiles[i]); 105 } 106 107 WebURLRequest request; 108 request.initialize(); 109 request.setURL(url); 110 m_webView->mainFrame()->loadRequest(request); 111 serveRequests(); 112 113 Platform::current()->unitTestSupport()->unregisterMockedURL(url); 114 } 115 116 void TearDown() 117 { 118 Platform::current()->unitTestSupport()->unregisterAllMockedURLs(); 119 m_webView->close(); 120 } 121 122 void serveRequests() 123 { 124 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests(); 125 } 126 127 WebURLLoader* createAssociatedURLLoader(const WebURLLoaderOptions options = WebURLLoaderOptions()) 128 { 129 return m_webView->mainFrame()->createAssociatedURLLoader(options); 130 } 131 132 // WebURLLoaderClient implementation. 133 void willSendRequest(WebURLLoader* loader, WebURLRequest& newRequest, const WebURLResponse& redirectResponse) 134 { 135 m_willSendRequest = true; 136 EXPECT_EQ(m_expectedLoader, loader); 137 EXPECT_EQ(m_expectedNewRequest.url(), newRequest.url()); 138 EXPECT_EQ(m_expectedRedirectResponse.url(), redirectResponse.url()); 139 EXPECT_EQ(m_expectedRedirectResponse.httpStatusCode(), redirectResponse.httpStatusCode()); 140 EXPECT_EQ(m_expectedRedirectResponse.mimeType(), redirectResponse.mimeType()); 141 } 142 143 void didSendData(WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) 144 { 145 m_didSendData = true; 146 EXPECT_EQ(m_expectedLoader, loader); 147 } 148 149 void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response) 150 { 151 m_didReceiveResponse = true; 152 m_actualResponse = WebURLResponse(response); 153 EXPECT_EQ(m_expectedLoader, loader); 154 EXPECT_EQ(m_expectedResponse.url(), response.url()); 155 EXPECT_EQ(m_expectedResponse.httpStatusCode(), response.httpStatusCode()); 156 } 157 158 void didDownloadData(WebURLLoader* loader, int dataLength) 159 { 160 m_didDownloadData = true; 161 EXPECT_EQ(m_expectedLoader, loader); 162 } 163 164 void didReceiveData(WebURLLoader* loader, const char* data, int dataLength, int encodedDataLength) 165 { 166 m_didReceiveData = true; 167 EXPECT_EQ(m_expectedLoader, loader); 168 EXPECT_TRUE(data); 169 EXPECT_GT(dataLength, 0); 170 } 171 172 void didReceiveCachedMetadata(WebURLLoader* loader, const char* data, int dataLength) 173 { 174 m_didReceiveCachedMetadata = true; 175 EXPECT_EQ(m_expectedLoader, loader); 176 } 177 178 void didFinishLoading(WebURLLoader* loader, double finishTime) 179 { 180 m_didFinishLoading = true; 181 EXPECT_EQ(m_expectedLoader, loader); 182 } 183 184 void didFail(WebURLLoader* loader, const WebURLError& error) 185 { 186 m_didFail = true; 187 EXPECT_EQ(m_expectedLoader, loader); 188 if (m_runningMessageLoop) { 189 m_runningMessageLoop = false; 190 Platform::current()->currentThread()->exitRunLoop(); 191 } 192 } 193 194 void CheckMethodFails(const char* unsafeMethod) 195 { 196 WebURLRequest request; 197 request.initialize(); 198 request.setURL(toKURL("http://www.test.com/success.html")); 199 request.setHTTPMethod(WebString::fromUTF8(unsafeMethod)); 200 WebURLLoaderOptions options; 201 options.untrustedHTTP = true; 202 CheckFails(request, options); 203 } 204 205 void CheckHeaderFails(const char* headerField) 206 { 207 CheckHeaderFails(headerField, "foo"); 208 } 209 210 void CheckHeaderFails(const char* headerField, const char* headerValue) 211 { 212 WebURLRequest request; 213 request.initialize(); 214 request.setURL(toKURL("http://www.test.com/success.html")); 215 request.setHTTPHeaderField(WebString::fromUTF8(headerField), WebString::fromUTF8(headerValue)); 216 WebURLLoaderOptions options; 217 options.untrustedHTTP = true; 218 CheckFails(request, options); 219 } 220 221 void CheckFails(const WebURLRequest& request, WebURLLoaderOptions options = WebURLLoaderOptions()) 222 { 223 m_expectedLoader = createAssociatedURLLoader(options); 224 EXPECT_TRUE(m_expectedLoader); 225 m_didFail = false; 226 m_expectedLoader->loadAsynchronously(request, this); 227 // Failure should not be reported synchronously. 228 EXPECT_FALSE(m_didFail); 229 // Allow the loader to return the error. 230 m_runningMessageLoop = true; 231 Platform::current()->currentThread()->enterRunLoop(); 232 EXPECT_TRUE(m_didFail); 233 EXPECT_FALSE(m_didReceiveResponse); 234 } 235 236 bool CheckAccessControlHeaders(const char* headerName, bool exposed) 237 { 238 std::string id("http://www.other.com/CheckAccessControlExposeHeaders_"); 239 id.append(headerName); 240 if (exposed) 241 id.append("-Exposed"); 242 id.append(".html"); 243 244 WebCore::KURL url = toKURL(id); 245 WebURLRequest request; 246 request.initialize(); 247 request.setURL(url); 248 249 WebString headerNameString(WebString::fromUTF8(headerName)); 250 m_expectedResponse = WebURLResponse(); 251 m_expectedResponse.initialize(); 252 m_expectedResponse.setMIMEType("text/html"); 253 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*"); 254 if (exposed) 255 m_expectedResponse.addHTTPHeaderField("access-control-expose-headers", headerNameString); 256 m_expectedResponse.addHTTPHeaderField(headerNameString, "foo"); 257 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath); 258 259 WebURLLoaderOptions options; 260 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 261 m_expectedLoader = createAssociatedURLLoader(options); 262 EXPECT_TRUE(m_expectedLoader); 263 m_expectedLoader->loadAsynchronously(request, this); 264 serveRequests(); 265 EXPECT_TRUE(m_didReceiveResponse); 266 EXPECT_TRUE(m_didReceiveData); 267 EXPECT_TRUE(m_didFinishLoading); 268 269 return !m_actualResponse.httpHeaderField(headerNameString).isEmpty(); 270 } 271 272 protected: 273 WTF::String m_baseFilePath; 274 WTF::String m_frameFilePath; 275 TestWebFrameClient m_webFrameClient; 276 WebView* m_webView; 277 278 WebURLLoader* m_expectedLoader; 279 WebURLResponse m_actualResponse; 280 WebURLResponse m_expectedResponse; 281 WebURLRequest m_expectedNewRequest; 282 WebURLResponse m_expectedRedirectResponse; 283 bool m_willSendRequest; 284 bool m_didSendData; 285 bool m_didReceiveResponse; 286 bool m_didDownloadData; 287 bool m_didReceiveData; 288 bool m_didReceiveCachedMetadata; 289 bool m_didFinishLoading; 290 bool m_didFail; 291 bool m_runningMessageLoop; 292 }; 293 294 // Test a successful same-origin URL load. 295 TEST_F(AssociatedURLLoaderTest, SameOriginSuccess) 296 { 297 WebCore::KURL url = toKURL("http://www.test.com/SameOriginSuccess.html"); 298 WebURLRequest request; 299 request.initialize(); 300 request.setURL(url); 301 302 m_expectedResponse = WebURLResponse(); 303 m_expectedResponse.initialize(); 304 m_expectedResponse.setMIMEType("text/html"); 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 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath); 340 341 WebURLLoaderOptions options; 342 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow; 343 m_expectedLoader = createAssociatedURLLoader(options); 344 EXPECT_TRUE(m_expectedLoader); 345 m_expectedLoader->loadAsynchronously(request, this); 346 serveRequests(); 347 EXPECT_TRUE(m_didReceiveResponse); 348 EXPECT_TRUE(m_didReceiveData); 349 EXPECT_TRUE(m_didFinishLoading); 350 } 351 352 // Test a successful cross-origin load using CORS. 353 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess) 354 { 355 // This is cross-origin since the frame was loaded from www.test.com. 356 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html"); 357 WebURLRequest request; 358 request.initialize(); 359 request.setURL(url); 360 361 m_expectedResponse = WebURLResponse(); 362 m_expectedResponse.initialize(); 363 m_expectedResponse.setMIMEType("text/html"); 364 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); 365 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath); 366 367 WebURLLoaderOptions options; 368 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 369 m_expectedLoader = createAssociatedURLLoader(options); 370 EXPECT_TRUE(m_expectedLoader); 371 m_expectedLoader->loadAsynchronously(request, this); 372 serveRequests(); 373 EXPECT_TRUE(m_didReceiveResponse); 374 EXPECT_TRUE(m_didReceiveData); 375 EXPECT_TRUE(m_didFinishLoading); 376 } 377 378 // Test an unsuccessful cross-origin load using CORS. 379 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailure) 380 { 381 // This is cross-origin since the frame was loaded from www.test.com. 382 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html"); 383 WebURLRequest request; 384 request.initialize(); 385 request.setURL(url); 386 387 m_expectedResponse = WebURLResponse(); 388 m_expectedResponse.initialize(); 389 m_expectedResponse.setMIMEType("text/html"); 390 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); 391 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath); 392 393 WebURLLoaderOptions options; 394 // Send credentials. This will cause the CORS checks to fail, because credentials can't be 395 // sent to a server which returns the header "access-control-allow-origin" with "*" as its value. 396 options.allowCredentials = true; 397 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 398 m_expectedLoader = createAssociatedURLLoader(options); 399 EXPECT_TRUE(m_expectedLoader); 400 m_expectedLoader->loadAsynchronously(request, this); 401 402 // Failure should not be reported synchronously. 403 EXPECT_FALSE(m_didFail); 404 // The loader needs to receive the response, before doing the CORS check. 405 serveRequests(); 406 EXPECT_TRUE(m_didFail); 407 EXPECT_FALSE(m_didReceiveResponse); 408 } 409 410 // Test a same-origin URL redirect and load. 411 TEST_F(AssociatedURLLoaderTest, RedirectSuccess) 412 { 413 WebCore::KURL url = toKURL("http://www.test.com/RedirectSuccess.html"); 414 char redirect[] = "http://www.test.com/RedirectSuccess2.html"; // Same-origin 415 WebCore::KURL redirectURL = toKURL(redirect); 416 417 WebURLRequest request; 418 request.initialize(); 419 request.setURL(url); 420 421 m_expectedRedirectResponse = WebURLResponse(); 422 m_expectedRedirectResponse.initialize(); 423 m_expectedRedirectResponse.setMIMEType("text/html"); 424 m_expectedRedirectResponse.setHTTPStatusCode(301); 425 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); 426 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath); 427 428 m_expectedNewRequest = WebURLRequest(); 429 m_expectedNewRequest.initialize(); 430 m_expectedNewRequest.setURL(redirectURL); 431 432 m_expectedResponse = WebURLResponse(); 433 m_expectedResponse.initialize(); 434 m_expectedResponse.setMIMEType("text/html"); 435 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath); 436 437 m_expectedLoader = createAssociatedURLLoader(); 438 EXPECT_TRUE(m_expectedLoader); 439 m_expectedLoader->loadAsynchronously(request, this); 440 serveRequests(); 441 EXPECT_TRUE(m_willSendRequest); 442 EXPECT_TRUE(m_didReceiveResponse); 443 EXPECT_TRUE(m_didReceiveData); 444 EXPECT_TRUE(m_didFinishLoading); 445 } 446 447 // Test that a cross origin redirect response without CORS headers fails. 448 // Disabled, http://crbug.com/240912 . 449 TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlFailure) 450 { 451 WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html"); 452 char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html"; // Cross-origin 453 WebCore::KURL redirectURL = toKURL(redirect); 454 455 WebURLRequest request; 456 request.initialize(); 457 request.setURL(url); 458 459 // Create a redirect response without CORS headers. 460 m_expectedRedirectResponse = WebURLResponse(); 461 m_expectedRedirectResponse.initialize(); 462 m_expectedRedirectResponse.setMIMEType("text/html"); 463 m_expectedRedirectResponse.setHTTPStatusCode(301); 464 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); 465 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath); 466 467 WebURLLoaderOptions options; 468 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 469 m_expectedLoader = createAssociatedURLLoader(options); 470 EXPECT_TRUE(m_expectedLoader); 471 m_expectedLoader->loadAsynchronously(request, this); 472 serveRequests(); 473 // We should not receive a notification for the redirect or any response. 474 EXPECT_FALSE(m_willSendRequest); 475 EXPECT_FALSE(m_didReceiveResponse); 476 EXPECT_FALSE(m_didReceiveData); 477 EXPECT_FALSE(m_didFail); 478 } 479 480 // Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds. 481 TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess) 482 { 483 WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html"); 484 char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html"; // Cross-origin 485 WebCore::KURL redirectURL = toKURL(redirect); 486 487 WebURLRequest request; 488 request.initialize(); 489 request.setURL(url); 490 491 // Create a redirect response that allows the redirect to pass the access control checks. 492 m_expectedRedirectResponse = WebURLResponse(); 493 m_expectedRedirectResponse.initialize(); 494 m_expectedRedirectResponse.setMIMEType("text/html"); 495 m_expectedRedirectResponse.setHTTPStatusCode(301); 496 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); 497 m_expectedRedirectResponse.addHTTPHeaderField("access-control-allow-origin", "*"); 498 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath); 499 500 m_expectedNewRequest = WebURLRequest(); 501 m_expectedNewRequest.initialize(); 502 m_expectedNewRequest.setURL(redirectURL); 503 504 m_expectedResponse = WebURLResponse(); 505 m_expectedResponse.initialize(); 506 m_expectedResponse.setMIMEType("text/html"); 507 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); 508 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath); 509 510 WebURLLoaderOptions options; 511 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 512 m_expectedLoader = createAssociatedURLLoader(options); 513 EXPECT_TRUE(m_expectedLoader); 514 m_expectedLoader->loadAsynchronously(request, this); 515 serveRequests(); 516 // We should not receive a notification for the redirect. 517 EXPECT_FALSE(m_willSendRequest); 518 EXPECT_TRUE(m_didReceiveResponse); 519 EXPECT_TRUE(m_didReceiveData); 520 EXPECT_TRUE(m_didFinishLoading); 521 } 522 523 // Test that untrusted loads can't use a forbidden method. 524 TEST_F(AssociatedURLLoaderTest, UntrustedCheckMethods) 525 { 526 // Check non-token method fails. 527 CheckMethodFails("GET()"); 528 CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234"); 529 530 // Forbidden methods should fail regardless of casing. 531 CheckMethodFails("CoNneCt"); 532 CheckMethodFails("TrAcK"); 533 CheckMethodFails("TrAcE"); 534 } 535 536 // Test that untrusted loads can't use a forbidden header field. 537 TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders) 538 { 539 // Check non-token header fails. 540 CheckHeaderFails("foo()"); 541 542 // Check forbidden headers fail. 543 CheckHeaderFails("accept-charset"); 544 CheckHeaderFails("accept-encoding"); 545 CheckHeaderFails("connection"); 546 CheckHeaderFails("content-length"); 547 CheckHeaderFails("cookie"); 548 CheckHeaderFails("cookie2"); 549 CheckHeaderFails("content-transfer-encoding"); 550 CheckHeaderFails("date"); 551 CheckHeaderFails("expect"); 552 CheckHeaderFails("host"); 553 CheckHeaderFails("keep-alive"); 554 CheckHeaderFails("origin"); 555 CheckHeaderFails("referer"); 556 CheckHeaderFails("te"); 557 CheckHeaderFails("trailer"); 558 CheckHeaderFails("transfer-encoding"); 559 CheckHeaderFails("upgrade"); 560 CheckHeaderFails("user-agent"); 561 CheckHeaderFails("via"); 562 563 CheckHeaderFails("proxy-"); 564 CheckHeaderFails("proxy-foo"); 565 CheckHeaderFails("sec-"); 566 CheckHeaderFails("sec-foo"); 567 568 // Check that validation is case-insensitive. 569 CheckHeaderFails("AcCePt-ChArSeT"); 570 CheckHeaderFails("ProXy-FoO"); 571 572 // Check invalid header values. 573 CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234"); 574 } 575 576 // Test that the loader filters response headers according to the CORS standard. 577 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting) 578 { 579 // Test that whitelisted headers are returned without exposing them. 580 EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false)); 581 EXPECT_TRUE(CheckAccessControlHeaders("content-language", false)); 582 EXPECT_TRUE(CheckAccessControlHeaders("content-type", false)); 583 EXPECT_TRUE(CheckAccessControlHeaders("expires", false)); 584 EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false)); 585 EXPECT_TRUE(CheckAccessControlHeaders("pragma", false)); 586 587 // Test that non-whitelisted headers aren't returned. 588 EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false)); 589 590 // Test that Set-Cookie headers aren't returned. 591 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false)); 592 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false)); 593 594 // Test that exposed headers that aren't whitelisted are returned. 595 EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true)); 596 597 // Test that Set-Cookie headers aren't returned, even if exposed. 598 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true)); 599 } 600 601 // Test that the loader can allow non-whitelisted response headers for trusted CORS loads. 602 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders) 603 { 604 WebURLRequest request; 605 request.initialize(); 606 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html"); 607 request.setURL(url); 608 609 WebString headerNameString(WebString::fromUTF8("non-whitelisted")); 610 m_expectedResponse = WebURLResponse(); 611 m_expectedResponse.initialize(); 612 m_expectedResponse.setMIMEType("text/html"); 613 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*"); 614 m_expectedResponse.addHTTPHeaderField(headerNameString, "foo"); 615 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath); 616 617 WebURLLoaderOptions options; 618 options.exposeAllResponseHeaders = true; // This turns off response whitelisting. 619 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 620 m_expectedLoader = createAssociatedURLLoader(options); 621 EXPECT_TRUE(m_expectedLoader); 622 m_expectedLoader->loadAsynchronously(request, this); 623 serveRequests(); 624 EXPECT_TRUE(m_didReceiveResponse); 625 EXPECT_TRUE(m_didReceiveData); 626 EXPECT_TRUE(m_didFinishLoading); 627 628 EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty()); 629 } 630 631 } 632