Changeset 105134 in webkit
- Timestamp:
- Jan 17, 2012 2:26:31 AM (12 years ago)
- Location:
- trunk/Source/WebKit/chromium
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/chromium/ChangeLog
r105087 r105134 1 2012-01-17 Bill Budge <bbudge@chromium.org> 2 3 AssociatedURLLoader adds support for the HTTP response header Access-Control-Expose-Header. 4 https://bugs.webkit.org/show_bug.cgi?id=76419 5 6 Reviewed by Adam Barth. 7 8 * src/AssociatedURLLoader.cpp: 9 (WebKit::AssociatedURLLoader::ClientAdapter::didReceiveResponse): 10 * tests/AssociatedURLLoaderTest.cpp: 11 (WebKit::AssociatedURLLoaderTest::CheckAccessControlHeaders): 12 (WebKit::TEST_F): 13 1 14 2012-01-16 Bill Budge <bbudge@chromium.org> 2 15 -
trunk/Source/WebKit/chromium/src/AssociatedURLLoader.cpp
r105087 r105134 1 1 /* 2 * Copyright (C) 2010, 2011 Google Inc. All rights reserved.2 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 51 51 #include "platform/WebURLLoaderClient.h" 52 52 #include "platform/WebURLRequest.h" 53 #include <wtf/ Vector.h>53 #include <wtf/HashSet.h> 54 54 #include <wtf/text/WTFString.h> 55 55 … … 73 73 }; 74 74 75 typedef HashSet<String, CaseFoldingHash> HTTPHeaderSet; 76 75 77 void HTTPRequestHeaderValidator::visitHeader(const WebString& name, const WebString& value) 76 78 { … … 84 86 85 87 void visitHeader(const WebString& name, const WebString& value); 86 const Vector<WebString>& disallowedHeaders() const { return m_disallowedHeaders; }88 const HTTPHeaderSet& blockedHeaders(); 87 89 88 90 private: 89 Vector<WebString> m_disallowedHeaders; 91 HTTPHeaderSet m_exposedHeaders; 92 HTTPHeaderSet m_blockedHeaders; 90 93 bool m_usingAccessControl; 91 94 }; … … 94 97 { 95 98 String headerName(name); 96 // Hide non-whitelisted headers for CORS requests. 97 // Hide Set-Cookie headers for all requests. 98 if ((m_usingAccessControl && !isOnAccessControlResponseHeaderWhitelist(headerName)) 99 || (equalIgnoringCase(headerName, "set-cookie") || equalIgnoringCase(headerName, "set-cookie2"))) 100 m_disallowedHeaders.append(name); 99 if (m_usingAccessControl) { 100 if (equalIgnoringCase(headerName, "access-control-expose-header")) 101 parseAccessControlExposeHeadersAllowList(value, m_exposedHeaders); 102 else if (!isOnAccessControlResponseHeaderWhitelist(headerName)) 103 m_blockedHeaders.add(name); 104 } 105 } 106 107 const HTTPHeaderSet& HTTPResponseHeaderValidator::blockedHeaders() 108 { 109 // Remove exposed headers from the blocked set. 110 if (!m_exposedHeaders.isEmpty()) { 111 // Don't allow Set-Cookie headers to be exposed. 112 m_exposedHeaders.remove("set-cookie"); 113 m_exposedHeaders.remove("set-cookie2"); 114 // Block Access-Control-Expose-Header itself. It could be exposed later. 115 m_blockedHeaders.add("access-control-expose-header"); 116 HTTPHeaderSet::const_iterator end = m_exposedHeaders.end(); 117 for (HTTPHeaderSet::const_iterator it = m_exposedHeaders.begin(); it != end; ++it) 118 m_blockedHeaders.remove(*it); 119 } 120 121 return m_blockedHeaders; 101 122 } 102 123 … … 188 209 HTTPResponseHeaderValidator validator(m_options.crossOriginRequestPolicy == WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl); 189 210 validatedResponse.visitHTTPHeaderFields(&validator); 190 // If there are disallowed headers, copy the response so we can remove them.191 const Vector<WebString>& disallowedHeaders = validator.disallowedHeaders();192 if (! disallowedHeaders.isEmpty()) {211 // If there are blocked headers, copy the response so we can remove them. 212 const HTTPHeaderSet& blockedHeaders = validator.blockedHeaders(); 213 if (!blockedHeaders.isEmpty()) { 193 214 validatedResponse = WebURLResponse(validatedResponse); 194 for (size_t i = 0; i < disallowedHeaders.size(); ++i) 195 validatedResponse.clearHTTPHeaderField(disallowedHeaders[i]); 215 HTTPHeaderSet::const_iterator end = blockedHeaders.end(); 216 for (HTTPHeaderSet::const_iterator it = blockedHeaders.begin(); it != end; ++it) 217 validatedResponse.clearHTTPHeaderField(*it); 196 218 } 197 219 m_client->didReceiveResponse(m_loader, validatedResponse); -
trunk/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
r105087 r105134 41 41 #include "platform/WebURLRequest.h" 42 42 #include "platform/WebURLResponse.h" 43 #include <wtf/text/WTFString.h> 43 44 44 45 #include <googleurl/src/gurl.h> … … 220 221 EXPECT_TRUE(m_didFail); 221 222 EXPECT_FALSE(m_didReceiveResponse); 223 } 224 225 bool CheckAccessControlHeaders(const char* headerName, bool exposed) 226 { 227 std::string id("http://www.other.com/CheckAccessControlExposeHeaders_"); 228 id.append(headerName); 229 if (exposed) 230 id.append("-Exposed"); 231 id.append(".html"); 232 233 GURL url = GURL(id); 234 WebURLRequest request; 235 request.initialize(); 236 request.setURL(url); 237 238 WebString headerNameString(WebString::fromUTF8(headerName)); 239 m_expectedResponse = WebURLResponse(); 240 m_expectedResponse.initialize(); 241 m_expectedResponse.setMIMEType("text/html"); 242 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*"); 243 if (exposed) 244 m_expectedResponse.addHTTPHeaderField("access-control-expose-header", headerNameString); 245 m_expectedResponse.addHTTPHeaderField(headerNameString, "foo"); 246 webkit_support::RegisterMockedURL(url, m_expectedResponse, m_frameFilePath); 247 248 WebURLLoaderOptions options; 249 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 250 m_expectedLoader = createAssociatedURLLoader(options); 251 EXPECT_TRUE(m_expectedLoader); 252 m_expectedLoader->loadAsynchronously(request, this); 253 serveRequests(); 254 EXPECT_TRUE(m_didReceiveResponse); 255 EXPECT_TRUE(m_didReceiveData); 256 EXPECT_TRUE(m_didFinishLoading); 257 258 return !m_actualResponse.httpHeaderField(headerNameString).isEmpty(); 222 259 } 223 260 … … 490 527 } 491 528 492 // Test that a CORS load only returns whitelisted headers.529 // Test that the loader filters response headers according to the CORS standard. 493 530 TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting) 494 531 { 495 // This is cross-origin since the frame was loaded from www.test.com. 496 GURL url = GURL("http://www.other.com/CrossOriginHeaderWhitelisting.html"); 497 WebURLRequest request; 498 request.initialize(); 499 request.setURL(url); 500 501 m_expectedResponse = WebURLResponse(); 502 m_expectedResponse.initialize(); 503 m_expectedResponse.setMIMEType("text/html"); 504 m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*"); 505 // These headers are whitelisted and should be in the response. 506 m_expectedResponse.addHTTPHeaderField("cache-control", "foo"); 507 m_expectedResponse.addHTTPHeaderField("content-language", "foo"); 508 m_expectedResponse.addHTTPHeaderField("content-type", "foo"); 509 m_expectedResponse.addHTTPHeaderField("expires", "foo"); 510 m_expectedResponse.addHTTPHeaderField("last-modified", "foo"); 511 m_expectedResponse.addHTTPHeaderField("pragma", "foo"); 512 // These should never be in the response. 513 m_expectedResponse.addHTTPHeaderField("Set-Cookie", "foo"); 514 m_expectedResponse.addHTTPHeaderField("Set-Cookie2", "foo"); 515 webkit_support::RegisterMockedURL(url, m_expectedResponse, m_frameFilePath); 516 517 WebURLLoaderOptions options; 518 options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 519 m_expectedLoader = createAssociatedURLLoader(options); 520 EXPECT_TRUE(m_expectedLoader); 521 m_expectedLoader->loadAsynchronously(request, this); 522 serveRequests(); 523 EXPECT_TRUE(m_didReceiveResponse); 524 EXPECT_TRUE(m_didReceiveData); 525 EXPECT_TRUE(m_didFinishLoading); 526 527 EXPECT_FALSE(m_actualResponse.httpHeaderField("cache-control").isEmpty()); 528 EXPECT_FALSE(m_actualResponse.httpHeaderField("content-language").isEmpty()); 529 EXPECT_FALSE(m_actualResponse.httpHeaderField("content-type").isEmpty()); 530 EXPECT_FALSE(m_actualResponse.httpHeaderField("expires").isEmpty()); 531 EXPECT_FALSE(m_actualResponse.httpHeaderField("last-modified").isEmpty()); 532 EXPECT_FALSE(m_actualResponse.httpHeaderField("pragma").isEmpty()); 533 534 EXPECT_TRUE(m_actualResponse.httpHeaderField("Set-Cookie").isEmpty()); 535 EXPECT_TRUE(m_actualResponse.httpHeaderField("Set-Cookie2").isEmpty()); 536 } 537 538 } 532 // Test that whitelisted headers are returned without exposing them. 533 EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false)); 534 EXPECT_TRUE(CheckAccessControlHeaders("content-language", false)); 535 EXPECT_TRUE(CheckAccessControlHeaders("content-type", false)); 536 EXPECT_TRUE(CheckAccessControlHeaders("expires", false)); 537 EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false)); 538 EXPECT_TRUE(CheckAccessControlHeaders("pragma", false)); 539 540 // Test that non-whitelisted headers aren't returned. 541 EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false)); 542 543 // Test that Set-Cookie headers aren't returned. 544 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false)); 545 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false)); 546 547 // Test that exposed headers that aren't whitelisted are returned. 548 EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true)); 549 550 // Test that Set-Cookie headers aren't returned, even if exposed. 551 EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true)); 552 } 553 554 }
Note: See TracChangeset
for help on using the changeset viewer.