Changeset 201800 in webkit
- Timestamp:
- Jun 8, 2016 2:01:07 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r201799 r201800 1 2016-06-06 Antti Koivisto <antti@apple.com> 2 3 WebKit memory cache doesn't respect Vary header 4 https://bugs.webkit.org/show_bug.cgi?id=71509 5 <rdar://problem/26651033> 6 7 Reviewed by Sam Weinig. 8 9 Implement Vary header support in WebCore memory cache. 10 11 The patch moves Vary header code from WebKit2 Network Cache to WebCore and uses it to 12 verify the headers for CachedResources. 13 14 * loader/cache/CachedResource.cpp: 15 (WebCore::CachedResource::failBeforeStarting): 16 (WebCore::addAdditionalRequestHeadersToRequest): 17 18 Factor into standalone function so we can use it from varyHeaderValuesMatch. 19 20 (WebCore::CachedResource::addAdditionalRequestHeaders): 21 (WebCore::CachedResource::load): 22 (WebCore::CachedResource::setResponse): 23 24 Collect the Vary header values when we receive a response. 25 26 (WebCore::CachedResource::responseReceived): 27 (WebCore::CachedResource::redirectChainAllowsReuse): 28 (WebCore::CachedResource::varyHeaderValuesMatch): 29 30 Test for Vary match. 31 32 (WebCore::CachedResource::overheadSize): 33 * loader/cache/CachedResource.h: 34 (WebCore::CachedResource::isCacheValidator): 35 (WebCore::CachedResource::resourceToRevalidate): 36 * loader/cache/CachedResourceLoader.cpp: 37 (WebCore::CachedResourceLoader::determineRevalidationPolicy): 38 39 Reload on Vary mismatch. 40 41 * platform/network/CacheValidation.cpp: 42 (WebCore::parseCacheControlDirectives): 43 (WebCore::headerValueForVary): 44 (WebCore::collectVaryingRequestHeaders): 45 (WebCore::verifyVaryingRequestHeaders): 46 47 Vary header collection and validation code moves here. 48 49 * platform/network/CacheValidation.h: 50 1 51 2016-06-08 Myles C. Maxfield <mmaxfield@apple.com> 2 52 -
trunk/Source/WebCore/loader/cache/CachedResource.cpp
r201596 r201800 183 183 } 184 184 185 void CachedResource::addAdditionalRequestHeaders(CachedResourceLoader& cachedResourceLoader)185 static void addAdditionalRequestHeadersToRequest(ResourceRequest& request, const CachedResourceLoader& cachedResourceLoader) 186 186 { 187 187 // Note: We skip the Content-Security-Policy check here because we check … … 192 192 String outgoingReferrer; 193 193 String outgoingOrigin; 194 if ( m_resourceRequest.httpReferrer().isNull()) {194 if (request.httpReferrer().isNull()) { 195 195 outgoingReferrer = frameLoader.outgoingReferrer(); 196 196 outgoingOrigin = frameLoader.outgoingOrigin(); 197 197 } else { 198 outgoingReferrer = m_resourceRequest.httpReferrer();198 outgoingReferrer = request.httpReferrer(); 199 199 outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString(); 200 200 } 201 201 202 outgoingReferrer = SecurityPolicy::generateReferrerHeader(cachedResourceLoader.document()->referrerPolicy(), m_resourceRequest.url(), outgoingReferrer); 202 auto referrerPolicy = cachedResourceLoader.document() ? cachedResourceLoader.document()->referrerPolicy() : ReferrerPolicy::Default; 203 outgoingReferrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, request.url(), outgoingReferrer); 203 204 if (outgoingReferrer.isEmpty()) 204 m_resourceRequest.clearHTTPReferrer();205 request.clearHTTPReferrer(); 205 206 else 206 m_resourceRequest.setHTTPReferrer(outgoingReferrer); 207 FrameLoader::addHTTPOriginIfNeeded(m_resourceRequest, outgoingOrigin); 208 209 frameLoader.addExtraFieldsToSubresourceRequest(m_resourceRequest); 207 request.setHTTPReferrer(outgoingReferrer); 208 FrameLoader::addHTTPOriginIfNeeded(request, outgoingOrigin); 209 210 frameLoader.addExtraFieldsToSubresourceRequest(request); 211 } 212 213 void CachedResource::addAdditionalRequestHeaders(CachedResourceLoader& cachedResourceLoader) 214 { 215 addAdditionalRequestHeadersToRequest(m_resourceRequest, cachedResourceLoader); 210 216 } 211 217 … … 418 424 m_response.setType(m_responseType); 419 425 m_response.setRedirected(m_redirectChainCacheStatus.status != RedirectChainCacheStatus::NoRedirection); 426 427 m_varyingHeaderValues = collectVaryingRequestHeaders(m_resourceRequest, m_response, m_sessionID); 420 428 } 421 429 … … 766 774 } 767 775 776 bool CachedResource::varyHeaderValuesMatch(const ResourceRequest& request, const CachedResourceLoader& cachedResourceLoader) 777 { 778 if (m_varyingHeaderValues.isEmpty()) 779 return true; 780 781 ResourceRequest requestWithFullHeaders(request); 782 addAdditionalRequestHeadersToRequest(requestWithFullHeaders, cachedResourceLoader); 783 784 return verifyVaryingRequestHeaders(m_varyingHeaderValues, requestWithFullHeaders, m_sessionID); 785 } 786 768 787 unsigned CachedResource::overheadSize() const 769 788 { -
trunk/Source/WebCore/loader/cache/CachedResource.h
r201324 r201800 243 243 bool redirectChainAllowsReuse(ReuseExpiredRedirectionOrNot) const; 244 244 245 bool varyHeaderValuesMatch(const ResourceRequest&, const CachedResourceLoader&); 246 245 247 bool isCacheValidator() const { return m_resourceToRevalidate; } 246 248 CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } … … 355 357 RedirectChainCacheStatus m_redirectChainCacheStatus; 356 358 359 Vector<std::pair<String, String>> m_varyingHeaderValues; 360 357 361 unsigned long m_identifierForLoadWithoutResourceLoader { 0 }; 358 362 }; -
trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp
r201753 r201800 754 754 } 755 755 756 if (!existingResource->varyHeaderValuesMatch(request, *this)) 757 return Reload; 758 756 759 auto* textDecoder = existingResource->textResourceDecoder(); 757 760 if (textDecoder && !textDecoder->hasEqualEncodingForCharset(cachedResourceRequest.charset())) -
trunk/Source/WebCore/platform/network/CacheValidation.cpp
r195743 r201800 28 28 29 29 #include "HTTPHeaderMap.h" 30 #include "NetworkStorageSession.h" 31 #include "PlatformCookieJar.h" 32 #include "ResourceRequest.h" 30 33 #include "ResourceResponse.h" 31 34 #include <wtf/CurrentTime.h> … … 327 330 } 328 331 329 } 332 static String headerValueForVary(SessionID sessionID, const ResourceRequest& request, const String& headerName) 333 { 334 // Explicit handling for cookies is needed because they are added magically by the networking layer. 335 // FIXME: The value might have changed between making the request and retrieving the cookie here. 336 // We could fetch the cookie when making the request but that seems overkill as the case is very rare and it 337 // is a blocking operation. This should be sufficient to cover reasonable cases. 338 if (headerName == httpHeaderNameString(HTTPHeaderName::Cookie)) { 339 if (sessionID != SessionID::defaultSessionID()) { 340 // FIXME: Don't know how to get the cookie. There should be a global way to get NetworkStorageSession from sessionID. 341 return ""; 342 } 343 return cookieRequestHeaderFieldValue(NetworkStorageSession::defaultStorageSession(), request.firstPartyForCookies(), request.url()); 344 } 345 return request.httpHeaderField(headerName); 346 } 347 348 Vector<std::pair<String, String>> collectVaryingRequestHeaders(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, SessionID sessionID) 349 { 350 String varyValue = response.httpHeaderField(WebCore::HTTPHeaderName::Vary); 351 if (varyValue.isEmpty()) 352 return { }; 353 Vector<String> varyingHeaderNames; 354 varyValue.split(',', /*allowEmptyEntries*/ false, varyingHeaderNames); 355 Vector<std::pair<String, String>> varyingRequestHeaders; 356 varyingRequestHeaders.reserveCapacity(varyingHeaderNames.size()); 357 for (auto& varyHeaderName : varyingHeaderNames) { 358 String headerName = varyHeaderName.stripWhiteSpace(); 359 String headerValue = headerValueForVary(sessionID, request, headerName); 360 varyingRequestHeaders.append(std::make_pair(headerName, headerValue)); 361 } 362 return varyingRequestHeaders; 363 } 364 365 bool verifyVaryingRequestHeaders(const Vector<std::pair<String, String>>& varyingRequestHeaders, const WebCore::ResourceRequest& request, SessionID sessionID) 366 { 367 for (auto& varyingRequestHeader : varyingRequestHeaders) { 368 // FIXME: Vary: * in response would ideally trigger a cache delete instead of a store. 369 if (varyingRequestHeader.first == "*") 370 return false; 371 if (sessionID != SessionID::defaultSessionID() && varyingRequestHeader.first == httpHeaderNameString(HTTPHeaderName::Cookie)) { 372 // FIXME: See the comment in headerValueForVary. 373 return false; 374 } 375 String headerValue = headerValueForVary(sessionID, request, varyingRequestHeader.first); 376 if (headerValue != varyingRequestHeader.second) 377 return false; 378 } 379 return true; 380 } 381 382 } -
trunk/Source/WebCore/platform/network/CacheValidation.h
r196360 r201800 28 28 29 29 #include "PlatformExportMacros.h" 30 #include "SessionID.h" 30 31 #include <wtf/Optional.h> 32 #include <wtf/Vector.h> 33 #include <wtf/text/WTFString.h> 31 34 32 35 namespace WebCore { 33 36 34 37 class HTTPHeaderMap; 38 class ResourceRequest; 35 39 class ResourceResponse; 36 40 … … 66 70 WEBCORE_EXPORT CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&); 67 71 72 WEBCORE_EXPORT Vector<std::pair<String, String>> collectVaryingRequestHeaders(const ResourceRequest&, const ResourceResponse&, SessionID = SessionID::defaultSessionID()); 73 WEBCORE_EXPORT bool verifyVaryingRequestHeaders(const Vector<std::pair<String, String>>& varyingRequestHeaders, const ResourceRequest&, SessionID = SessionID::defaultSessionID()); 74 68 75 } 69 76
Note: See TracChangeset
for help on using the changeset viewer.