2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
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"
50 #include <gtest/gtest.h>
52 using namespace blink;
53 using blink::URLTestHelpers::toKURL;
57 class AssociatedURLLoaderTest : public testing::Test,
58 public WebURLLoaderClient {
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)
68 , m_runningMessageLoop(false)
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");
77 WebCore::KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename)
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);
91 m_helper.initialize();
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",
100 for (size_t i = 0; i < arraysize(iframeSupportFiles); ++i) {
101 RegisterMockedUrl(urlRoot, iframeSupportFiles[i]);
104 WebURLRequest request;
105 request.initialize();
107 mainFrame()->loadRequest(request);
110 Platform::current()->unitTestSupport()->unregisterMockedURL(url);
115 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
120 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
123 PassOwnPtr<WebURLLoader> createAssociatedURLLoader(const WebURLLoaderOptions options = WebURLLoaderOptions())
125 return adoptPtr(mainFrame()->createAssociatedURLLoader(options));
128 // WebURLLoaderClient implementation.
129 void willSendRequest(WebURLLoader* loader, WebURLRequest& newRequest, const WebURLResponse& redirectResponse)
131 m_willSendRequest = true;
132 EXPECT_EQ(m_expectedLoader, loader);
133 EXPECT_EQ(m_expectedNewRequest.url(), newRequest.url());
134 // Check that CORS simple headers are transferred to the new request.
135 EXPECT_EQ(m_expectedNewRequest.httpHeaderField("accept"), newRequest.httpHeaderField("accept"));
136 EXPECT_EQ(m_expectedRedirectResponse.url(), redirectResponse.url());
137 EXPECT_EQ(m_expectedRedirectResponse.httpStatusCode(), redirectResponse.httpStatusCode());
138 EXPECT_EQ(m_expectedRedirectResponse.mimeType(), redirectResponse.mimeType());
141 void didSendData(WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
143 m_didSendData = true;
144 EXPECT_EQ(m_expectedLoader, loader);
147 void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response)
149 m_didReceiveResponse = true;
150 m_actualResponse = WebURLResponse(response);
151 EXPECT_EQ(m_expectedLoader, loader);
152 EXPECT_EQ(m_expectedResponse.url(), response.url());
153 EXPECT_EQ(m_expectedResponse.httpStatusCode(), response.httpStatusCode());
156 void didDownloadData(WebURLLoader* loader, int dataLength, int encodedDataLength)
158 m_didDownloadData = true;
159 EXPECT_EQ(m_expectedLoader, loader);
162 void didReceiveData(WebURLLoader* loader, const char* data, int dataLength, int encodedDataLength)
164 m_didReceiveData = true;
165 EXPECT_EQ(m_expectedLoader, loader);
167 EXPECT_GT(dataLength, 0);
170 void didReceiveCachedMetadata(WebURLLoader* loader, const char* data, int dataLength)
172 m_didReceiveCachedMetadata = true;
173 EXPECT_EQ(m_expectedLoader, loader);
176 void didFinishLoading(WebURLLoader* loader, double finishTime, int64_t encodedDataLength)
178 m_didFinishLoading = true;
179 EXPECT_EQ(m_expectedLoader, loader);
182 void didFail(WebURLLoader* loader, const WebURLError& error)
185 EXPECT_EQ(m_expectedLoader, loader);
186 if (m_runningMessageLoop) {
187 m_runningMessageLoop = false;
188 Platform::current()->currentThread()->exitRunLoop();
192 void CheckMethodFails(const char* unsafeMethod)
194 WebURLRequest request;
195 request.initialize();
196 request.setURL(toKURL("http://www.test.com/success.html"));
197 request.setHTTPMethod(WebString::fromUTF8(unsafeMethod));
198 WebURLLoaderOptions options;
199 options.untrustedHTTP = true;
200 CheckFails(request, options);
203 void CheckHeaderFails(const char* headerField)
205 CheckHeaderFails(headerField, "foo");
208 void CheckHeaderFails(const char* headerField, const char* headerValue)
210 WebURLRequest request;
211 request.initialize();
212 request.setURL(toKURL("http://www.test.com/success.html"));
213 if (equalIgnoringCase(WebString::fromUTF8(headerField), "referer"))
214 request.setHTTPReferrer(WebString::fromUTF8(headerValue), blink::WebReferrerPolicyDefault);
216 request.setHTTPHeaderField(WebString::fromUTF8(headerField), WebString::fromUTF8(headerValue));
217 WebURLLoaderOptions options;
218 options.untrustedHTTP = true;
219 CheckFails(request, options);
222 void CheckFails(const WebURLRequest& request, WebURLLoaderOptions options = WebURLLoaderOptions())
224 m_expectedLoader = createAssociatedURLLoader(options);
225 EXPECT_TRUE(m_expectedLoader);
227 m_expectedLoader->loadAsynchronously(request, this);
228 // Failure should not be reported synchronously.
229 EXPECT_FALSE(m_didFail);
230 // Allow the loader to return the error.
231 m_runningMessageLoop = true;
232 Platform::current()->currentThread()->enterRunLoop();
233 EXPECT_TRUE(m_didFail);
234 EXPECT_FALSE(m_didReceiveResponse);
237 bool CheckAccessControlHeaders(const char* headerName, bool exposed)
239 std::string id("http://www.other.com/CheckAccessControlExposeHeaders_");
240 id.append(headerName);
242 id.append("-Exposed");
245 WebCore::KURL url = toKURL(id);
246 WebURLRequest request;
247 request.initialize();
250 WebString headerNameString(WebString::fromUTF8(headerName));
251 m_expectedResponse = WebURLResponse();
252 m_expectedResponse.initialize();
253 m_expectedResponse.setMIMEType("text/html");
254 m_expectedResponse.setHTTPStatusCode(200);
255 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
257 m_expectedResponse.addHTTPHeaderField("access-control-expose-headers", headerNameString);
258 m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
259 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
261 WebURLLoaderOptions options;
262 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
263 m_expectedLoader = createAssociatedURLLoader(options);
264 EXPECT_TRUE(m_expectedLoader);
265 m_expectedLoader->loadAsynchronously(request, this);
267 EXPECT_TRUE(m_didReceiveResponse);
268 EXPECT_TRUE(m_didReceiveData);
269 EXPECT_TRUE(m_didFinishLoading);
271 return !m_actualResponse.httpHeaderField(headerNameString).isEmpty();
274 WebFrame* mainFrame() const { return m_helper.webView()->mainFrame(); }
277 WTF::String m_baseFilePath;
278 WTF::String m_frameFilePath;
279 FrameTestHelpers::WebViewHelper m_helper;
281 OwnPtr<WebURLLoader> m_expectedLoader;
282 WebURLResponse m_actualResponse;
283 WebURLResponse m_expectedResponse;
284 WebURLRequest m_expectedNewRequest;
285 WebURLResponse m_expectedRedirectResponse;
286 bool m_willSendRequest;
288 bool m_didReceiveResponse;
289 bool m_didDownloadData;
290 bool m_didReceiveData;
291 bool m_didReceiveCachedMetadata;
292 bool m_didFinishLoading;
294 bool m_runningMessageLoop;
297 // Test a successful same-origin URL load.
298 TEST_F(AssociatedURLLoaderTest, SameOriginSuccess)
300 WebCore::KURL url = toKURL("http://www.test.com/SameOriginSuccess.html");
301 WebURLRequest request;
302 request.initialize();
305 m_expectedResponse = WebURLResponse();
306 m_expectedResponse.initialize();
307 m_expectedResponse.setMIMEType("text/html");
308 m_expectedResponse.setHTTPStatusCode(200);
309 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
311 m_expectedLoader = createAssociatedURLLoader();
312 EXPECT_TRUE(m_expectedLoader);
313 m_expectedLoader->loadAsynchronously(request, this);
315 EXPECT_TRUE(m_didReceiveResponse);
316 EXPECT_TRUE(m_didReceiveData);
317 EXPECT_TRUE(m_didFinishLoading);
320 // Test that the same-origin restriction is the default.
321 TEST_F(AssociatedURLLoaderTest, SameOriginRestriction)
323 // This is cross-origin since the frame was loaded from www.test.com.
324 WebCore::KURL url = toKURL("http://www.other.com/SameOriginRestriction.html");
325 WebURLRequest request;
326 request.initialize();
331 // Test a successful cross-origin load.
332 TEST_F(AssociatedURLLoaderTest, CrossOriginSuccess)
334 // This is cross-origin since the frame was loaded from www.test.com.
335 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginSuccess.html");
336 WebURLRequest request;
337 request.initialize();
340 m_expectedResponse = WebURLResponse();
341 m_expectedResponse.initialize();
342 m_expectedResponse.setMIMEType("text/html");
343 m_expectedResponse.setHTTPStatusCode(200);
344 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
346 WebURLLoaderOptions options;
347 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
348 m_expectedLoader = createAssociatedURLLoader(options);
349 EXPECT_TRUE(m_expectedLoader);
350 m_expectedLoader->loadAsynchronously(request, this);
352 EXPECT_TRUE(m_didReceiveResponse);
353 EXPECT_TRUE(m_didReceiveData);
354 EXPECT_TRUE(m_didFinishLoading);
357 // Test a successful cross-origin load using CORS.
358 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess)
360 // This is cross-origin since the frame was loaded from www.test.com.
361 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html");
362 WebURLRequest request;
363 request.initialize();
366 m_expectedResponse = WebURLResponse();
367 m_expectedResponse.initialize();
368 m_expectedResponse.setMIMEType("text/html");
369 m_expectedResponse.setHTTPStatusCode(200);
370 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
371 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
373 WebURLLoaderOptions options;
374 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
375 m_expectedLoader = createAssociatedURLLoader(options);
376 EXPECT_TRUE(m_expectedLoader);
377 m_expectedLoader->loadAsynchronously(request, this);
379 EXPECT_TRUE(m_didReceiveResponse);
380 EXPECT_TRUE(m_didReceiveData);
381 EXPECT_TRUE(m_didFinishLoading);
384 // Test an unsuccessful cross-origin load using CORS.
385 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailure)
387 // This is cross-origin since the frame was loaded from www.test.com.
388 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
389 WebURLRequest request;
390 request.initialize();
393 m_expectedResponse = WebURLResponse();
394 m_expectedResponse.initialize();
395 m_expectedResponse.setMIMEType("text/html");
396 m_expectedResponse.setHTTPStatusCode(200);
397 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
398 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
400 WebURLLoaderOptions options;
401 // Send credentials. This will cause the CORS checks to fail, because credentials can't be
402 // sent to a server which returns the header "access-control-allow-origin" with "*" as its value.
403 options.allowCredentials = true;
404 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
405 m_expectedLoader = createAssociatedURLLoader(options);
406 EXPECT_TRUE(m_expectedLoader);
407 m_expectedLoader->loadAsynchronously(request, this);
409 // Failure should not be reported synchronously.
410 EXPECT_FALSE(m_didFail);
411 // The loader needs to receive the response, before doing the CORS check.
413 EXPECT_TRUE(m_didFail);
414 EXPECT_FALSE(m_didReceiveResponse);
417 // Test an unsuccessful cross-origin load using CORS.
418 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailureBadStatusCode)
420 // This is cross-origin since the frame was loaded from www.test.com.
421 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
422 WebURLRequest request;
423 request.initialize();
426 m_expectedResponse = WebURLResponse();
427 m_expectedResponse.initialize();
428 m_expectedResponse.setMIMEType("text/html");
429 m_expectedResponse.setHTTPStatusCode(0);
430 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
431 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
433 WebURLLoaderOptions options;
434 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
435 m_expectedLoader = createAssociatedURLLoader(options);
436 EXPECT_TRUE(m_expectedLoader);
437 m_expectedLoader->loadAsynchronously(request, this);
439 // Failure should not be reported synchronously.
440 EXPECT_FALSE(m_didFail);
441 // The loader needs to receive the response, before doing the CORS check.
443 EXPECT_TRUE(m_didFail);
444 EXPECT_FALSE(m_didReceiveResponse);
447 // Test a same-origin URL redirect and load.
448 TEST_F(AssociatedURLLoaderTest, RedirectSuccess)
450 WebCore::KURL url = toKURL("http://www.test.com/RedirectSuccess.html");
451 char redirect[] = "http://www.test.com/RedirectSuccess2.html"; // Same-origin
452 WebCore::KURL redirectURL = toKURL(redirect);
454 WebURLRequest request;
455 request.initialize();
458 m_expectedRedirectResponse = WebURLResponse();
459 m_expectedRedirectResponse.initialize();
460 m_expectedRedirectResponse.setMIMEType("text/html");
461 m_expectedRedirectResponse.setHTTPStatusCode(301);
462 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
463 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
465 m_expectedNewRequest = WebURLRequest();
466 m_expectedNewRequest.initialize();
467 m_expectedNewRequest.setURL(redirectURL);
469 m_expectedResponse = WebURLResponse();
470 m_expectedResponse.initialize();
471 m_expectedResponse.setMIMEType("text/html");
472 m_expectedResponse.setHTTPStatusCode(200);
473 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);
475 m_expectedLoader = createAssociatedURLLoader();
476 EXPECT_TRUE(m_expectedLoader);
477 m_expectedLoader->loadAsynchronously(request, this);
479 EXPECT_TRUE(m_willSendRequest);
480 EXPECT_TRUE(m_didReceiveResponse);
481 EXPECT_TRUE(m_didReceiveData);
482 EXPECT_TRUE(m_didFinishLoading);
485 // Test that a cross origin redirect response without CORS headers fails.
486 // Disabled, http://crbug.com/240912 .
487 TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlFailure)
489 WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html");
490 char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html"; // Cross-origin
491 WebCore::KURL redirectURL = toKURL(redirect);
493 WebURLRequest request;
494 request.initialize();
497 // Create a redirect response without CORS headers.
498 m_expectedRedirectResponse = WebURLResponse();
499 m_expectedRedirectResponse.initialize();
500 m_expectedRedirectResponse.setMIMEType("text/html");
501 m_expectedRedirectResponse.setHTTPStatusCode(301);
502 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
503 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
505 WebURLLoaderOptions options;
506 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
507 m_expectedLoader = createAssociatedURLLoader(options);
508 EXPECT_TRUE(m_expectedLoader);
509 m_expectedLoader->loadAsynchronously(request, this);
511 // We should not receive a notification for the redirect or any response.
512 EXPECT_FALSE(m_willSendRequest);
513 EXPECT_FALSE(m_didReceiveResponse);
514 EXPECT_FALSE(m_didReceiveData);
515 EXPECT_FALSE(m_didFail);
518 // Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
519 TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess)
521 WebCore::KURL url = toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html");
522 char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html"; // Cross-origin
523 WebCore::KURL redirectURL = toKURL(redirect);
525 WebURLRequest request;
526 request.initialize();
528 // Add a CORS simple header.
529 request.setHTTPHeaderField("accept", "application/json");
531 // Create a redirect response that allows the redirect to pass the access control checks.
532 m_expectedRedirectResponse = WebURLResponse();
533 m_expectedRedirectResponse.initialize();
534 m_expectedRedirectResponse.setMIMEType("text/html");
535 m_expectedRedirectResponse.setHTTPStatusCode(301);
536 m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
537 m_expectedRedirectResponse.addHTTPHeaderField("access-control-allow-origin", "*");
538 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
540 m_expectedNewRequest = WebURLRequest();
541 m_expectedNewRequest.initialize();
542 m_expectedNewRequest.setURL(redirectURL);
543 m_expectedNewRequest.setHTTPHeaderField("accept", "application/json");
545 m_expectedResponse = WebURLResponse();
546 m_expectedResponse.initialize();
547 m_expectedResponse.setMIMEType("text/html");
548 m_expectedResponse.setHTTPStatusCode(200);
549 m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*");
550 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL, m_expectedResponse, m_frameFilePath);
552 WebURLLoaderOptions options;
553 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
554 m_expectedLoader = createAssociatedURLLoader(options);
555 EXPECT_TRUE(m_expectedLoader);
556 m_expectedLoader->loadAsynchronously(request, this);
558 // We should not receive a notification for the redirect.
559 EXPECT_FALSE(m_willSendRequest);
560 EXPECT_TRUE(m_didReceiveResponse);
561 EXPECT_TRUE(m_didReceiveData);
562 EXPECT_TRUE(m_didFinishLoading);
565 // Test that untrusted loads can't use a forbidden method.
566 TEST_F(AssociatedURLLoaderTest, UntrustedCheckMethods)
568 // Check non-token method fails.
569 CheckMethodFails("GET()");
570 CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234");
572 // Forbidden methods should fail regardless of casing.
573 CheckMethodFails("CoNneCt");
574 CheckMethodFails("TrAcK");
575 CheckMethodFails("TrAcE");
578 // Test that untrusted loads can't use a forbidden header field.
579 TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders)
581 // Check non-token header fails.
582 CheckHeaderFails("foo()");
584 // Check forbidden headers fail.
585 CheckHeaderFails("accept-charset");
586 CheckHeaderFails("accept-encoding");
587 CheckHeaderFails("connection");
588 CheckHeaderFails("content-length");
589 CheckHeaderFails("cookie");
590 CheckHeaderFails("cookie2");
591 CheckHeaderFails("content-transfer-encoding");
592 CheckHeaderFails("date");
593 CheckHeaderFails("expect");
594 CheckHeaderFails("host");
595 CheckHeaderFails("keep-alive");
596 CheckHeaderFails("origin");
597 CheckHeaderFails("referer");
598 CheckHeaderFails("te");
599 CheckHeaderFails("trailer");
600 CheckHeaderFails("transfer-encoding");
601 CheckHeaderFails("upgrade");
602 CheckHeaderFails("user-agent");
603 CheckHeaderFails("via");
605 CheckHeaderFails("proxy-");
606 CheckHeaderFails("proxy-foo");
607 CheckHeaderFails("sec-");
608 CheckHeaderFails("sec-foo");
610 // Check that validation is case-insensitive.
611 CheckHeaderFails("AcCePt-ChArSeT");
612 CheckHeaderFails("ProXy-FoO");
614 // Check invalid header values.
615 CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
618 // Test that the loader filters response headers according to the CORS standard.
619 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting)
621 // Test that whitelisted headers are returned without exposing them.
622 EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false));
623 EXPECT_TRUE(CheckAccessControlHeaders("content-language", false));
624 EXPECT_TRUE(CheckAccessControlHeaders("content-type", false));
625 EXPECT_TRUE(CheckAccessControlHeaders("expires", false));
626 EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false));
627 EXPECT_TRUE(CheckAccessControlHeaders("pragma", false));
629 // Test that non-whitelisted headers aren't returned.
630 EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));
632 // Test that Set-Cookie headers aren't returned.
633 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
634 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));
636 // Test that exposed headers that aren't whitelisted are returned.
637 EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));
639 // Test that Set-Cookie headers aren't returned, even if exposed.
640 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
643 // Test that the loader can allow non-whitelisted response headers for trusted CORS loads.
644 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders)
646 WebURLRequest request;
647 request.initialize();
648 WebCore::KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
651 WebString headerNameString(WebString::fromUTF8("non-whitelisted"));
652 m_expectedResponse = WebURLResponse();
653 m_expectedResponse.initialize();
654 m_expectedResponse.setMIMEType("text/html");
655 m_expectedResponse.setHTTPStatusCode(200);
656 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
657 m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
658 Platform::current()->unitTestSupport()->registerMockedURL(url, m_expectedResponse, m_frameFilePath);
660 WebURLLoaderOptions options;
661 options.exposeAllResponseHeaders = true; // This turns off response whitelisting.
662 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
663 m_expectedLoader = createAssociatedURLLoader(options);
664 EXPECT_TRUE(m_expectedLoader);
665 m_expectedLoader->loadAsynchronously(request, this);
667 EXPECT_TRUE(m_didReceiveResponse);
668 EXPECT_TRUE(m_didReceiveData);
669 EXPECT_TRUE(m_didFinishLoading);
671 EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty());