Changeset 252778 in webkit
- Timestamp:
- Nov 22, 2019 9:25:29 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r252774 r252778 1 2019-11-22 Chris Dumez <cdumez@apple.com> 2 3 Speculative loading sometimes happens too early and is missing login cookies 4 https://bugs.webkit.org/show_bug.cgi?id=204305 5 <rdar://problem/57063840> 6 7 Reviewed by Antti Koivisto. 8 9 Extend layout test coverage to make sure that the validation request contains the latest cookies 10 set by the main resource. 11 12 * http/tests/cache/disk-cache/speculative-validation/resources/validation-request-frame.php: 13 * http/tests/cache/disk-cache/speculative-validation/validation-request-expected.txt: 14 * http/tests/cache/disk-cache/speculative-validation/validation-request.html: 15 1 16 2019-11-22 Per Arne Vollan <pvollan@apple.com> 2 17 -
trunk/LayoutTests/http/tests/cache/disk-cache/speculative-validation/resources/validation-request-frame.php
r198450 r252778 3 3 header('Cache-Control: max-age=0'); 4 4 header('Etag: 123456789'); 5 5 $cookie = "speculativeRequestValidation=" . uniqid(); 6 header('Set-Cookie: ' . $cookie); 6 7 ?> 7 8 <!DOCTYPE html> 8 9 <body> 9 10 <script src="request-headers-script.php"></script> 11 <script> 12 <?php 13 echo "sentSetCookieHeader = '" . $cookie . "';"; 14 ?> 15 </script> 10 16 </body> -
trunk/LayoutTests/http/tests/cache/disk-cache/speculative-validation/validation-request-expected.txt
r198741 r252778 5 5 6 6 PASS validationRequestHeader('If-None-Match') is "123456789" 7 PASS isCookieHeaderCorrect is true 7 8 PASS validationRequestHeader('Accept') is initialHeaderValues['Accept'] 8 9 PASS validationRequestHeader('Accept-Encoding') is initialHeaderValues['Accept-Encoding'] -
trunk/LayoutTests/http/tests/cache/disk-cache/speculative-validation/validation-request.html
r198741 r252778 38 38 // Validate the HTTP headers of the speculative validation request. 39 39 shouldBeEqualToString("validationRequestHeader('If-None-Match')", "123456789"); 40 isCookieHeaderCorrect = validationRequestHeader('Cookie') === document.getElementById("testFrame").contentWindow.sentSetCookieHeader; 41 shouldBeTrue("isCookieHeaderCorrect"); 40 42 41 43 for (var i = 0; i < headersToCheck.length; i++) { -
trunk/Source/WebKit/ChangeLog
r252770 r252778 1 2019-11-22 Chris Dumez <cdumez@apple.com> 2 3 Speculative loading sometimes happens too early and is missing login cookies 4 https://bugs.webkit.org/show_bug.cgi?id=204305 5 <rdar://problem/57063840> 6 7 Reviewed by Antti Koivisto. 8 9 Speculative loads were issued before receiving the response from the main resource. However, 10 the main resource may set important cookies that are thus missing from the speculative requests. 11 12 To address the issue we now delay speculative loads for first-party subresources until we've 13 received the response from the main resource. To avoid regressing PLT, we still warm up the 14 first-party subresources from disk right away and preconnect to the server. 15 16 No new tests, extended existing test. 17 18 * NetworkProcess/NetworkResourceLoader.cpp: 19 (WebKit::NetworkResourceLoader::didReceiveResponse): 20 (WebKit::NetworkResourceLoader::didReceiveMainResourceResponse): 21 (WebKit::NetworkResourceLoader::didRetrieveCacheEntry): 22 * NetworkProcess/NetworkResourceLoader.h: 23 * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp: 24 (WebKit::NetworkCache::SpeculativeLoadManager::PendingFrameLoad::didReceiveMainResourceResponse const): 25 (WebKit::NetworkCache::SpeculativeLoadManager::PendingFrameLoad::markMainResourceResponseAsReceived): 26 (WebKit::NetworkCache::SpeculativeLoadManager::PendingFrameLoad::addPostMainResourceResponseTask): 27 (WebKit::NetworkCache::SpeculativeLoadManager::shouldRegisterLoad): 28 (WebKit::NetworkCache::SpeculativeLoadManager::registerLoad): 29 (WebKit::NetworkCache::SpeculativeLoadManager::registerMainResourceLoadResponse): 30 (WebKit::NetworkCache::SpeculativeLoadManager::preconnectForSubresource): 31 (WebKit::NetworkCache::SpeculativeLoadManager::revalidateSubresource): 32 * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.h: 33 * NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp: 34 (WebKit::NetworkCache::SubresourceInfo::isFirstParty const): 35 * NetworkProcess/cache/NetworkCacheSubresourcesEntry.h: 36 1 37 2019-11-22 Carlos Garcia Campos <cgarcia@igalia.com> 2 38 -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
r252510 r252778 31 31 #include "Logging.h" 32 32 #include "NetworkCache.h" 33 #include "NetworkCacheSpeculativeLoadManager.h" 33 34 #include "NetworkConnectionToWebProcess.h" 34 35 #include "NetworkConnectionToWebProcessMessages.h" … … 467 468 RELEASE_LOG_IF_ALLOWED("didReceiveResponse: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", httpStatusCode = %d, length = %" PRId64 ")", m_parameters.webPageID.toUInt64(), m_parameters.webFrameID.toUInt64(), m_parameters.identifier, receivedResponse.httpStatusCode(), receivedResponse.expectedContentLength()); 468 469 470 if (isMainResource()) 471 didReceiveMainResourceResponse(receivedResponse); 472 469 473 m_response = WTFMove(receivedResponse); 470 474 … … 901 905 } 902 906 907 void NetworkResourceLoader::didReceiveMainResourceResponse(const WebCore::ResourceResponse& response) 908 { 909 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) 910 if (auto* speculativeLoadManager = m_cache ? m_cache->speculativeLoadManager() : nullptr) 911 speculativeLoadManager->registerMainResourceLoadResponse(globalFrameID(), originalRequest(), response); 912 #endif 913 } 914 903 915 void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) 904 916 { 905 917 auto response = entry->response(); 918 919 if (isMainResource()) 920 didReceiveMainResourceResponse(response); 906 921 907 922 if (isMainResource() && shouldInterruptLoadForCSPFrameAncestorsOrXFrameOptions(response)) { -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h
r251445 r252778 156 156 void restartNetworkLoad(WebCore::ResourceRequest&&); 157 157 void continueDidReceiveResponse(); 158 void didReceiveMainResourceResponse(const WebCore::ResourceResponse&); 158 159 159 160 enum class LoadResult { -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp
r252397 r252778 34 34 #include "NetworkCacheSubresourcesEntry.h" 35 35 #include "NetworkProcess.h" 36 #include "PreconnectTask.h" 36 37 #include <WebCore/DiagnosticLoggingKeys.h> 37 38 #include <pal/HysteresisActivity.h> … … 204 205 } 205 206 207 bool didReceiveMainResourceResponse() const { return m_didReceiveMainResourceResponse; } 208 void markMainResourceResponseAsReceived() 209 { 210 m_didReceiveMainResourceResponse = true; 211 for (auto& task : m_postMainResourceResponseTasks) 212 task(); 213 } 214 215 void addPostMainResourceResponseTask(Function<void()>&& task) { m_postMainResourceResponseTasks.append(WTFMove(task)); } 216 206 217 private: 207 218 PendingFrameLoad(Storage& storage, const Key& mainResourceKey, WTF::Function<void()>&& loadCompletionHandler) … … 243 254 PAL::HysteresisActivity m_loadHysteresisActivity; 244 255 std::unique_ptr<SubresourcesEntry> m_existingEntry; 256 Vector<Function<void()>> m_postMainResourceResponseTasks; 245 257 bool m_didFinishLoad { false }; 246 258 bool m_didRetrieveExistingEntry { false }; 259 bool m_didReceiveMainResourceResponse { false }; 247 260 }; 248 261 … … 324 337 } 325 338 339 bool SpeculativeLoadManager::shouldRegisterLoad(const WebCore::ResourceRequest& request) 340 { 341 if (request.httpMethod() != "GET") 342 return false; 343 if (!request.httpHeaderField(HTTPHeaderName::Range).isEmpty()) 344 return false; 345 return true; 346 } 347 326 348 void SpeculativeLoadManager::registerLoad(const GlobalFrameID& frameID, const ResourceRequest& request, const Key& resourceKey) 327 349 { … … 329 351 ASSERT(request.url().protocolIsInHTTPFamily()); 330 352 331 if (request.httpMethod() != "GET") 332 return; 333 if (!request.httpHeaderField(HTTPHeaderName::Range).isEmpty()) 353 if (!shouldRegisterLoad(request)) 334 354 return; 335 355 … … 361 381 if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameID)) 362 382 pendingFrameLoad->registerSubresourceLoad(request, resourceKey); 383 } 384 385 void SpeculativeLoadManager::registerMainResourceLoadResponse(const GlobalFrameID& frameID, const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response) 386 { 387 if (!shouldRegisterLoad(request)) 388 return; 389 390 if (response.isRedirection()) 391 return; 392 393 if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameID)) 394 pendingFrameLoad->markMainResourceResponseAsReceived(); 363 395 } 364 396 … … 418 450 } 419 451 452 void SpeculativeLoadManager::preconnectForSubresource(const SubresourceInfo& subresourceInfo, Entry* entry, const GlobalFrameID& frameID) 453 { 454 #if ENABLE(SERVER_PRECONNECT) 455 NetworkLoadParameters parameters; 456 parameters.webPageProxyID = frameID.webPageProxyID; 457 parameters.webPageID = frameID.webPageID; 458 parameters.webFrameID = frameID.frameID; 459 parameters.storedCredentialsPolicy = StoredCredentialsPolicy::Use; 460 parameters.contentSniffingPolicy = ContentSniffingPolicy::DoNotSniffContent; 461 parameters.contentEncodingSniffingPolicy = ContentEncodingSniffingPolicy::Sniff; 462 parameters.shouldPreconnectOnly = PreconnectOnly::Yes; 463 parameters.request = constructRevalidationRequest(subresourceInfo.key(), subresourceInfo, entry); 464 new PreconnectTask(m_cache.networkProcess(), m_cache.sessionID(), WTFMove(parameters), [](const WebCore::ResourceError&) { }); 465 #else 466 UNUSED_PARAM(subresourceInfo); 467 UNUSED_PARAM(entry); 468 UNUSED_PARAM(frameID); 469 #endif 470 } 471 420 472 void SpeculativeLoadManager::revalidateSubresource(const SubresourceInfo& subresourceInfo, std::unique_ptr<Entry> entry, const GlobalFrameID& frameID) 421 473 { … … 427 479 if (!key.range().isEmpty()) 428 480 return; 481 482 auto* pendingLoad = m_pendingFrameLoads.get(frameID); 483 484 // Delay first-party speculative loads until we've received the response for the main resource, in case the main resource 485 // response sets cookies that are needed for subsequent loads. 486 if (pendingLoad && !pendingLoad->didReceiveMainResourceResponse() && subresourceInfo.isFirstParty()) { 487 preconnectForSubresource(subresourceInfo, entry.get(), frameID); 488 pendingLoad->addPostMainResourceResponseTask([this, subresourceInfo, entry = WTFMove(entry), frameID]() mutable { 489 revalidateSubresource(subresourceInfo, WTFMove(entry), frameID); 490 }); 491 return; 492 } 429 493 430 494 ResourceRequest revalidationRequest = constructRevalidationRequest(key, subresourceInfo, entry.get()); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.h
r239427 r252778 51 51 52 52 void registerLoad(const GlobalFrameID&, const WebCore::ResourceRequest&, const Key& resourceKey); 53 void registerMainResourceLoadResponse(const GlobalFrameID&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); 53 54 54 55 typedef Function<void (std::unique_ptr<Entry>)> RetrieveCompletionHandler; … … 60 61 class PreloadedEntry; 61 62 63 static bool shouldRegisterLoad(const WebCore::ResourceRequest&); 62 64 void addPreloadedEntry(std::unique_ptr<Entry>, const GlobalFrameID&, Optional<WebCore::ResourceRequest>&& revalidationRequest = WTF::nullopt); 63 65 void preloadEntry(const Key&, const SubresourceInfo&, const GlobalFrameID&); 64 66 void retrieveEntryFromStorage(const SubresourceInfo&, RetrieveCompletionHandler&&); 65 67 void revalidateSubresource(const SubresourceInfo&, std::unique_ptr<Entry>, const GlobalFrameID&); 68 void preconnectForSubresource(const SubresourceInfo&, Entry*, const GlobalFrameID&); 66 69 bool satisfyPendingRequests(const Key&, Entry*); 67 70 void retrieveSubresourcesEntry(const Key& storageKey, WTF::Function<void (std::unique_ptr<SubresourcesEntry>)>&&); -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp
r248846 r252778 80 80 81 81 return true; 82 } 83 84 bool SubresourceInfo::isFirstParty() const 85 { 86 RegistrableDomain firstPartyDomain { m_firstPartyForCookies }; 87 return firstPartyDomain.matches(URL(URL(), key().identifier())); 82 88 } 83 89 -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h
r238771 r252778 59 59 void setNonTransient() { m_isTransient = false; } 60 60 61 bool isFirstParty() const; 62 61 63 private: 62 64 Key m_key;
Note: See TracChangeset
for help on using the changeset viewer.