Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / web / AssociatedURLLoaderTest.cpp
blob07000f39c3665d78f35a342a42f9305de8535161
1 /*
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
6 * met:
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.
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.
31 #include "config.h"
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;
55 namespace blink {
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)
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);
85 return url;
88 void SetUp() override
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();
113 void serveRequests()
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);
161 EXPECT_TRUE(data);
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
179 m_didFail = true;
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);
206 else
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);
217 m_didFail = false;
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.
222 runPendingTasks();
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);
231 if (exposed)
232 id.append("-Exposed");
233 id.append(".html");
235 KURL url = toKURL(id);
236 WebURLRequest request;
237 request.initialize();
238 request.setURL(url);
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", "*");
246 if (exposed)
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);
256 serveRequests();
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(); }
266 protected:
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;
277 bool m_didSendData;
278 bool m_didReceiveResponse;
279 bool m_didDownloadData;
280 bool m_didReceiveData;
281 bool m_didReceiveCachedMetadata;
282 bool m_didFinishLoading;
283 bool m_didFail;
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();
292 request.setURL(url);
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);
303 serveRequests();
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();
316 request.setURL(url);
317 CheckFails(request);
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();
327 request.setURL(url);
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);
340 serveRequests();
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();
353 request.setURL(url);
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);
367 serveRequests();
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();
380 request.setURL(url);
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.
401 serveRequests();
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();
413 request.setURL(url);
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.
431 serveRequests();
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();
445 request.setURL(url);
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);
467 serveRequests();
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
479 KURL redirectURL;
481 WebURLRequest request;
482 request.initialize();
483 request.setURL(url);
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);
506 serveRequests();
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();
522 request.setURL(url);
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);
547 serveRequests();
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();
564 request.setURL(url);
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);
594 serveRequests();
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
618 #else
619 #define MAYBE_UntrustedCheckHeaders UntrustedCheckHeaders
620 #endif
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");
693 request.setURL(url);
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);
710 serveRequests();
711 EXPECT_TRUE(m_didReceiveResponse);
712 EXPECT_TRUE(m_didReceiveData);
713 EXPECT_TRUE(m_didFinishLoading);
715 EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty());
718 } // namespace blink