Skip to content

Commit 2b732b9

Browse files
committed
Implement speculation rules - same origin conservative prefetch
https://bugs.webkit.org/show_bug.cgi?id=295193 Reviewed by NOBODY (OOPS!). This implements an initial version of same-origin prefetch speculation rules. The feature enables prefetching an HTML document ahead of time ("immediate" eagerness), or when the user started clicking an anchor element pointing at it ("conservative" eagerness). That prefetched document is then used when the user actually navigates to this URL, resulting in significant performance improvements. Subresources of the prefetched document are not yet loaded before navigation, nor does it begin its processing. HTML spec PR for speculation rules: whatwg/html#11426 Spec for the prefetch parts: https://wicg.github.io/nav-speculation/prefetch.html * LayoutTests/TestExpectations: Add a few failing expectations. * LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/clear-site-data-cache.py: Added. (generate_png): (generate_png.chunk): (main): * LayoutTests/imported/w3c/web-platform-tests/clear-site-data/support/clear-site-data-prefetchCache.py: Added. (main): * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/external-speculation-rules-errors-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/invalid-rules.https_prefetch-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/invalid-rules.https_prerender-expected.txt: Progression * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/anonymous-client.https-expected.txt: Failure instead of timeout. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/clear-prefetch-cache-after-clear-site-data-cache.https-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=changed-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=changedWithRedirect-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=changedWithRedirect2-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=changedWithRedirect3-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=unchanged-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cookie-indices.https_include=unchangedWithRedirect-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cross-origin-cookies-anonymous-client-ip-duplicate.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/cross-origin-cookies.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/different-initiators-2.https-expected.txt: Timeout. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/different-initiators.sub.https_cross-site-1-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/different-initiators.sub.https_cross-site-2-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/different-initiators.sub.https_same-site-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=and-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=baseURLChangedByBaseElement-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=baseURLChangedBySameDocumentNavigation-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=defaultPredicate-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=hrefMatches-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=immediateMutation-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=invalidPredicate-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=linkHrefChanged-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=linkInShadowTree-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=linkToSelfFragment-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=newRuleSetAdded-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=not-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=or-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=selectorMatches-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=selectorMatchesDisplayLocked-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=selectorMatchesDisplayNone-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=selectorMatchesScopingRoot-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/document-rules.https_include=unslottedLink-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/duplicate-urls.https-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/fragment.https-expected.txt: Progrssion. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/implicit-source.https-expected.txt: Progrssion. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-a-element.sub.https_cross-site-expected.txt: Progrsssion (partial failure). * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-a-element.sub.https_same-site-expected.txt: Progrsssion (partial failure). * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-iframe-location-href.sub.https_cross-site-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-iframe-location-href.sub.https_same-site-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-window-open.sub.https_cross-site-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-window-open.sub.https_same-site-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/multiple-url.https-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-delivery-type.https_prefetch=false&bypass_cache=false-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-delivery-type.https_prefetch=false&bypass_cache=true-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-delivery-type.https_prefetch=true&bypass_cache=false-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-delivery-type.https_prefetch=true&bypass_cache=true-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https_include=afterResponse-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https_include=noPrefetch-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https_include=waitingForRedirect-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https_include=waitingForResponse-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-sizes.https_bypass_cache=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-sizes.https_default-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-sizes.https_prefetch=true&bypass_cache=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-sizes.https_prefetch=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/no-http-cache-interference.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/no-prefetch-for-post.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=BaseCase-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=CSPExemption-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=EmptyRuleSet-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=FailCORS-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=FailToParseRuleSet-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=FailToParseSpeculationRulesHeader-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=FollowRedirect-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=InnerListInSpeculationRulesHeader-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=InvalidMimeType-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=InvalidUrlForSpeculationRulesSet-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=RelativeUrlForCandidate-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=RelativeUrlForSpeculationRulesSet-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=StatusCode199-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=StatusCode404-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https_include=UseNonUTF8EncodingForSpeculationRulesSet-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-single.https_from_protocol=http&to_protocol=http-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-single.https_from_protocol=http&to_protocol=https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-single.https_from_protocol=https&to_protocol=http-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-single.https_from_protocol=https&to_protocol=https-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-status.https_status=200&should_prefetch=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-status.https_status=250&should_prefetch=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-status.https_status=299&should_prefetch=true-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-status.https_status=400&should_prefetch=false-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-status.https_status=500&should_prefetch=false-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-traverse-reload.sub-expected.txt: Progression (partial failure). * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-uses-cache.sub.https_cross-site-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-uses-cache.sub.https_same-site-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-middle-of-prefetch.https_origin=cross-site-initial-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-middle-of-prefetch.https_origin=cross-site-redirect-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-middle-of-prefetch.https_origin=same-origin-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-to-prefetch-url.https_origin=cross-site-initial-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-to-prefetch-url.https_origin=cross-site-redirect-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-to-prefetch-url.https_origin=same-origin-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-url.https_origin=cross-site-initial-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-url.https_origin=cross-site-redirect-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-url.https_origin=same-origin-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_1-1-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_2-2-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_3-3-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_4-4-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_5-5-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_6-6-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_7-7-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https_8-last-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-not-accepted.https_1-1-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-not-accepted.https_2-2-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-not-accepted.https_3-last-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy.https_1-1-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy.https_2-2-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy.https_3-3-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy.https_4-last-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/same-origin-cookies.https_1-1-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/same-origin-cookies.https_2-last-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/sec-fetch-headers.https-expected.txt: Progression (partial failure). * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/user-pass.https_cross-origin=false-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/prefetch/user-pass.https_cross-origin=true-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/script-supports.https-expected.txt: Progression. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/cross-site-prefetch.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/cross-site-to-same-site-redirection-prefetch.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/deduped-and-sorted-tags.https_type=prefetch-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/deduped-and-sorted-tags.https_type=prerender-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/invalid-tags.https_tag-level=rule&type=prefetch-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/invalid-tags.https_tag-level=rule&type=prerender-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/invalid-tags.https_tag-level=ruleset&type=prefetch-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/invalid-tags.https_tag-level=ruleset&type=prerender-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/no-tags.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/prefetch-eagerness-pointer-down.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/prefetch-eagerness-pointer-hover.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/prerender-target-hint.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/same-site-to-cross-site-redirection-prefetch.https-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/valid-tags.https_tag-level=rule&type=prefetch-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/valid-tags.https_tag-level=rule&type=prerender-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/valid-tags.https_tag-level=ruleset&type=prefetch-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/speculation-rules/speculation-tags/valid-tags.https_tag-level=ruleset&type=prerender-expected.txt: Failure. * LayoutTests/imported/w3c/web-platform-tests/websockets/constants.sub.js: Updated. * LayoutTests/platform/gtk/TestExpectations: * LayoutTests/platform/mac-wk1/TestExpectations: Skip service-worker reliant tests. * LayoutTests/platform/wpe/TestExpectations: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: Add a preference to enable the feature. * Source/WebCore/Headers.cmake: Add new headers. * Source/WebCore/Sources.txt: Add new source files. * Source/WebCore/WebCore.xcodeproj/project.pbxproj: Add new files. * Source/WebCore/bindings/js/ScriptController.cpp: (WebCore::ScriptController::registerSpeculationRules): Parse and set new speculation rules. * Source/WebCore/bindings/js/ScriptController.h: * Source/WebCore/dom/Document.cpp: (WebCore::Document::Document): (WebCore::Document::resolveStyle): Call considerSpeculationRules. (WebCore::Document::updateBaseURL): Call considerSpeculationRules. (WebCore::Document::considerSpeculationRules): Check if speculation rules indicate we need to prefetch new documents. (WebCore::Document::speculationRules const): (WebCore::Document::speculationRules): (WebCore::Document::prefetch): Kick off a document prefetch. * Source/WebCore/dom/Document.h: * Source/WebCore/dom/ScriptElement.cpp: (WebCore::ScriptElement::determineScriptType): Add "speculationrules" as a script type. (WebCore::ScriptElement::prepareScript): Call registerSpeculationRules. (WebCore::ScriptElement::registerSpeculationRules): Register speculation rules for the document. * Source/WebCore/dom/ScriptElement.h: * Source/WebCore/dom/ScriptElementCachedScriptFetcher.h: (WebCore::ScriptElementCachedScriptFetcher::isSpeculationRules const): * Source/WebCore/dom/ScriptType.h: * Source/WebCore/dom/SpeculationRulesMatcher.cpp: Implements speculation rules matching. (WebCore::matches): Checks if a rule matches. (WebCore::SpeculationRulesMatcher::hasMatchingRule): Entry point that that checks if an anchor element should be prefetched. * Source/WebCore/dom/SpeculationRulesMatcher.h: * Source/WebCore/dom/TrustedTypePolicy.cpp: Unified build fix. * Source/WebCore/html/HTMLAnchorElement.cpp: Check if an anchor should be prefetched. (WebCore::HTMLAnchorElement::defaultEventHandler): Implements the "conservative" eagerness heuristic and prefetches matching anchors on keydown/pointerdown. (WebCore::HTMLAnchorElement::attributeChanged): Check speculation rules on attribute change. (WebCore::HTMLAnchorElement::insertedIntoAncestor): Check speculation rules on insertion. (WebCore::HTMLAnchorElement::setFullURL): Check speculation rules when the URL changes. (WebCore::HTMLAnchorElement::setShouldBePrefetched): Indicates that an anchor should be prefetched. (WebCore::HTMLAnchorElement::checkForSpeculationRules): Checks speculations rules and called setShouldBePrefetched. * Source/WebCore/html/HTMLAnchorElement.h: * Source/WebCore/html/HTMLScriptElement.h: Add "speculationrules" script type. * Source/WebCore/loader/DocumentLoader.cpp: (WebCore::DocumentLoader::loadMainResource): * Source/WebCore/loader/DocumentPrefetcher.cpp: Handle document prefetching. (WebCore::DocumentPrefetcher::DocumentPrefetcher): (WebCore::DocumentPrefetcher::~DocumentPrefetcher): (WebCore::isPassingSecurityChecks): Run security checks. (WebCore::makePrefetchRequest): Request the prefetched document. (WebCore::DocumentPrefetcher::prefetch): Prefetch the document if it passes all checks. (WebCore::DocumentPrefetcher::responseReceived): Implement responseReceived to run the completion handler. (WebCore::DocumentPrefetcher::redirectReceived): Handle redirect responses. (WebCore::DocumentPrefetcher::notifyFinished): Handle the resource finish notification. (WebCore::DocumentPrefetcher::clearPrefetchedAssets): Clear all the prefetched assets from this prefetcher. (WebCore::DocumentPrefetcher::clear): Clear the prefetcher. * Source/WebCore/loader/DocumentPrefetcher.h: (WebCore::DocumentPrefetcher::create): (WebCore::DocumentPrefetcher::isFinished const): (WebCore::DocumentPrefetcher::notifyWhenFinished): (WebCore::DocumentPrefetcher::isNotifyingWhenFinished const): * Source/WebCore/loader/FrameLoader.cpp: (WebCore::FrameLoader::FrameLoader): Initialize m_documentPrefetcher. (WebCore::FrameLoader::commitProvisionalLoad): (WebCore::FrameLoader::loadResourceSynchronously): (WebCore::FrameLoader::continueLoadAfterNavigationPolicy): Match navigation with a prefetched resource. (WebCore::FrameLoader::prefetch): Prefetch a document. * Source/WebCore/loader/FrameLoader.h: * Source/WebCore/loader/ResourceLoaderOptions.h: * Source/WebCore/loader/SpeculationRules.cpp: Added. (WebCore::SpeculationRules::create): (WebCore::SpeculationRules::prefetchRules const): (WebCore::SpeculationRules::DocumentPredicate::DocumentPredicate): (WebCore::SpeculationRules::DocumentPredicate::value const): (WebCore::parseStringOrStringList): (WebCore::parseDocumentPredicate): (WebCore::parseSingleRule): (WebCore::parseRules): (WebCore::SpeculationRules::parseSpeculationRules): * Source/WebCore/loader/SpeculationRules.h: Added. * Source/WebCore/loader/cache/CachedRawResource.cpp: (WebCore::shouldIgnoreHeaderForCacheReuse): * Source/WebCore/loader/cache/CachedResource.cpp: (WebCore::CachedResource::CachedResource): (WebCore::CachedResource::redirectReceived): (WebCore::CachedResource::addClientToSet): * Source/WebCore/loader/cache/CachedResource.h: (WebCore::CachedResource::allowsCaching const): * Source/WebCore/loader/cache/CachedResourceLoader.cpp: (WebCore::CachedResourceLoader::allowedByContentSecurityPolicy const): Add MainResource as an option. (WebCore::CachedResourceLoader::shouldUpdateCachedResourceWithCurrentRequest): (WebCore::isResourceSuitableForDirectReuse): (WebCore::CachedResourceLoader::updateCachedResourceWithCurrentRequest): (WebCore::mustReloadFromServiceWorkerOptions): (WebCore::CachedResourceLoader::determineRevalidationPolicy const): * Source/WebCore/loader/cache/CachedResourceRequest.h: (WebCore::CachedResourceRequest::allowsCaching const): * Source/WebCore/page/PerformanceResourceTiming.cpp: (WebCore::networkLoadTimeToDOMHighResTimeStamp): * Source/WebCore/platform/ReferrerPolicy.cpp: (WebCore::parseReferrerPolicy): Add SpeculationRules as a source for referrer policy. * Source/WebCore/platform/ReferrerPolicy.h: * Source/WebCore/platform/network/CacheValidation.cpp: (WebCore::updateRedirectChainStatus): * Source/WebCore/platform/network/CacheValidation.h: * Source/WebCore/platform/network/HTTPHeaderNames.in: Add Sec-Speculation-Tags. * Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm: (WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad):
1 parent 8f49115 commit 2b732b9

