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 "platform/testing/URLTestHelpers.h"
34 #include "platform/testing/UnitTestHelpers.h"
35 #include "public/platform/Platform.h"
36 #include "public/platform/WebString.h"
37 #include "public/platform/WebThread.h"
38 #include "public/platform/WebURL.h"
39 #include "public/platform/WebURLLoader.h"
40 #include "public/platform/WebURLLoaderClient.h"
41 #include "public/platform/WebURLRequest.h"
42 #include "public/platform/WebURLResponse.h"
43 #include "public/platform/WebUnitTestSupport.h"
44 #include "public/web/WebFrame.h"
45 #include "public/web/WebURLLoaderOptions.h"
46 #include "public/web/WebView.h"
47 #include "web/tests/FrameTestHelpers.h"
48 #include "wtf/text/CString.h"
49 #include "wtf/text/WTFString.h"
50 #include <gtest/gtest.h>
52 using blink::URLTestHelpers::toKURL
;
53 using blink::testing::runPendingTasks
;
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)
69 // Reuse one of the test files from WebFrameTest.
70 m_baseFilePath
= Platform::current()->unitTestSupport()->webKitRootDir();
71 m_baseFilePath
.append("/Source/web/tests/data/");
72 m_frameFilePath
= m_baseFilePath
;
73 m_frameFilePath
.append("iframes_test.html");
76 KURL
RegisterMockedUrl(const std::string
& urlRoot
, const WTF::String
& filename
)
78 WebURLResponse response
;
79 response
.initialize();
80 response
.setMIMEType("text/html");
81 WTF::String localPath
= m_baseFilePath
;
82 localPath
.append(filename
);
83 KURL url
= toKURL(urlRoot
+ filename
.utf8().data());
84 Platform::current()->unitTestSupport()->registerMockedURL(url
, response
, localPath
);
90 m_helper
.initialize();
92 std::string urlRoot
= "http://www.test.com/";
93 KURL url
= RegisterMockedUrl(urlRoot
, "iframes_test.html");
94 const char* iframeSupportFiles
[] = {
95 "invisible_iframe.html",
96 "visible_iframe.html",
97 "zero_sized_iframe.html",
99 for (size_t i
= 0; i
< arraysize(iframeSupportFiles
); ++i
) {
100 RegisterMockedUrl(urlRoot
, iframeSupportFiles
[i
]);
103 FrameTestHelpers::loadFrame(mainFrame(), url
.string().utf8().data());
105 Platform::current()->unitTestSupport()->unregisterMockedURL(url
);
108 void TearDown() override
110 Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
115 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
118 PassOwnPtr
<WebURLLoader
> createAssociatedURLLoader(const WebURLLoaderOptions options
= WebURLLoaderOptions())
120 return adoptPtr(mainFrame()->createAssociatedURLLoader(options
));
123 // WebURLLoaderClient implementation.
124 void willSendRequest(WebURLLoader
* loader
, WebURLRequest
& newRequest
, const WebURLResponse
& redirectResponse
) override
126 m_willSendRequest
= true;
127 EXPECT_EQ(m_expectedLoader
, loader
);
128 EXPECT_EQ(m_expectedNewRequest
.url(), newRequest
.url());
129 // Check that CORS simple headers are transferred to the new request.
130 EXPECT_EQ(m_expectedNewRequest
.httpHeaderField("accept"), newRequest
.httpHeaderField("accept"));
131 EXPECT_EQ(m_expectedRedirectResponse
.url(), redirectResponse
.url());
132 EXPECT_EQ(m_expectedRedirectResponse
.httpStatusCode(), redirectResponse
.httpStatusCode());
133 EXPECT_EQ(m_expectedRedirectResponse
.mimeType(), redirectResponse
.mimeType());
136 void didSendData(WebURLLoader
* loader
, unsigned long long bytesSent
, unsigned long long totalBytesToBeSent
) override
138 m_didSendData
= true;
139 EXPECT_EQ(m_expectedLoader
, loader
);
142 void didReceiveResponse(WebURLLoader
* loader
, const WebURLResponse
& response
) override
144 m_didReceiveResponse
= true;
145 m_actualResponse
= WebURLResponse(response
);
146 EXPECT_EQ(m_expectedLoader
, loader
);
147 EXPECT_EQ(m_expectedResponse
.url(), response
.url());
148 EXPECT_EQ(m_expectedResponse
.httpStatusCode(), response
.httpStatusCode());
151 void didDownloadData(WebURLLoader
* loader
, int dataLength
, int encodedDataLength
) override
153 m_didDownloadData
= true;
154 EXPECT_EQ(m_expectedLoader
, loader
);
157 void didReceiveData(WebURLLoader
* loader
, const char* data
, int dataLength
, int encodedDataLength
) override
159 m_didReceiveData
= true;
160 EXPECT_EQ(m_expectedLoader
, loader
);
162 EXPECT_GT(dataLength
, 0);
165 void didReceiveCachedMetadata(WebURLLoader
* loader
, const char* data
, int dataLength
) override
167 m_didReceiveCachedMetadata
= true;
168 EXPECT_EQ(m_expectedLoader
, loader
);
171 void didFinishLoading(WebURLLoader
* loader
, double finishTime
, int64_t encodedDataLength
) override
173 m_didFinishLoading
= true;
174 EXPECT_EQ(m_expectedLoader
, loader
);
177 void didFail(WebURLLoader
* loader
, const WebURLError
& error
) override
180 EXPECT_EQ(m_expectedLoader
, loader
);
183 void CheckMethodFails(const char* unsafeMethod
)
185 WebURLRequest request
;
186 request
.initialize();
187 request
.setURL(toKURL("http://www.test.com/success.html"));
188 request
.setHTTPMethod(WebString::fromUTF8(unsafeMethod
));
189 WebURLLoaderOptions options
;
190 options
.untrustedHTTP
= true;
191 CheckFails(request
, options
);
194 void CheckHeaderFails(const char* headerField
)
196 CheckHeaderFails(headerField
, "foo");
199 void CheckHeaderFails(const char* headerField
, const char* headerValue
)
201 WebURLRequest request
;
202 request
.initialize();
203 request
.setURL(toKURL("http://www.test.com/success.html"));
204 if (equalIgnoringCase(WebString::fromUTF8(headerField
), "referer"))
205 request
.setHTTPReferrer(WebString::fromUTF8(headerValue
), WebReferrerPolicyDefault
);
207 request
.setHTTPHeaderField(WebString::fromUTF8(headerField
), WebString::fromUTF8(headerValue
));
208 WebURLLoaderOptions options
;
209 options
.untrustedHTTP
= true;
210 CheckFails(request
, options
);
213 void CheckFails(const WebURLRequest
& request
, WebURLLoaderOptions options
= WebURLLoaderOptions())
215 m_expectedLoader
= createAssociatedURLLoader(options
);
216 EXPECT_TRUE(m_expectedLoader
);
218 m_expectedLoader
->loadAsynchronously(request
, this);
219 // Failure should not be reported synchronously.
220 EXPECT_FALSE(m_didFail
);
221 // Allow the loader to return the error.
223 EXPECT_TRUE(m_didFail
);
224 EXPECT_FALSE(m_didReceiveResponse
);
227 bool CheckAccessControlHeaders(const char* headerName
, bool exposed
)
229 std::string
id("http://www.other.com/CheckAccessControlExposeHeaders_");
230 id
.append(headerName
);
232 id
.append("-Exposed");
235 KURL url
= toKURL(id
);
236 WebURLRequest request
;
237 request
.initialize();
240 WebString
headerNameString(WebString::fromUTF8(headerName
));
241 m_expectedResponse
= WebURLResponse();
242 m_expectedResponse
.initialize();
243 m_expectedResponse
.setMIMEType("text/html");
244 m_expectedResponse
.setHTTPStatusCode(200);
245 m_expectedResponse
.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
247 m_expectedResponse
.addHTTPHeaderField("access-control-expose-headers", headerNameString
);
248 m_expectedResponse
.addHTTPHeaderField(headerNameString
, "foo");
249 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
251 WebURLLoaderOptions options
;
252 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
253 m_expectedLoader
= createAssociatedURLLoader(options
);
254 EXPECT_TRUE(m_expectedLoader
);
255 m_expectedLoader
->loadAsynchronously(request
, this);
257 EXPECT_TRUE(m_didReceiveResponse
);
258 EXPECT_TRUE(m_didReceiveData
);
259 EXPECT_TRUE(m_didFinishLoading
);
261 return !m_actualResponse
.httpHeaderField(headerNameString
).isEmpty();
264 WebFrame
* mainFrame() const { return m_helper
.webView()->mainFrame(); }
267 String m_baseFilePath
;
268 String m_frameFilePath
;
269 FrameTestHelpers::WebViewHelper m_helper
;
271 OwnPtr
<WebURLLoader
> m_expectedLoader
;
272 WebURLResponse m_actualResponse
;
273 WebURLResponse m_expectedResponse
;
274 WebURLRequest m_expectedNewRequest
;
275 WebURLResponse m_expectedRedirectResponse
;
276 bool m_willSendRequest
;
278 bool m_didReceiveResponse
;
279 bool m_didDownloadData
;
280 bool m_didReceiveData
;
281 bool m_didReceiveCachedMetadata
;
282 bool m_didFinishLoading
;
286 // Test a successful same-origin URL load.
287 TEST_F(AssociatedURLLoaderTest
, SameOriginSuccess
)
289 KURL url
= toKURL("http://www.test.com/SameOriginSuccess.html");
290 WebURLRequest request
;
291 request
.initialize();
294 m_expectedResponse
= WebURLResponse();
295 m_expectedResponse
.initialize();
296 m_expectedResponse
.setMIMEType("text/html");
297 m_expectedResponse
.setHTTPStatusCode(200);
298 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
300 m_expectedLoader
= createAssociatedURLLoader();
301 EXPECT_TRUE(m_expectedLoader
);
302 m_expectedLoader
->loadAsynchronously(request
, this);
304 EXPECT_TRUE(m_didReceiveResponse
);
305 EXPECT_TRUE(m_didReceiveData
);
306 EXPECT_TRUE(m_didFinishLoading
);
309 // Test that the same-origin restriction is the default.
310 TEST_F(AssociatedURLLoaderTest
, SameOriginRestriction
)
312 // This is cross-origin since the frame was loaded from www.test.com.
313 KURL url
= toKURL("http://www.other.com/SameOriginRestriction.html");
314 WebURLRequest request
;
315 request
.initialize();
320 // Test a successful cross-origin load.
321 TEST_F(AssociatedURLLoaderTest
, CrossOriginSuccess
)
323 // This is cross-origin since the frame was loaded from www.test.com.
324 KURL url
= toKURL("http://www.other.com/CrossOriginSuccess.html");
325 WebURLRequest request
;
326 request
.initialize();
329 m_expectedResponse
= WebURLResponse();
330 m_expectedResponse
.initialize();
331 m_expectedResponse
.setMIMEType("text/html");
332 m_expectedResponse
.setHTTPStatusCode(200);
333 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
335 WebURLLoaderOptions options
;
336 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyAllow
;
337 m_expectedLoader
= createAssociatedURLLoader(options
);
338 EXPECT_TRUE(m_expectedLoader
);
339 m_expectedLoader
->loadAsynchronously(request
, this);
341 EXPECT_TRUE(m_didReceiveResponse
);
342 EXPECT_TRUE(m_didReceiveData
);
343 EXPECT_TRUE(m_didFinishLoading
);
346 // Test a successful cross-origin load using CORS.
347 TEST_F(AssociatedURLLoaderTest
, CrossOriginWithAccessControlSuccess
)
349 // This is cross-origin since the frame was loaded from www.test.com.
350 KURL url
= toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html");
351 WebURLRequest request
;
352 request
.initialize();
355 m_expectedResponse
= WebURLResponse();
356 m_expectedResponse
.initialize();
357 m_expectedResponse
.setMIMEType("text/html");
358 m_expectedResponse
.setHTTPStatusCode(200);
359 m_expectedResponse
.addHTTPHeaderField("access-control-allow-origin", "*");
360 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
362 WebURLLoaderOptions options
;
363 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
364 m_expectedLoader
= createAssociatedURLLoader(options
);
365 EXPECT_TRUE(m_expectedLoader
);
366 m_expectedLoader
->loadAsynchronously(request
, this);
368 EXPECT_TRUE(m_didReceiveResponse
);
369 EXPECT_TRUE(m_didReceiveData
);
370 EXPECT_TRUE(m_didFinishLoading
);
373 // Test an unsuccessful cross-origin load using CORS.
374 TEST_F(AssociatedURLLoaderTest
, CrossOriginWithAccessControlFailure
)
376 // This is cross-origin since the frame was loaded from www.test.com.
377 KURL url
= toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
378 WebURLRequest request
;
379 request
.initialize();
382 m_expectedResponse
= WebURLResponse();
383 m_expectedResponse
.initialize();
384 m_expectedResponse
.setMIMEType("text/html");
385 m_expectedResponse
.setHTTPStatusCode(200);
386 m_expectedResponse
.addHTTPHeaderField("access-control-allow-origin", "*");
387 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
389 WebURLLoaderOptions options
;
390 // Send credentials. This will cause the CORS checks to fail, because credentials can't be
391 // sent to a server which returns the header "access-control-allow-origin" with "*" as its value.
392 options
.allowCredentials
= true;
393 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
394 m_expectedLoader
= createAssociatedURLLoader(options
);
395 EXPECT_TRUE(m_expectedLoader
);
396 m_expectedLoader
->loadAsynchronously(request
, this);
398 // Failure should not be reported synchronously.
399 EXPECT_FALSE(m_didFail
);
400 // The loader needs to receive the response, before doing the CORS check.
402 EXPECT_TRUE(m_didFail
);
403 EXPECT_FALSE(m_didReceiveResponse
);
406 // Test an unsuccessful cross-origin load using CORS.
407 TEST_F(AssociatedURLLoaderTest
, CrossOriginWithAccessControlFailureBadStatusCode
)
409 // This is cross-origin since the frame was loaded from www.test.com.
410 KURL url
= toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html");
411 WebURLRequest request
;
412 request
.initialize();
415 m_expectedResponse
= WebURLResponse();
416 m_expectedResponse
.initialize();
417 m_expectedResponse
.setMIMEType("text/html");
418 m_expectedResponse
.setHTTPStatusCode(0);
419 m_expectedResponse
.addHTTPHeaderField("access-control-allow-origin", "*");
420 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
422 WebURLLoaderOptions options
;
423 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
424 m_expectedLoader
= createAssociatedURLLoader(options
);
425 EXPECT_TRUE(m_expectedLoader
);
426 m_expectedLoader
->loadAsynchronously(request
, this);
428 // Failure should not be reported synchronously.
429 EXPECT_FALSE(m_didFail
);
430 // The loader needs to receive the response, before doing the CORS check.
432 EXPECT_TRUE(m_didFail
);
433 EXPECT_FALSE(m_didReceiveResponse
);
436 // Test a same-origin URL redirect and load.
437 TEST_F(AssociatedURLLoaderTest
, RedirectSuccess
)
439 KURL url
= toKURL("http://www.test.com/RedirectSuccess.html");
440 char redirect
[] = "http://www.test.com/RedirectSuccess2.html"; // Same-origin
441 KURL redirectURL
= toKURL(redirect
);
443 WebURLRequest request
;
444 request
.initialize();
447 m_expectedRedirectResponse
= WebURLResponse();
448 m_expectedRedirectResponse
.initialize();
449 m_expectedRedirectResponse
.setMIMEType("text/html");
450 m_expectedRedirectResponse
.setHTTPStatusCode(301);
451 m_expectedRedirectResponse
.setHTTPHeaderField("Location", redirect
);
452 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedRedirectResponse
, m_frameFilePath
);
454 m_expectedNewRequest
= WebURLRequest();
455 m_expectedNewRequest
.initialize();
456 m_expectedNewRequest
.setURL(redirectURL
);
458 m_expectedResponse
= WebURLResponse();
459 m_expectedResponse
.initialize();
460 m_expectedResponse
.setMIMEType("text/html");
461 m_expectedResponse
.setHTTPStatusCode(200);
462 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL
, m_expectedResponse
, m_frameFilePath
);
464 m_expectedLoader
= createAssociatedURLLoader();
465 EXPECT_TRUE(m_expectedLoader
);
466 m_expectedLoader
->loadAsynchronously(request
, this);
468 EXPECT_TRUE(m_willSendRequest
);
469 EXPECT_TRUE(m_didReceiveResponse
);
470 EXPECT_TRUE(m_didReceiveData
);
471 EXPECT_TRUE(m_didFinishLoading
);
474 // Test a cross-origin URL redirect without Access Control set.
475 TEST_F(AssociatedURLLoaderTest
, RedirectCrossOriginFailure
)
477 KURL url
= toKURL("http://www.test.com/RedirectCrossOriginFailure.html");
478 char redirect
[] = "http://www.other.com/RedirectCrossOriginFailure.html"; // Cross-origin
481 WebURLRequest request
;
482 request
.initialize();
485 m_expectedRedirectResponse
= WebURLResponse();
486 m_expectedRedirectResponse
.initialize();
487 m_expectedRedirectResponse
.setMIMEType("text/html");
488 m_expectedRedirectResponse
.setHTTPStatusCode(301);
489 m_expectedRedirectResponse
.setHTTPHeaderField("Location", redirect
);
490 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedRedirectResponse
, m_frameFilePath
);
492 m_expectedNewRequest
= WebURLRequest();
493 m_expectedNewRequest
.initialize();
494 m_expectedNewRequest
.setURL(redirectURL
);
496 m_expectedResponse
= WebURLResponse();
497 m_expectedResponse
.initialize();
498 m_expectedResponse
.setMIMEType("text/html");
499 m_expectedResponse
.setHTTPStatusCode(200);
500 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL
, m_expectedResponse
, m_frameFilePath
);
502 m_expectedLoader
= createAssociatedURLLoader();
503 EXPECT_TRUE(m_expectedLoader
);
504 m_expectedLoader
->loadAsynchronously(request
, this);
507 EXPECT_FALSE(m_willSendRequest
);
508 EXPECT_FALSE(m_didReceiveResponse
);
509 EXPECT_FALSE(m_didReceiveData
);
510 EXPECT_FALSE(m_didFinishLoading
);
513 // Test that a cross origin redirect response without CORS headers fails.
514 TEST_F(AssociatedURLLoaderTest
, RedirectCrossOriginWithAccessControlFailure
)
516 KURL url
= toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html");
517 char redirect
[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html"; // Cross-origin
518 KURL redirectURL
= toKURL(redirect
);
520 WebURLRequest request
;
521 request
.initialize();
524 m_expectedRedirectResponse
= WebURLResponse();
525 m_expectedRedirectResponse
.initialize();
526 m_expectedRedirectResponse
.setMIMEType("text/html");
527 m_expectedRedirectResponse
.setHTTPStatusCode(301);
528 m_expectedRedirectResponse
.setHTTPHeaderField("Location", redirect
);
529 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedRedirectResponse
, m_frameFilePath
);
531 m_expectedNewRequest
= WebURLRequest();
532 m_expectedNewRequest
.initialize();
533 m_expectedNewRequest
.setURL(redirectURL
);
535 m_expectedResponse
= WebURLResponse();
536 m_expectedResponse
.initialize();
537 m_expectedResponse
.setMIMEType("text/html");
538 m_expectedResponse
.setHTTPStatusCode(200);
539 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL
, m_expectedResponse
, m_frameFilePath
);
541 WebURLLoaderOptions options
;
542 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
543 m_expectedLoader
= createAssociatedURLLoader(options
);
544 EXPECT_TRUE(m_expectedLoader
);
545 m_expectedLoader
->loadAsynchronously(request
, this);
548 // We should get a notification about access control check failure.
549 EXPECT_FALSE(m_willSendRequest
);
550 EXPECT_FALSE(m_didReceiveResponse
);
551 EXPECT_FALSE(m_didReceiveData
);
552 EXPECT_TRUE(m_didFail
);
555 // Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
556 TEST_F(AssociatedURLLoaderTest
, RedirectCrossOriginWithAccessControlSuccess
)
558 KURL url
= toKURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html");
559 char redirect
[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html"; // Cross-origin
560 KURL redirectURL
= toKURL(redirect
);
562 WebURLRequest request
;
563 request
.initialize();
565 // Add a CORS simple header.
566 request
.setHTTPHeaderField("accept", "application/json");
568 // Create a redirect response that allows the redirect to pass the access control checks.
569 m_expectedRedirectResponse
= WebURLResponse();
570 m_expectedRedirectResponse
.initialize();
571 m_expectedRedirectResponse
.setMIMEType("text/html");
572 m_expectedRedirectResponse
.setHTTPStatusCode(301);
573 m_expectedRedirectResponse
.setHTTPHeaderField("Location", redirect
);
574 m_expectedRedirectResponse
.addHTTPHeaderField("access-control-allow-origin", "*");
575 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedRedirectResponse
, m_frameFilePath
);
577 m_expectedNewRequest
= WebURLRequest();
578 m_expectedNewRequest
.initialize();
579 m_expectedNewRequest
.setURL(redirectURL
);
580 m_expectedNewRequest
.setHTTPHeaderField("accept", "application/json");
582 m_expectedResponse
= WebURLResponse();
583 m_expectedResponse
.initialize();
584 m_expectedResponse
.setMIMEType("text/html");
585 m_expectedResponse
.setHTTPStatusCode(200);
586 m_expectedResponse
.addHTTPHeaderField("access-control-allow-origin", "*");
587 Platform::current()->unitTestSupport()->registerMockedURL(redirectURL
, m_expectedResponse
, m_frameFilePath
);
589 WebURLLoaderOptions options
;
590 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
591 m_expectedLoader
= createAssociatedURLLoader(options
);
592 EXPECT_TRUE(m_expectedLoader
);
593 m_expectedLoader
->loadAsynchronously(request
, this);
595 // We should not receive a notification for the redirect.
596 EXPECT_FALSE(m_willSendRequest
);
597 EXPECT_TRUE(m_didReceiveResponse
);
598 EXPECT_TRUE(m_didReceiveData
);
599 EXPECT_TRUE(m_didFinishLoading
);
602 // Test that untrusted loads can't use a forbidden method.
603 TEST_F(AssociatedURLLoaderTest
, UntrustedCheckMethods
)
605 // Check non-token method fails.
606 CheckMethodFails("GET()");
607 CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234");
609 // Forbidden methods should fail regardless of casing.
610 CheckMethodFails("CoNneCt");
611 CheckMethodFails("TrAcK");
612 CheckMethodFails("TrAcE");
615 // This test is flaky on Windows and Android. See <http://crbug.com/471645>.
616 #if OS(WIN) || OS(ANDROID)
617 #define MAYBE_UntrustedCheckHeaders DISABLED_UntrustedCheckHeaders
619 #define MAYBE_UntrustedCheckHeaders UntrustedCheckHeaders
622 // Test that untrusted loads can't use a forbidden header field.
623 TEST_F(AssociatedURLLoaderTest
, MAYBE_UntrustedCheckHeaders
)
625 // Check non-token header fails.
626 CheckHeaderFails("foo()");
628 // Check forbidden headers fail.
629 CheckHeaderFails("accept-charset");
630 CheckHeaderFails("accept-encoding");
631 CheckHeaderFails("connection");
632 CheckHeaderFails("content-length");
633 CheckHeaderFails("cookie");
634 CheckHeaderFails("cookie2");
635 CheckHeaderFails("date");
636 CheckHeaderFails("dnt");
637 CheckHeaderFails("expect");
638 CheckHeaderFails("host");
639 CheckHeaderFails("keep-alive");
640 CheckHeaderFails("origin");
641 CheckHeaderFails("referer");
642 CheckHeaderFails("te");
643 CheckHeaderFails("trailer");
644 CheckHeaderFails("transfer-encoding");
645 CheckHeaderFails("upgrade");
646 CheckHeaderFails("user-agent");
647 CheckHeaderFails("via");
649 CheckHeaderFails("proxy-");
650 CheckHeaderFails("proxy-foo");
651 CheckHeaderFails("sec-");
652 CheckHeaderFails("sec-foo");
654 // Check that validation is case-insensitive.
655 CheckHeaderFails("AcCePt-ChArSeT");
656 CheckHeaderFails("ProXy-FoO");
658 // Check invalid header values.
659 CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
662 // Test that the loader filters response headers according to the CORS standard.
663 TEST_F(AssociatedURLLoaderTest
, CrossOriginHeaderWhitelisting
)
665 // Test that whitelisted headers are returned without exposing them.
666 EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false));
667 EXPECT_TRUE(CheckAccessControlHeaders("content-language", false));
668 EXPECT_TRUE(CheckAccessControlHeaders("content-type", false));
669 EXPECT_TRUE(CheckAccessControlHeaders("expires", false));
670 EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false));
671 EXPECT_TRUE(CheckAccessControlHeaders("pragma", false));
673 // Test that non-whitelisted headers aren't returned.
674 EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));
676 // Test that Set-Cookie headers aren't returned.
677 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
678 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));
680 // Test that exposed headers that aren't whitelisted are returned.
681 EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));
683 // Test that Set-Cookie headers aren't returned, even if exposed.
684 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
687 // Test that the loader can allow non-whitelisted response headers for trusted CORS loads.
688 TEST_F(AssociatedURLLoaderTest
, CrossOriginHeaderAllowResponseHeaders
)
690 WebURLRequest request
;
691 request
.initialize();
692 KURL url
= toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
695 WebString
headerNameString(WebString::fromUTF8("non-whitelisted"));
696 m_expectedResponse
= WebURLResponse();
697 m_expectedResponse
.initialize();
698 m_expectedResponse
.setMIMEType("text/html");
699 m_expectedResponse
.setHTTPStatusCode(200);
700 m_expectedResponse
.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
701 m_expectedResponse
.addHTTPHeaderField(headerNameString
, "foo");
702 Platform::current()->unitTestSupport()->registerMockedURL(url
, m_expectedResponse
, m_frameFilePath
);
704 WebURLLoaderOptions options
;
705 options
.exposeAllResponseHeaders
= true; // This turns off response whitelisting.
706 options
.crossOriginRequestPolicy
= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl
;
707 m_expectedLoader
= createAssociatedURLLoader(options
);
708 EXPECT_TRUE(m_expectedLoader
);
709 m_expectedLoader
->loadAsynchronously(request
, this);
711 EXPECT_TRUE(m_didReceiveResponse
);
712 EXPECT_TRUE(m_didReceiveData
);
713 EXPECT_TRUE(m_didFinishLoading
);
715 EXPECT_FALSE(m_actualResponse
.httpHeaderField(headerNameString
).isEmpty());