| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 65 |
| 66 private: | 66 private: |
| 67 bool m_isSafe; | 67 bool m_isSafe; |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 void HTTPRequestHeaderValidator::visitHeader(const WebString& name, const WebStr
ing& value) | 70 void HTTPRequestHeaderValidator::visitHeader(const WebString& name, const WebStr
ing& value) |
| 71 { | 71 { |
| 72 m_isSafe = m_isSafe && isValidHTTPToken(name) && !FetchUtils::isForbiddenHea
derName(name) && isValidHTTPHeaderValue(value); | 72 m_isSafe = m_isSafe && isValidHTTPToken(name) && !FetchUtils::isForbiddenHea
derName(name) && isValidHTTPHeaderValue(value); |
| 73 } | 73 } |
| 74 | 74 |
| 75 // FIXME: Remove this and use WebCore code that does the same thing. | |
| 76 class HTTPResponseHeaderValidator : public WebHTTPHeaderVisitor { | |
| 77 WTF_MAKE_NONCOPYABLE(HTTPResponseHeaderValidator); | |
| 78 public: | |
| 79 HTTPResponseHeaderValidator(bool usingAccessControl) : m_usingAccessControl(
usingAccessControl) { } | |
| 80 | |
| 81 void visitHeader(const WebString& name, const WebString& value); | |
| 82 const HTTPHeaderSet& blockedHeaders(); | |
| 83 | |
| 84 private: | |
| 85 HTTPHeaderSet m_exposedHeaders; | |
| 86 HTTPHeaderSet m_blockedHeaders; | |
| 87 bool m_usingAccessControl; | |
| 88 }; | |
| 89 | |
| 90 void HTTPResponseHeaderValidator::visitHeader(const WebString& name, const WebSt
ring& value) | |
| 91 { | |
| 92 String headerName(name); | |
| 93 if (m_usingAccessControl) { | |
| 94 if (equalIgnoringCase(headerName, "access-control-expose-headers")) | |
| 95 parseAccessControlExposeHeadersAllowList(value, m_exposedHeaders); | |
| 96 else if (!isOnAccessControlResponseHeaderWhitelist(headerName)) | |
| 97 m_blockedHeaders.add(static_cast<String>(name)); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 const HTTPHeaderSet& HTTPResponseHeaderValidator::blockedHeaders() | |
| 102 { | |
| 103 // Remove exposed headers from the blocked set. | |
| 104 if (!m_exposedHeaders.isEmpty()) { | |
| 105 // Don't allow Set-Cookie headers to be exposed. | |
| 106 m_exposedHeaders.remove("set-cookie"); | |
| 107 m_exposedHeaders.remove("set-cookie2"); | |
| 108 // Block Access-Control-Expose-Header itself. It could be exposed later. | |
| 109 m_blockedHeaders.add("access-control-expose-headers"); | |
| 110 m_blockedHeaders.removeAll(m_exposedHeaders); | |
| 111 } | |
| 112 | |
| 113 return m_blockedHeaders; | |
| 114 } | |
| 115 | |
| 116 } // namespace | 75 } // namespace |
| 117 | 76 |
| 118 // This class bridges the interface differences between WebCore and WebKit loade
r clients. | 77 // This class bridges the interface differences between WebCore and WebKit loade
r clients. |
| 119 // It forwards its ThreadableLoaderClient notifications to a WebURLLoaderClient. | 78 // It forwards its ThreadableLoaderClient notifications to a WebURLLoaderClient. |
| 120 class AssociatedURLLoader::ClientAdapter final : public DocumentThreadableLoader
Client { | 79 class AssociatedURLLoader::ClientAdapter final : public DocumentThreadableLoader
Client { |
| 121 WTF_MAKE_NONCOPYABLE(ClientAdapter); | 80 WTF_MAKE_NONCOPYABLE(ClientAdapter); |
| 122 public: | 81 public: |
| 123 static PassOwnPtr<ClientAdapter> create(AssociatedURLLoader*, WebURLLoaderCl
ient*, const WebURLLoaderOptions&); | 82 static PassOwnPtr<ClientAdapter> create(AssociatedURLLoader*, WebURLLoaderCl
ient*, const WebURLLoaderOptions&); |
| 124 | 83 |
| 125 // ThreadableLoaderClient | 84 // ThreadableLoaderClient |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 | 157 |
| 199 m_client->didSendData(m_loader, bytesSent, totalBytesToBeSent); | 158 m_client->didSendData(m_loader, bytesSent, totalBytesToBeSent); |
| 200 } | 159 } |
| 201 | 160 |
| 202 void AssociatedURLLoader::ClientAdapter::didReceiveResponse(unsigned long, const
ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 161 void AssociatedURLLoader::ClientAdapter::didReceiveResponse(unsigned long, const
ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
| 203 { | 162 { |
| 204 ASSERT_UNUSED(handle, !handle); | 163 ASSERT_UNUSED(handle, !handle); |
| 205 if (!m_client) | 164 if (!m_client) |
| 206 return; | 165 return; |
| 207 | 166 |
| 208 // Try to use the original ResourceResponse if possible. | 167 if (m_options.exposeAllResponseHeaders || m_options.crossOriginRequestPolicy
!= WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl) { |
| 209 WebURLResponse validatedResponse = WrappedResourceResponse(response); | 168 // Use the original ResourceResponse. |
| 210 HTTPResponseHeaderValidator validator(m_options.crossOriginRequestPolicy ==
WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl); | 169 m_client->didReceiveResponse(m_loader, WrappedResourceResponse(response)
); |
| 211 if (!m_options.exposeAllResponseHeaders) | 170 return; |
| 212 validatedResponse.visitHTTPHeaderFields(&validator); | 171 } |
| 172 |
| 173 HTTPHeaderSet exposedHeaders; |
| 174 extractCorsExposedHeaderNamesList(response, exposedHeaders); |
| 175 HTTPHeaderSet blockedHeaders; |
| 176 for (const auto& header : response.httpHeaderFields()) { |
| 177 if (FetchUtils::isForbiddenResponseHeaderName(header.key) || (!isOnAcces
sControlResponseHeaderWhitelist(header.key) && !exposedHeaders.contains(header.k
ey))) |
| 178 blockedHeaders.add(header.key); |
| 179 } |
| 180 |
| 181 if (blockedHeaders.isEmpty()) { |
| 182 // Use the original ResourceResponse. |
| 183 m_client->didReceiveResponse(m_loader, WrappedResourceResponse(response)
); |
| 184 return; |
| 185 } |
| 213 | 186 |
| 214 // If there are blocked headers, copy the response so we can remove them. | 187 // If there are blocked headers, copy the response so we can remove them. |
| 215 const HTTPHeaderSet& blockedHeaders = validator.blockedHeaders(); | 188 WebURLResponse validatedResponse = WrappedResourceResponse(response); |
| 216 if (!blockedHeaders.isEmpty()) { | 189 for (const auto& header : blockedHeaders) |
| 217 validatedResponse = WebURLResponse(validatedResponse); | 190 validatedResponse.clearHTTPHeaderField(header); |
| 218 HTTPHeaderSet::const_iterator end = blockedHeaders.end(); | |
| 219 for (HTTPHeaderSet::const_iterator it = blockedHeaders.begin(); it != en
d; ++it) | |
| 220 validatedResponse.clearHTTPHeaderField(*it); | |
| 221 } | |
| 222 m_client->didReceiveResponse(m_loader, validatedResponse); | 191 m_client->didReceiveResponse(m_loader, validatedResponse); |
| 223 } | 192 } |
| 224 | 193 |
| 225 void AssociatedURLLoader::ClientAdapter::didDownloadData(int dataLength) | 194 void AssociatedURLLoader::ClientAdapter::didDownloadData(int dataLength) |
| 226 { | 195 { |
| 227 if (!m_client) | 196 if (!m_client) |
| 228 return; | 197 return; |
| 229 | 198 |
| 230 m_client->didDownloadData(m_loader, dataLength, -1); | 199 m_client->didDownloadData(m_loader, dataLength, -1); |
| 231 } | 200 } |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 // there could be a WebURLLoader instance behind the | 449 // there could be a WebURLLoader instance behind the |
| 481 // DocumentThreadableLoader instance. So, for safety, we chose to just | 450 // DocumentThreadableLoader instance. So, for safety, we chose to just |
| 482 // crash here. | 451 // crash here. |
| 483 RELEASE_ASSERT(ThreadState::current()); | 452 RELEASE_ASSERT(ThreadState::current()); |
| 484 | 453 |
| 485 m_observer->dispose(); | 454 m_observer->dispose(); |
| 486 m_observer = nullptr; | 455 m_observer = nullptr; |
| 487 } | 456 } |
| 488 | 457 |
| 489 } // namespace blink | 458 } // namespace blink |
| OLD | NEW |