File tree

178 files changed

+1738
-300
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+1738
-300
lines changed

LayoutTests/TestExpectations

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,24 @@ imported/w3c/web-platform-tests/html/syntax/speculative-parsing/generated/docume
921921
imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-data-url.any.html [ Skip ]
922922
imported/w3c/web-platform-tests/workers/modules/dedicated-worker-import-data-url-cross-origin.html [ Skip ]
923923

924+
# This is failing because the navigationTiming timestamps are not correct.
925+
imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https.html?include=afterResponse [ Pass Failure ]
926+
imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https.html?include=waitingForRedirect [ Pass Failure ]
927+
imported/w3c/web-platform-tests/speculation-rules/prefetch/navigation-timing-requestStart-responseStart.https.html?include=waitingForResponse [ Pass Failure ]
928+
imported/w3c/web-platform-tests/speculation-rules/prefetch/referrer-policy-from-rules.https.html?3-3 [ Pass Failure ]
929+
# This is passing, but timing out as `Clear-Site-Data: *` is making the test framework fail to get its own messages.
930+
imported/w3c/web-platform-tests/speculation-rules/prefetch/clear-prefetch-cache-after-clear-site-data-cache.https.html [ Skip ]
931+
# This is timing out because we do not support singleton prefetch matching, and the different initiators have different FrameLoaders.
932+
imported/w3c/web-platform-tests/speculation-rules/prefetch/different-initiators-2.https.html [ Skip ]
933+
# These tests output noisy console logs.
934+
imported/w3c/web-platform-tests/speculation-rules/prefetch/initiators-iframe-location-href.sub.https.html?cross-site [ DumpJSConsoleLogInStdErr ]
935+
imported/w3c/web-platform-tests/speculation-rules/prefetch/out-of-document-rule-set.https.html?include=CSPExemption [ DumpJSConsoleLogInStdErr ]
936+
imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-traverse-reload.sub.html [ DumpJSConsoleLogInStdErr ]
937+
imported/w3c/web-platform-tests/speculation-rules/prefetch/prefetch-uses-cache.sub.https.html?cross-site [ DumpJSConsoleLogInStdErr ]
938+
imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-middle-of-prefetch.https.html?origin=cross-site-initial [ DumpJSConsoleLogInStdErr ]
939+
imported/w3c/web-platform-tests/speculation-rules/prefetch/redirect-to-prefetch-url.https.html?origin=cross-site-initial [ DumpJSConsoleLogInStdErr ]
940+
941+
924942
# Newly imported WPT ref tests failures.
925943
imported/w3c/web-platform-tests/compat/webkit-box-fieldset.html [ ImageOnlyFailure ]
926944
imported/w3c/web-platform-tests/compat/webkit-box-rtl-flex.html [ ImageOnlyFailure ]
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
"""
2+
Loaded in Step 2/4/Optional 6 (/clear-site-data/clear-cache.https.html)
3+
Sending Message for Step 3/5/Optional 7 (/clear-site-data/clear-cache.https.html)
4+
"""
5+
import uuid
6+
import random
7+
8+
def generate_png(width, height, color=(0, 0, 0)):
9+
import zlib
10+
import struct
11+
def chunk(chunk_type, data):
12+
return (
13+
struct.pack(">I", len(data)) +
14+
chunk_type +
15+
data +
16+
struct.pack(">I", zlib.crc32(chunk_type + data) & 0xffffffff)
17+
)
18+
19+
# PNG signature
20+
png = b"\x89PNG\r\n\x1a\n"
21+
22+
# IHDR chunk
23+
ihdr = struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0)
24+
png += chunk(b'IHDR', ihdr)
25+
26+
# IDAT chunk: RGB pixels
27+
row = b'\x00' + bytes(color * width)
28+
raw = row * height
29+
idat = zlib.compress(raw)
30+
png += chunk(b'IDAT', idat)
31+
32+
# IEND chunk
33+
png += chunk(b'IEND', b'')
34+
return png
35+
36+
def main(request, response):
37+
# type of response:
38+
# - General purpose: returns random uuid or forwards uuid from iframe
39+
# - "single_html": Main page html file with a different postMessage uuid on each response
40+
# - Pages for simple testing normal http cache:
41+
# - "json": Json that always responds with a different uuid in a single-element array
42+
# - "html_embed_json": Main page html that embeds a cachable version of the above json
43+
# - Pages for testing specialized caches
44+
# - "image": Image that returns random dimensions up to 1024x1024 each time
45+
# - "html_embed_image": Main page html that embeds a cachable version of the above image
46+
# - "css": Style sheet with random uuid variable
47+
# - "html_embed_css": Main page html that embeds a cachable version of the above css
48+
# - "js": Script that returns a different uuid each time
49+
# - "html_embed_js": Main page html that embeds a cachable version of the above js file
50+
response_type = request.GET.first(b"response")
51+
52+
cache_helper = request.GET.first(b"cache_helper")
53+
54+
# force enable caching when present or force disable if not
55+
cache = b"cache" in request.GET
56+
clear = None
57+
if b"clear" in request.GET:
58+
clear = request.GET.first(b"clear")
59+
if b"clear_first" in request.GET:
60+
if request.server.stash.take(cache_helper) is None:
61+
clear = request.GET.first(b"clear_first")
62+
request.server.stash.put(cache_helper, ())
63+
64+
headers = []
65+
if response_type == b"json":
66+
headers += [(b"Content-Type", b"application/json")]
67+
elif response_type == b"image":
68+
headers += [(b"Content-Type", b"image/png")]
69+
elif response_type == b"css":
70+
headers += [(b"Content-Type", b"text/css")]
71+
elif response_type == b"js":
72+
headers += [(b"Content-Type", b"text/javascript")]
73+
else:
74+
headers += [(b"Content-Type", b"text/html")]
75+
76+
headers += [(b"Access-Control-Allow-Origin", b"*")]
77+
if cache:
78+
headers += [(b"cache-control", b"public, max-age=31536000, immutable")]
79+
else:
80+
headers += [(b"cache-control", b"no-store")]
81+
82+
if clear is not None:
83+
if clear == b"all":
84+
headers += [(b"Clear-Site-Data", b'"*"')]
85+
else:
86+
headers += [(b"Clear-Site-Data", b'"' + clear + b'"')]
87+
88+
if response_type == b"single_html":
89+
iframe = ""
90+
if b"iframe" in request.GET:
91+
# forward message from iframe to opener
92+
iframe_url = request.GET.first(b"iframe").decode()
93+
content = f'''
94+
<script>
95+
// forward iframe uuid to opener
96+
window.addEventListener('message', function(event) {{
97+
if(window.opener) {{
98+
window.opener.postMessage(event.data, "*");
99+
}} else {{
100+
window.parent.postMessage(event.data, "*");
101+
}}
102+
window.close();
103+
}});
104+
</script>
105+
<br>
106+
{request.url}<br>
107+
{iframe_url}<br>
108+
<iframe src="{iframe_url}"></iframe>
109+
</body>
110+
'''
111+
else:
112+
# send unique UUID. Cache got cleared when uuids don't match.
113+
u = uuid.uuid4()
114+
content = f'''
115+
<script>
116+
if(window.opener) {{
117+
window.opener.postMessage("{u}", "*");
118+
}} else {{
119+
window.parent.postMessage("{u}", "*");
120+
}}
121+
window.close();
122+
</script>
123+
<body>
124+
{request.url}
125+
</body>'''
126+
elif response_type == b"json":
127+
# send unique UUID. helper for below "html_embed_json"
128+
content = f'''["{uuid.uuid4()}"]'''
129+
elif response_type == b"html_embed_json":
130+
url = request.url_parts.path + "?response=json&cache&cache_helper=" + cache_helper.decode()
131+
content = f'''
132+
<script>
133+
fetch("{url}")
134+
.then(response => response.json())
135+
.then(uuid => {{
136+
window.opener.postMessage(uuid[0], "*");
137+
window.close();
138+
}});
139+
</script>
140+
<body>
141+
{request.url}<br>
142+
{url}
143+
</body>'''
144+
elif response_type == b"image":
145+
# send uniquely sized images, because that info can be retrived from html and definitly using the image cache
146+
# helper for below "html_embed_image"
147+
content = generate_png(random.randint(1, 1024), random.randint(1, 1024))
148+
elif response_type == b"html_embed_image":
149+
urls = [request.url_parts.path + "?response=image&cache&cache_helper=" + cache_helper.decode() + "&img=" + str(i) for i in range(2)]
150+
content = f'''
151+
<!DOCTYPE html>
152+
<script>
153+
addEventListener("load", () => {{
154+
let img1 = document.getElementById("randomess1");
155+
let img2 = document.getElementById("randomess2");
156+
let id = img1.naturalWidth + "x" + img1.naturalHeight;
157+
id += "-" + img2.naturalWidth + "x" + img2.naturalHeight
158+
window.opener.postMessage(id, "*");
159+
window.close();
160+
}})
161+
</script>
162+
<body>
163+
{request.url}<br>
164+
<img id="randomess1" src="{urls[0]}"></img><br>
165+
<img id="randomess2" src="{urls[1]}"></img><br>
166+
</body>'''
167+
elif response_type == b"css":
168+
# send unique UUID. helper for below "html_embed_css"
169+
content = f'''
170+
:root {{
171+
--uuid: "{uuid.uuid4()}"
172+
}}'''
173+
elif response_type == b"html_embed_css":
174+
url = request.url_parts.path + "?response=css&cache&cache_helper=" + cache_helper.decode()
175+
content = f'''
176+
<!DOCTYPE html>
177+
<link rel="stylesheet" href="{url}">
178+
<script>
179+
let computed = getComputedStyle(document.documentElement);
180+
let uuid = computed.getPropertyValue("--uuid").trim().replaceAll('"', '');
181+
window.opener.postMessage(uuid, "*");
182+
window.close();
183+
</script>
184+
<body>
185+
{request.url}<br>
186+
{url}
187+
</body>'''
188+
elif response_type == b"js":
189+
# send unique UUID. helper for below "html_embed_js"
190+
content = f'''
191+
window.opener.postMessage("{uuid.uuid4()}", "*");
192+
window.close();
193+
'''
194+
elif response_type == b"html_embed_js":
195+
url = request.url_parts.path + "?response=js&cache&cache_helper=" + cache_helper.decode()
196+
content = f'''
197+
<script src="{url}"></script>
198+
<body>
199+
{request.url}<br>
200+
{url}
201+
</body>'''
202+
203+
return 200, headers, content
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
def main(request, response):
2+
headers = [(b"Content-Type", b"text/html")]
3+
headers += [(b"Clear-Site-Data", b'"prefetchCache"')]
4+
content = f'''
5+
<script>
6+
setTimeout(() => {{
7+
if(window.opener) {{
8+
window.opener.postMessage("message", "*");
9+
}} else {{
10+
window.parent.postMessage("message", "*");
11+
}}
12+
window.close();
13+
}}, 1000);
14+
</script>
15+
<body>
16+
{request.url}
17+
</body>'''
18+
return 200, headers, content
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11

