Changeset 201805 in webkit
- Timestamp:
- Jun 8, 2016 6:37:04 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r201798 r201805 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 * http/tests/cache/disk-cache/disk-cache-vary-expected.txt: 10 * http/tests/cache/disk-cache/disk-cache-vary-no-body-expected.txt: 11 1 12 2016-06-08 Adam Bergkvist <adam.bergkvist@ericsson.com> 2 13 -
trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-vary-expected.txt
r188468 r201805 559 559 response headers: {"Cache-control":"max-age=100","Vary":"Accept-Language"} 560 560 request headers: {"Accept-Language":"unique()"} 561 response source: Memory cache561 response source: Network 562 562 563 563 response headers: {"Cache-control":"no-store","Vary":"Accept-Language"} … … 587 587 response headers: {"ETag":"match","Vary":"Accept-Language"} 588 588 request headers: {"Accept-Language":"unique()"} 589 response source: Memory cache after validation589 response source: Network 590 590 591 591 response headers: {"Cache-control":"max-age=0","ETag":"match","Vary":"Accept-Language"} 592 592 request headers: {"Accept-Language":"unique()"} 593 response source: Memory cache after validation593 response source: Network 594 594 595 595 response headers: {"Cache-control":"max-age=100","ETag":"match","Vary":"Accept-Language"} 596 596 request headers: {"Accept-Language":"unique()"} 597 response source: Memory cache597 response source: Network 598 598 599 599 response headers: {"Cache-control":"no-store","ETag":"match","Vary":"Accept-Language"} … … 611 611 response headers: {"Cache-control":"no-cache","ETag":"match","Vary":"Accept-Language"} 612 612 request headers: {"Accept-Language":"unique()"} 613 response source: Memory cache after validation613 response source: Network 614 614 615 615 response headers: {"Cache-control":"max-age=0, no-cache","ETag":"match","Vary":"Accept-Language"} 616 616 request headers: {"Accept-Language":"unique()"} 617 response source: Memory cache after validation617 response source: Network 618 618 619 619 response headers: {"Cache-control":"max-age=100, no-cache","ETag":"match","Vary":"Accept-Language"} 620 620 request headers: {"Accept-Language":"unique()"} 621 response source: Memory cache after validation621 response source: Network 622 622 623 623 response headers: {"ETag":"nomatch","Vary":"Accept-Language"} … … 631 631 response headers: {"Cache-control":"max-age=100","ETag":"nomatch","Vary":"Accept-Language"} 632 632 request headers: {"Accept-Language":"unique()"} 633 response source: Memory cache633 response source: Network 634 634 635 635 response headers: {"Cache-control":"no-store","ETag":"nomatch","Vary":"Accept-Language"} -
trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-vary-no-body-expected.txt
r188468 r201805 559 559 response headers: {"Cache-control":"max-age=100","Vary":"Accept-Language"} 560 560 request headers: {"Accept-Language":"unique()"} 561 response source: Memory cache561 response source: Network 562 562 563 563 response headers: {"Cache-control":"no-store","Vary":"Accept-Language"} … … 587 587 response headers: {"ETag":"match","Vary":"Accept-Language"} 588 588 request headers: {"Accept-Language":"unique()"} 589 response source: Memory cache after validation589 response source: Network 590 590 591 591 response headers: {"Cache-control":"max-age=0","ETag":"match","Vary":"Accept-Language"} 592 592 request headers: {"Accept-Language":"unique()"} 593 response source: Memory cache after validation593 response source: Network 594 594 595 595 response headers: {"Cache-control":"max-age=100","ETag":"match","Vary":"Accept-Language"} 596 596 request headers: {"Accept-Language":"unique()"} 597 response source: Memory cache597 response source: Network 598 598 599 599 response headers: {"Cache-control":"no-store","ETag":"match","Vary":"Accept-Language"} … … 611 611 response headers: {"Cache-control":"no-cache","ETag":"match","Vary":"Accept-Language"} 612 612 request headers: {"Accept-Language":"unique()"} 613 response source: Memory cache after validation613 response source: Network 614 614 615 615 response headers: {"Cache-control":"max-age=0, no-cache","ETag":"match","Vary":"Accept-Language"} 616 616 request headers: {"Accept-Language":"unique()"} 617 response source: Memory cache after validation617 response source: Network 618 618 619 619 response headers: {"Cache-control":"max-age=100, no-cache","ETag":"match","Vary":"Accept-Language"} 620 620 request headers: {"Accept-Language":"unique()"} 621 response source: Memory cache after validation621 response source: Network 622 622 623 623 response headers: {"ETag":"nomatch","Vary":"Accept-Language"} … … 631 631 response headers: {"Cache-control":"max-age=100","ETag":"nomatch","Vary":"Accept-Language"} 632 632 request headers: {"Accept-Language":"unique()"} 633 response source: Memory cache633 response source: Network 634 634 635 635 response headers: {"Cache-control":"no-store","ETag":"nomatch","Vary":"Accept-Language"} -
trunk/Source/WebCore/ChangeLog
r201801 r201805 1 2016-06-08 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 Commit Queue <commit-queue@webkit.org> 2 52 -
trunk/Source/WebCore/loader/cache/CachedResource.cpp
r201801 r201805 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
r201801 r201805 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
r201801 r201805 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
r201801 r201805 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "CacheValidation.h" 28 28 29 #include "CookiesStrategy.h" 29 30 #include "HTTPHeaderMap.h" 31 #include "NetworkStorageSession.h" 32 #include "PlatformCookieJar.h" 33 #include "PlatformStrategies.h" 34 #include "ResourceRequest.h" 30 35 #include "ResourceResponse.h" 31 36 #include <wtf/CurrentTime.h> … … 327 332 } 328 333 329 } 334 static String headerValueForVary(const ResourceRequest& request, const String& headerName, SessionID sessionID) 335 { 336 // Explicit handling for cookies is needed because they are added magically by the networking layer. 337 // FIXME: The value might have changed between making the request and retrieving the cookie here. 338 // We could fetch the cookie when making the request but that seems overkill as the case is very rare and it 339 // is a blocking operation. This should be sufficient to cover reasonable cases. 340 if (headerName == httpHeaderNameString(HTTPHeaderName::Cookie)) { 341 if (sessionID != SessionID::defaultSessionID()) { 342 // FIXME: Don't know how to get the cookie. There should be a global way to get NetworkStorageSession from sessionID. 343 return ""; 344 } 345 auto& session = NetworkStorageSession::defaultStorageSession(); 346 auto* cookieStrategy = platformStrategies() ? platformStrategies()->cookiesStrategy() : nullptr; 347 if (!cookieStrategy) 348 return cookieRequestHeaderFieldValue(session, request.firstPartyForCookies(), request.url()); 349 return cookieStrategy->cookieRequestHeaderFieldValue(session, request.firstPartyForCookies(), request.url()); 350 } 351 return request.httpHeaderField(headerName); 352 } 353 354 Vector<std::pair<String, String>> collectVaryingRequestHeaders(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, SessionID sessionID) 355 { 356 String varyValue = response.httpHeaderField(WebCore::HTTPHeaderName::Vary); 357 if (varyValue.isEmpty()) 358 return { }; 359 Vector<String> varyingHeaderNames; 360 varyValue.split(',', /*allowEmptyEntries*/ false, varyingHeaderNames); 361 Vector<std::pair<String, String>> varyingRequestHeaders; 362 varyingRequestHeaders.reserveCapacity(varyingHeaderNames.size()); 363 for (auto& varyHeaderName : varyingHeaderNames) { 364 String headerName = varyHeaderName.stripWhiteSpace(); 365 String headerValue = headerValueForVary(request, headerName, sessionID); 366 varyingRequestHeaders.append(std::make_pair(headerName, headerValue)); 367 } 368 return varyingRequestHeaders; 369 } 370 371 bool verifyVaryingRequestHeaders(const Vector<std::pair<String, String>>& varyingRequestHeaders, const WebCore::ResourceRequest& request, SessionID sessionID) 372 { 373 for (auto& varyingRequestHeader : varyingRequestHeaders) { 374 // FIXME: Vary: * in response would ideally trigger a cache delete instead of a store. 375 if (varyingRequestHeader.first == "*") 376 return false; 377 if (sessionID != SessionID::defaultSessionID() && varyingRequestHeader.first == httpHeaderNameString(HTTPHeaderName::Cookie)) { 378 // FIXME: See the comment in headerValueForVary. 379 return false; 380 } 381 String headerValue = headerValueForVary(request, varyingRequestHeader.first, sessionID); 382 if (headerValue != varyingRequestHeader.second) 383 return false; 384 } 385 return true; 386 } 387 388 } -
trunk/Source/WebCore/platform/network/CacheValidation.h
r201801 r201805 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 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 -
trunk/Source/WebKit2/ChangeLog
r201803 r201805 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 * NetworkProcess/cache/NetworkCache.cpp: 10 (WebKit::NetworkCache::makeCacheKey): 11 (WebKit::NetworkCache::cachePolicyAllowsExpired): 12 (WebKit::NetworkCache::makeUseDecision): 13 (WebKit::NetworkCache::Cache::retrieve): 14 (WebKit::NetworkCache::Cache::store): 15 (WebKit::NetworkCache::Cache::storeRedirect): 16 (WebKit::NetworkCache::Cache::update): 17 (WebKit::NetworkCache::headerValueForVary): Deleted. 18 (WebKit::NetworkCache::collectVaryingRequestHeaders): Deleted. 19 (WebKit::NetworkCache::verifyVaryingRequestHeaders): Deleted. 20 21 These move to WebCore. 22 1 23 2016-06-08 Carlos Garcia Campos <cgarcia@igalia.com> 2 24 -
trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
r201673 r201805 129 129 } 130 130 131 static String headerValueForVary(const WebCore::ResourceRequest& request, const String& headerName)132 {133 // Explicit handling for cookies is needed because they are added magically by the networking layer.134 // FIXME: The value might have changed between making the request and retrieving the cookie here.135 // We could fetch the cookie when making the request but that seems overkill as the case is very rare and it136 // is a blocking operation. This should be sufficient to cover reasonable cases.137 if (headerName == httpHeaderNameString(WebCore::HTTPHeaderName::Cookie))138 return WebCore::cookieRequestHeaderFieldValue(WebCore::NetworkStorageSession::defaultStorageSession(), request.firstPartyForCookies(), request.url());139 return request.httpHeaderField(headerName);140 }141 142 static Vector<std::pair<String, String>> collectVaryingRequestHeaders(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response)143 {144 String varyValue = response.httpHeaderField(WebCore::HTTPHeaderName::Vary);145 if (varyValue.isEmpty())146 return { };147 Vector<String> varyingHeaderNames;148 varyValue.split(',', /*allowEmptyEntries*/ false, varyingHeaderNames);149 Vector<std::pair<String, String>> varyingRequestHeaders;150 varyingRequestHeaders.reserveCapacity(varyingHeaderNames.size());151 for (auto& varyHeaderName : varyingHeaderNames) {152 String headerName = varyHeaderName.stripWhiteSpace();153 String headerValue = headerValueForVary(request, headerName);154 varyingRequestHeaders.append(std::make_pair(headerName, headerValue));155 }156 return varyingRequestHeaders;157 }158 159 static bool verifyVaryingRequestHeaders(const Vector<std::pair<String, String>>& varyingRequestHeaders, const WebCore::ResourceRequest& request)160 {161 for (auto& varyingRequestHeader : varyingRequestHeaders) {162 // FIXME: Vary: * in response would ideally trigger a cache delete instead of a store.163 if (varyingRequestHeader.first == "*")164 return false;165 String headerValue = headerValueForVary(request, varyingRequestHeader.first);166 if (headerValue != varyingRequestHeader.second)167 return false;168 }169 return true;170 }171 172 131 static bool cachePolicyAllowsExpired(WebCore::ResourceRequestCachePolicy policy) 173 132 { … … 222 181 return UseDecision::Validate; 223 182 224 if (! verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request))183 if (!WebCore::verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request)) 225 184 return UseDecision::NoDueToVaryingHeaderMismatch; 226 185 … … 375 334 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) 376 335 if (canUseSpeculativeRevalidation && m_speculativeLoadManager->retrieve(frameID, storageKey, request, [request, completionHandler](std::unique_ptr<Entry> entry) { 377 if (entry && verifyVaryingRequestHeaders(entry->varyingRequestHeaders(), request))336 if (entry && WebCore::verifyVaryingRequestHeaders(entry->varyingRequestHeaders(), request)) 378 337 completionHandler(WTFMove(entry)); 379 338 else … … 448 407 } 449 408 450 auto cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, WTFMove(responseData), collectVaryingRequestHeaders(request, response));409 auto cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, WTFMove(responseData), WebCore::collectVaryingRequestHeaders(request, response)); 451 410 auto record = cacheEntry->encodeAsStorageRecord(); 452 411 … … 483 442 } 484 443 485 std::unique_ptr<Entry> cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, redirectRequest, collectVaryingRequestHeaders(request, response));444 std::unique_ptr<Entry> cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, redirectRequest, WebCore::collectVaryingRequestHeaders(request, response)); 486 445 487 446 auto record = cacheEntry->encodeAsStorageRecord(); … … 499 458 WebCore::updateResponseHeadersAfterRevalidation(response, validatingResponse); 500 459 501 auto updateEntry = std::make_unique<Entry>(existingEntry.key(), response, existingEntry.buffer(), collectVaryingRequestHeaders(originalRequest, response));460 auto updateEntry = std::make_unique<Entry>(existingEntry.key(), response, existingEntry.buffer(), WebCore::collectVaryingRequestHeaders(originalRequest, response)); 502 461 auto updateRecord = updateEntry->encodeAsStorageRecord(); 503 462
Note: See TracChangeset
for help on using the changeset viewer.