Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / AssociatedURLLoaderTest.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #include "public/platform/Platform.h"
34 #include "public/platform/WebString.h"
35 #include "public/platform/WebThread.h"
36 #include "public/platform/WebURL.h"
37 #include "public/platform/WebURLLoader.h"
38 #include "public/platform/WebURLLoaderClient.h"
39 #include "public/platform/WebURLRequest.h"
40 #include "public/platform/WebURLResponse.h"
41 #include "public/platform/WebUnitTestSupport.h"
42 #include "public/web/WebFrame.h"
43 #include "public/web/WebURLLoaderOptions.h"
44 #include "public/web/WebView.h"
45 #include "web/tests/FrameTestHelpers.h"
46 #include "web/tests/URLTestHelpers.h"
47 #include "wtf/text/CString.h"
48 #include "wtf/text/WTFString.h"
49
50 #include <gtest/gtest.h>
51
52 using namespace blink;
53 using blink::URLTestHelpers::toKURL;
54
55 namespace {
56
57 class AssociatedURLLoaderTest : public testing::Test,
58                                 public WebURLLoaderClient {
59 public:
60     AssociatedURLLoaderTest()
61         :  m_willSendRequest(false)
62         ,  m_didSendData(false)
63         ,  m_didReceiveResponse(false)
64         ,  m_didReceiveData(false)
65         ,  m_didReceiveCachedMetadata(false)
66         ,  m_didFinishLoading(false)
67         ,  m_didFail(false)
68         ,  m_runningMessageLoop(false)
69     {
70         // Reuse one of the test files from WebFrameTest.
71         m_baseFilePath = Platform::current()->unitTestSupport()->webKitRootDir();
72         m_baseFilePath.append("/Source/web/tests/data/");
73         m_frameFilePath = m_baseFilePath;
74         m_frameFilePath.append("iframes_test.html");
75     }
76
77     WebCore::KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename)
78     {
79         WebURLResponse response;
80         response.initialize();
81         response.setMIMEType("text/html");
82         WTF::String localPath = m_baseFilePath;
83         localPath.append(filename);
84         WebCore::KURL url = toKURL(urlRoot + filename.utf8().data());
85         Platform::current()->unitTestSupport()->registerMockedURL(url, response, localPath);
86         return url;
87     }
88
89     void SetUp()
90     {
91         m_helper.initialize();
92
93         std::string urlRoot = "http://www.test.com/";
94         WebCore::KURL url = RegisterMockedUrl(urlRoot, "iframes_test.html");
95         const char* iframeSupportFiles[] = {
96             "invisible_iframe.html",
97             "visible_iframe.html",
98             "zero_sized_iframe.html",
99         };
100         for (size_t i = 0; i < arraysize(iframeSupportFiles); ++i) {
101             RegisterMockedUrl(urlRoot, iframeSupportFiles[i]);
102         }
103
104         WebURLRequest request;
105         request.initialize();
106         request.setURL(url);
107         mainFrame()->loadRequest(request);
108         serveRequests();
109
110         Platform::current()->unitTestSupport()->unregisterMockedURL(url);
111     }
112
113     void TearDown()
114     {
115         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
116     }
117
118     void serveRequests()
119     {
120         Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
121     }
122
123     PassOwnPtr<WebURLLoader> createAssociatedURLLoader(const WebURLLoaderOptions options = WebURLLoaderOptions())
124     {
125         return adoptPtr(mainFrame()->createAssociatedURLLoader(options));
126     }
127
128     // WebURLLoaderClient implementation.
129     void willSendRequest(WebURLLoader* loader, WebURLRequest& newRequest, const WebURLResponse& redirectResponse)
130     {
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());
139     }
140
141     void didSendData(WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
142     {
143         m_didSendData = true;
144         EXPECT_EQ(m_expectedLoader, loader);
145     }
146
147     void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response)
148     {
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());
154     }
155
156     void didDownloadData(WebURLLoader* loader, int dataLength, int encodedDataLength)
157     {
158         m_didDownloadData = true;
159         EXPECT_EQ(m_expectedLoader, loader);
160     }
161
162     void didReceiveData(WebURLLoader* loader, const char* data, int dataLength, int encodedDataLength)
163     {
164         m_didReceiveData = true;
165         EXPECT_EQ(m_expectedLoader, loader);
166         EXPECT_TRUE(data);
167         EXPECT_GT(dataLength, 0);
168     }
169
170     void didReceiveCachedMetadata(WebURLLoader* loader, const char* data, int dataLength)
171     {
172         m_didReceiveCachedMetadata = true;
173         EXPECT_EQ(m_expectedLoader, loader);
174     }
175
176     void didFinishLoading(WebURLLoader* loader, double finishTime, int64_t encodedDataLength)
177     {
178         m_didFinishLoading = true;
179         EXPECT_EQ(m_expectedLoader, loader);
180     }
181
182     void didFail(WebURLLoader* loader, const WebURLError& error)
183     {
184         m_didFail = true;
185         EXPECT_EQ(m_expectedLoader, loader);
186         if (m_runningMessageLoop) {
187             m_runningMessageLoop = false;
188             Platform::current()->currentThread()->exitRunLoop();
189         }
190     }
191
192     void CheckMethodFails(const char* unsafeMethod)
193     {
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);
201     }
202
203     void CheckHeaderFails(const char* headerField)
204     {
205         CheckHeaderFails(headerField, "foo");
206     }
207
208     void CheckHeaderFails(const char* headerField, const char* headerValue)
209     {
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);
215         else
216             request.setHTTPHeaderField(WebString::fromUTF8(headerField), WebString::fromUTF8(headerValue));
217         WebURLLoaderOptions options;
218         options.untrustedHTTP = true;
219         CheckFails(request, options);
220     }
221
222     void CheckFails(const WebURLRequest& request, WebURLLoaderOptions options = WebURLLoaderOptions())
223     {
224         m_expectedLoader = createAssociatedURLLoader(options);
225         EXPECT_TRUE(m_expectedLoader);
226         m_didFail = false;
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);
235     }
236
237     bool CheckAccessControlHeaders(const char* headerName, bool exposed)
238     {
239         std::string id("http://www.other.com/CheckAccessControlExposeHeaders_");
240         id.append(headerName);
241         if (exposed)
242             id.append("-Exposed");
243         id.append(".html");
244
245         WebCore::KURL url = toKURL(id);
246         WebURLRequest request;
247         request.initialize();
248         request.setURL(url);
249
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", "*");
256         if (exposed)
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);
260
261         WebURLLoaderOptions options;
262         options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
263         m_expectedLoader = createAssociatedURLLoader(options);
264         EXPECT_TRUE(m_expectedLoader);
265         m_expectedLoader->loadAsynchronously(request, this);
266         serveRequests();
267         EXPECT_TRUE(m_didReceiveResponse);
268         EXPECT_TRUE(m_didReceiveData);
269         EXPECT_TRUE(m_didFinishLoading);
270
271         return !m_actualResponse.httpHeaderField(headerNameString).isEmpty();
272     }
273
274     WebFrame* mainFrame() const { return m_helper.webView()->mainFrame(); }
275
276 protected:
277     WTF::String m_baseFilePath;
278     WTF::String m_frameFilePath;
279     FrameTestHelpers::WebViewHelper m_helper;
280
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;
287     bool m_didSendData;
288     bool m_didReceiveResponse;
289     bool m_didDownloadData;
290     bool m_didReceiveData;
291     bool m_didReceiveCachedMetadata;
292     bool m_didFinishLoading;
293     bool m_didFail;
294     bool m_runningMessageLoop;
295 };
296
297 // Test a successful same-origin URL load.
298 TEST_F(AssociatedURLLoaderTest, SameOriginSuccess)
299 {
300     WebCore::KURL url = toKURL("http://www.test.com/SameOriginSuccess.html");
301     WebURLRequest request;
302     request.initialize();
303     request.setURL(url);
304
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);
310
311     m_expectedLoader = createAssociatedURLLoader();
312     EXPECT_TRUE(m_expectedLoader);
313     m_expectedLoader->loadAsynchronously(request, this);
314     serveRequests();
315     EXPECT_TRUE(m_didReceiveResponse);
316     EXPECT_TRUE(m_didReceiveData);
317     EXPECT_TRUE(m_didFinishLoading);
318 }
319
320 // Test that the same-origin restriction is the default.
321 TEST_F(AssociatedURLLoaderTest, SameOriginRestriction)
322 {
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();
327     request.setURL(url);
328     CheckFails(request);
329 }
330
331 // Test a successful cross-origin load.
332 TEST_F(AssociatedURLLoaderTest, CrossOriginSuccess)
333 {
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();
338     request.setURL(url);
339
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);
345
346     WebURLLoaderOptions options;
347     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
348     m_expectedLoader = createAssociatedURLLoader(options);
349     EXPECT_TRUE(m_expectedLoader);
350     m_expectedLoader->loadAsynchronously(request, this);
351     serveRequests();
352     EXPECT_TRUE(m_didReceiveResponse);
353     EXPECT_TRUE(m_didReceiveData);
354     EXPECT_TRUE(m_didFinishLoading);
355 }
356
357 // Test a successful cross-origin load using CORS.
358 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess)
359 {
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();
364     request.setURL(url);
365
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);
372
373     WebURLLoaderOptions options;
374     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
375     m_expectedLoader = createAssociatedURLLoader(options);
376     EXPECT_TRUE(m_expectedLoader);
377     m_expectedLoader->loadAsynchronously(request, this);
378     serveRequests();
379     EXPECT_TRUE(m_didReceiveResponse);
380     EXPECT_TRUE(m_didReceiveData);
381     EXPECT_TRUE(m_didFinishLoading);
382 }
383
384 // Test an unsuccessful cross-origin load using CORS.
385 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailure)
386 {
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();
391     request.setURL(url);
392
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);
399
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);
408
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.
412     serveRequests();
413     EXPECT_TRUE(m_didFail);
414     EXPECT_FALSE(m_didReceiveResponse);
415 }
416
417 // Test an unsuccessful cross-origin load using CORS.
418 TEST_F(AssociatedURLLoaderTest, CrossOriginWithAccessControlFailureBadStatusCode)
419 {
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();
424     request.setURL(url);
425
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);
432
433     WebURLLoaderOptions options;
434     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
435     m_expectedLoader = createAssociatedURLLoader(options);
436     EXPECT_TRUE(m_expectedLoader);
437     m_expectedLoader->loadAsynchronously(request, this);
438
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.
442     serveRequests();
443     EXPECT_TRUE(m_didFail);
444     EXPECT_FALSE(m_didReceiveResponse);
445 }
446
447 // Test a same-origin URL redirect and load.
448 TEST_F(AssociatedURLLoaderTest, RedirectSuccess)
449 {
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);
453
454     WebURLRequest request;
455     request.initialize();
456     request.setURL(url);
457
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);
464
465     m_expectedNewRequest = WebURLRequest();
466     m_expectedNewRequest.initialize();
467     m_expectedNewRequest.setURL(redirectURL);
468
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);
474
475     m_expectedLoader = createAssociatedURLLoader();
476     EXPECT_TRUE(m_expectedLoader);
477     m_expectedLoader->loadAsynchronously(request, this);
478     serveRequests();
479     EXPECT_TRUE(m_willSendRequest);
480     EXPECT_TRUE(m_didReceiveResponse);
481     EXPECT_TRUE(m_didReceiveData);
482     EXPECT_TRUE(m_didFinishLoading);
483 }
484
485 // Test that a cross origin redirect response without CORS headers fails.
486 // Disabled, http://crbug.com/240912 .
487 TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlFailure)
488 {
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);
492
493     WebURLRequest request;
494     request.initialize();
495     request.setURL(url);
496
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);
504
505     WebURLLoaderOptions options;
506     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
507     m_expectedLoader = createAssociatedURLLoader(options);
508     EXPECT_TRUE(m_expectedLoader);
509     m_expectedLoader->loadAsynchronously(request, this);
510     serveRequests();
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);
516 }
517
518 // Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
519 TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess)
520 {
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);
524
525     WebURLRequest request;
526     request.initialize();
527     request.setURL(url);
528     // Add a CORS simple header.
529     request.setHTTPHeaderField("accept", "application/json");
530
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);
539
540     m_expectedNewRequest = WebURLRequest();
541     m_expectedNewRequest.initialize();
542     m_expectedNewRequest.setURL(redirectURL);
543     m_expectedNewRequest.setHTTPHeaderField("accept", "application/json");
544
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);
551
552     WebURLLoaderOptions options;
553     options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
554     m_expectedLoader = createAssociatedURLLoader(options);
555     EXPECT_TRUE(m_expectedLoader);
556     m_expectedLoader->loadAsynchronously(request, this);
557     serveRequests();
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);
563 }
564
565 // Test that untrusted loads can't use a forbidden method.
566 TEST_F(AssociatedURLLoaderTest, UntrustedCheckMethods)
567 {
568     // Check non-token method fails.
569     CheckMethodFails("GET()");
570     CheckMethodFails("POST\x0d\x0ax-csrf-token:\x20test1234");
571
572     // Forbidden methods should fail regardless of casing.
573     CheckMethodFails("CoNneCt");
574     CheckMethodFails("TrAcK");
575     CheckMethodFails("TrAcE");
576 }
577
578 // Test that untrusted loads can't use a forbidden header field.
579 TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders)
580 {
581     // Check non-token header fails.
582     CheckHeaderFails("foo()");
583
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");
604
605     CheckHeaderFails("proxy-");
606     CheckHeaderFails("proxy-foo");
607     CheckHeaderFails("sec-");
608     CheckHeaderFails("sec-foo");
609
610     // Check that validation is case-insensitive.
611     CheckHeaderFails("AcCePt-ChArSeT");
612     CheckHeaderFails("ProXy-FoO");
613
614     // Check invalid header values.
615     CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
616 }
617
618 // Test that the loader filters response headers according to the CORS standard.
619 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting)
620 {
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));
628
629     // Test that non-whitelisted headers aren't returned.
630     EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));
631
632     // Test that Set-Cookie headers aren't returned.
633     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
634     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));
635
636     // Test that exposed headers that aren't whitelisted are returned.
637     EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));
638
639     // Test that Set-Cookie headers aren't returned, even if exposed.
640     EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
641 }
642
643 // Test that the loader can allow non-whitelisted response headers for trusted CORS loads.
644 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders)
645 {
646     WebURLRequest request;
647     request.initialize();
648     WebCore::KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html");
649     request.setURL(url);
650
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);
659
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);
666     serveRequests();
667     EXPECT_TRUE(m_didReceiveResponse);
668     EXPECT_TRUE(m_didReceiveData);
669     EXPECT_TRUE(m_didFinishLoading);
670
671     EXPECT_FALSE(m_actualResponse.httpHeaderField(headerNameString).isEmpty());
672 }
673
674 }