2-
Harness Error (TIMEOUT), message = null
3-
4-
TIMEOUT Test that an external speculation rules script fires an error event Test timed out
5-
NOTRUN Test that an external speculation rules script fires an error event, regardless of attribute order
6-
NOTRUN Test that an external speculation rules script in markup fires an error event
2+
PASS Test that an external speculation rules script fires an error event
3+
PASS Test that an external speculation rules script fires an error event, regardless of attribute order
4+
PASS Test that an external speculation rules script in markup fires an error event
75

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11

2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
3-
2+
PASS an unrecognized key in a prefetch rule should prevent it from being preloaded
43

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11

2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
3-
2+
PASS an unrecognized key in a prerender rule should prevent it from being preloaded
43

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
CONSOLE MESSAGE: Prefetch request denied: not same origin as document
2+
CONSOLE MESSAGE: Prefetch request denied: not same origin as document
13

2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
3-
4+
FAIL test anonymous-client url prefetch for cross origin pages assert_equals: expected (string) "prefetch;anonymous-client-ip" but got (undefined) undefined
45

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
1+
CONSOLE MESSAGE: Fetch API cannot load https://localhost:9443/common/dispatcher/dispatcher.py?uuid=2f958f30-2590-4c7f-8c48-2d27061bc962 due to access control checks.
2+
CONSOLE MESSAGE: Fetch API cannot load https://localhost:9443/common/dispatcher/dispatcher.py?uuid=2aa4c567-6ca0-45a6-96d8-6846ef6822c6 due to access control checks.
3+
CONSOLE MESSAGE: Fetch API cannot load https://localhost:9443/common/dispatcher/dispatcher.py?uuid=2f958f30-2590-4c7f-8c48-2d27061bc962 due to access control checks.
4+
CONSOLE MESSAGE: Fetch API cannot load https://localhost:9443/common/dispatcher/dispatcher.py?uuid=11e644f8-fb6a-4c3c-9266-91c4978d8e0b due to access control checks.
5+
CONSOLE MESSAGE: Fetch API cannot load https://localhost:9443/common/dispatcher/dispatcher.py?uuid=2f958f30-2590-4c7f-8c48-2d27061bc962 due to access control checks.
6+
FAIL: Timed out waiting for notifyDone to be called
37

48

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11

2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
3-
2+
PASS Cookie-Indices should prevent a prefetch from being used if the cookie has changed.
43

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11

2-
Harness Error (FAIL), message = Error: assert_implements: <script type="speculationrules"> must be supported undefined
3-
2+
FAIL Cookie-Indices should prevent a prefetch from succeeding if the cookie changed, with a redirect assert_equals: expected (undefined) undefined but got (string) "prefetch"
43

0 commit comments

Comments
 (0)