#include "third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/types/strong_alias.h"
#include "services/network/public/mojom/no_vary_search.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-blink.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_urlpatterninit_usvstring.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
#include "third_party/blink/renderer/core/html/html_area_element.h"
#include "third_party/blink/renderer/core/html/html_base_element.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_meta_element.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h"
#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h"
#include "third_party/blink/renderer/core/speculation_rules/speculation_rules_metrics.h"
#include "third_party/blink/renderer/core/speculation_rules/stub_speculation_host.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/core/url_pattern/url_pattern.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/task_environment.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
namespace {
AllOf;
ElementsAre;
Not;
PrintToString;
class ListRuleMatcher { … };
class URLPatternMatcher { … };
template <typename... Matchers>
auto MatchesListOfURLs(Matchers&&... matchers) { … }
MATCHER(RequiresAnonymousClientIPWhenCrossOrigin,
negation ? "doesn't require anonymous client IP when cross origin"
: "requires anonymous client IP when cross origin") { … }
MATCHER(SetsReferrerPolicy,
std::string(negation ? "doesn't set" : "sets") + " a referrer policy") { … }
MATCHER_P(ReferrerPolicyIs,
policy,
std::string(negation ? "doesn't have" : "has") + " " +
PrintToString(policy) + " as the referrer policy") { … }
class SpeculationRuleSetTest : public ::testing::Test { … };
template <typename... Matchers>
auto HasURLs(Matchers&&... urls) { … }
auto HasEagerness(
::testing::Matcher<blink::mojom::SpeculationEagerness> matcher) { … }
auto HasURL(::testing::Matcher<KURL> matcher) { … }
auto HasAction(::testing::Matcher<mojom::blink::SpeculationAction> matcher) { … }
auto HasTargetHint(
::testing::Matcher<mojom::blink::SpeculationTargetHint> matcher) { … }
auto HasReferrerPolicy(
::testing::Matcher<network::mojom::ReferrerPolicy> matcher) { … }
auto HasNoVarySearchHint() { … }
auto NVSVariesOnKeyOrder() { … }
template <typename... Matchers>
auto NVSHasNoVaryParams(Matchers&&... params) { … }
TEST_F(SpeculationRuleSetTest, Empty) { … }
void AssertParseError(const SpeculationRuleSet* rule_set) { … }
TEST_F(SpeculationRuleSetTest, RejectsInvalidJSON) { … }
TEST_F(SpeculationRuleSetTest, RejectsNonObject) { … }
TEST_F(SpeculationRuleSetTest, RejectsComments) { … }
TEST_F(SpeculationRuleSetTest, SimplePrefetchRule) { … }
TEST_F(SpeculationRuleSetTest, SimplePrerenderRule) { … }
TEST_F(SpeculationRuleSetTest, SimplePrefetchWithSubresourcesRule) { … }
TEST_F(SpeculationRuleSetTest, ResolvesURLs) { … }
TEST_F(SpeculationRuleSetTest, ResolvesURLsWithRelativeTo) { … }
TEST_F(SpeculationRuleSetTest, RequiresAnonymousClientIPWhenCrossOrigin) { … }
TEST_F(SpeculationRuleSetTest, IgnoresUnknownOrDifferentlyTypedTopLevelKeys) { … }
TEST_F(SpeculationRuleSetTest, DropUnrecognizedRules) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_Blank) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_Self) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_Parent) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_Top) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_EmptyString) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_ValidBrowsingContextName) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_InvalidBrowsingContextName) { … }
TEST_F(SpeculationRuleSetTest, RulesWithTargetHint_CaseInsensitive) { … }
TEST_F(SpeculationRuleSetTest,
RulesWithRequiresAnonymousClientIpWhenCrossOrigin) { … }
TEST_F(SpeculationRuleSetTest, ReferrerPolicy) { … }
TEST_F(SpeculationRuleSetTest, EmptyReferrerPolicy) { … }
TEST_F(SpeculationRuleSetTest, PropagatesToDocument) { … }
HTMLScriptElement* InsertSpeculationRules(Document& document,
const String& speculation_script) { … }
IncludesStyleUpdate;
template <typename F>
void PropagateRulesToStubSpeculationHost(
DummyPageHolder& page_holder,
StubSpeculationHost& speculation_host,
const F& functor,
IncludesStyleUpdate includes_style_update = IncludesStyleUpdate{ … }
void PropagateRulesToStubSpeculationHost(DummyPageHolder& page_holder,
StubSpeculationHost& speculation_host,
const String& speculation_script) { … }
template <typename F>
testing::AssertionResult NoRulesPropagatedToStubSpeculationHost(
DummyPageHolder& page_holder,
StubSpeculationHost& speculation_host,
const F& functor,
IncludesStyleUpdate includes_style_update = IncludesStyleUpdate{ … }
TEST_F(SpeculationRuleSetTest, PropagatesAllRulesToBrowser) { … }
TEST_F(SpeculationRuleSetTest, PrerenderIgnorePrefetchRules) { … }
TEST_F(SpeculationRuleSetTest, PrefetchIgnorePrerenderRules) { … }
TEST_F(SpeculationRuleSetTest, UseCounter) { … }
TEST_F(SpeculationRuleSetTest, NoVarySearchHintUseCounter) { … }
TEST_F(SpeculationRuleSetTest, ExcludesFragmentLinks) { … }
TEST_F(SpeculationRuleSetTest, ExcludesFragmentLinksWithBase) { … }
TEST_F(SpeculationRuleSetTest, AddAndRemoveInSameTask) { … }
TEST_F(SpeculationRuleSetTest, AddAndRemoveAfterReport) { … }
TEST_F(SpeculationRuleSetTest, RemoveInMicrotask) { … }
class ConsoleCapturingChromeClient : public EmptyChromeClient { … };
TEST_F(SpeculationRuleSetTest, ConsoleWarning) { … }
TEST_F(SpeculationRuleSetTest, ConsoleWarningForInvalidRule) { … }
TEST_F(SpeculationRuleSetTest, ConsoleWarningForSetInnerHTML) { … }
TEST_F(SpeculationRuleSetTest, ConsoleWarningForChildModification) { … }
TEST_F(SpeculationRuleSetTest, ConsoleWarningForDuplicateKey) { … }
TEST_F(SpeculationRuleSetTest, DropNotArrayAtRuleSetPosition) { … }
TEST_F(SpeculationRuleSetTest, DropNotObjectAtRulePosition) { … }
MATCHER_P(MatchesPredicate,
matcher,
::testing::DescribeMatcher<DocumentRulePredicate>(matcher)) { … }
String GetTypeString(DocumentRulePredicate::Type type) { … }
template <typename ItemType>
class PredicateMatcher { … };
template <typename ItemType>
auto MakePredicateMatcher(
Vector<::testing::Matcher<ItemType>> matchers,
DocumentRulePredicate::Type type,
typename PredicateMatcher<ItemType>::DocumentRulePredicateGetter getter) { … }
auto MakeConditionMatcher(
Vector<::testing::Matcher<DocumentRulePredicate>> matchers,
DocumentRulePredicate::Type type) { … }
auto And(Vector<::testing::Matcher<DocumentRulePredicate>> matchers = { … }
auto Or(Vector<::testing::Matcher<DocumentRulePredicate>> matchers = { … }
auto Neg(::testing::Matcher<DocumentRulePredicate> matcher) { … }
auto Href(Vector<::testing::Matcher<URLPattern>> pattern_matchers = { … }
auto Selector(Vector<::testing::Matcher<StyleRule>> style_rule_matchers = { … }
class StyleRuleMatcher { … };
auto StyleRuleWithSelectorText(String selector_text) { … }
class DocumentRulesTest : public SpeculationRuleSetTest { … };
TEST_F(DocumentRulesTest, ParseAnd) { … }
TEST_F(DocumentRulesTest, ParseOr) { … }
TEST_F(DocumentRulesTest, ParseNot) { … }
TEST_F(DocumentRulesTest, ParseHref) { … }
TEST_F(DocumentRulesTest, ParseHref_AllUrlPatternKeys) { … }
TEST_F(DocumentRulesTest, HrefMatchesWithBaseURL) { … }
TEST_F(DocumentRulesTest, HrefMatchesWithBaseURLAndRelativeTo) { … }
TEST_F(DocumentRulesTest, DropInvalidRules) { … }
TEST_F(DocumentRulesTest, ConsoleWarningForInvalidRule) { … }
TEST_F(DocumentRulesTest, DocumentRuleParseErrors) { … }
TEST_F(DocumentRulesTest, DocumentRulePredicateParseErrors) { … }
TEST_F(DocumentRulesTest, DefaultPredicate) { … }
TEST_F(DocumentRulesTest, EvaluateCombinators) { … }
TEST_F(DocumentRulesTest, EvaluateHrefMatches) { … }
HTMLAnchorElement* AddAnchor(ContainerNode& parent, const String& href) { … }
HTMLAreaElement* AddAreaElement(ContainerNode& parent, const String& href) { … }
TEST_F(DocumentRulesTest, SpeculationCandidatesReportedAfterInitialization) { … }
TEST_F(DocumentRulesTest,
SpeculationCandidatesReportedAfterInitializationWithNVS) { … }
TEST_F(DocumentRulesTest, SpeculationCandidatesUpdatedAfterLinkModifications) { … }
TEST_F(DocumentRulesTest, SpeculationCandidatesUpdatedAfterRuleSetsChanged) { … }
TEST_F(DocumentRulesTest, ListRuleCombinedWithDocumentRule) { … }
TEST_F(DocumentRulesTest, RequiresAnonymousClientIPWhenCrossOrigin) { … }
TEST_F(DocumentRulesTest, LinkInShadowTreeIncluded) { … }
TEST_F(DocumentRulesTest, LinkWithNoHrefAttribute) { … }
TEST_F(DocumentRulesTest, LinkWithNonHttpHref) { … }
TEST_F(DocumentRulesTest, RemovingUnmatchedAndPendingLinks) { … }
TEST_F(DocumentRulesTest, AreaElement) { … }
TEST_F(DocumentRulesTest, DisconnectedLink) { … }
TEST_F(DocumentRulesTest, DisconnectedLinkInShadowTree) { … }
TEST_F(DocumentRulesTest, ReferrerPolicy) { … }
TEST_F(DocumentRulesTest, LinkReferrerPolicy) { … }
TEST_F(DocumentRulesTest, ReferrerPolicyAttributeChangeCausesLinkInvalidation) { … }
TEST_F(DocumentRulesTest, RelAttributeChangeCausesLinkInvalidation) { … }
TEST_F(DocumentRulesTest, ReferrerMetaChangeShouldInvalidateCandidates) { … }
TEST_F(DocumentRulesTest, BaseURLChanged) { … }
TEST_F(DocumentRulesTest, TargetHintFromLink) { … }
TEST_F(DocumentRulesTest, TargetHintFromSpeculationRuleOverridesLinkTarget) { … }
TEST_F(DocumentRulesTest, TargetHintFromLinkDynamic) { … }
TEST_F(DocumentRulesTest, ParseSelectorMatches) { … }
TEST_F(DocumentRulesTest, GetStyleRules) { … }
TEST_F(DocumentRulesTest, SelectorMatchesAddsCandidates) { … }
TEST_F(DocumentRulesTest, SelectorMatchesIsDynamic) { … }
TEST_F(DocumentRulesTest, AddingDocumentRulesInvalidatesStyle) { … }
TEST_F(DocumentRulesTest, BasicStyleInvalidation) { … }
TEST_F(DocumentRulesTest, IrrelevantDOMChangeShouldNotInvalidateCandidateList) { … }
TEST_F(DocumentRulesTest, SelectorMatchesInsideShadowTree) { … }
TEST_F(DocumentRulesTest, SelectorMatchesWithScopePseudoSelector) { … }
TEST_F(DocumentRulesTest, UpdateQueueingWithSelectorMatches_1) { … }
TEST_F(DocumentRulesTest, UpdateQueueingWithSelectorMatches_2) { … }
TEST_F(DocumentRulesTest, UpdateQueueingWithSelectorMatches_3) { … }
TEST_F(DocumentRulesTest, UpdateQueueingWithSelectorMatches_4) { … }
TEST_F(DocumentRulesTest, UpdateQueueingWithSelectorMatches_5) { … }
TEST_F(DocumentRulesTest, LinksWithoutComputedStyle) { … }
TEST_F(DocumentRulesTest, LinksWithoutComputedStyle_HrefMatches) { … }
TEST_F(DocumentRulesTest, LinkInsideDisplayLockedElement) { … }
TEST_F(DocumentRulesTest, LinkInsideNestedDisplayLockedElement) { … }
TEST_F(DocumentRulesTest, DisplayLockedLink) { … }
TEST_F(DocumentRulesTest, AddLinkToDisplayLockedContainer) { … }
TEST_F(DocumentRulesTest, DisplayLockedContainerTracking) { … }
TEST_F(DocumentRulesTest, RemoveForcesStyleUpdate) { … }
TEST_F(DocumentRulesTest, RemoveWhileWaitingForStyle) { … }
TEST_F(DocumentRulesTest, UniversalSelector) { … }
TEST_F(SpeculationRuleSetTest, Eagerness) { … }
TEST_F(SpeculationRuleSetTest, InvalidUseOfEagerness1) { … }
TEST_F(SpeculationRuleSetTest, InvalidUseOfEagerness2) { … }
TEST_F(SpeculationRuleSetTest, InvalidEagernessValue) { … }
TEST_F(SpeculationRuleSetTest, ValidNoVarySearchHintValueGeneratesCandidate) { … }
TEST_F(SpeculationRuleSetTest, InvalidNoVarySearchHintValueGeneratesCandidate) { … }
TEST_F(SpeculationRuleSetTest, EmptyNoVarySearchHintValueGeneratesCandidate) { … }
TEST_F(SpeculationRuleSetTest, DefaultNoVarySearchHintValueGeneratesCandidate) { … }
TEST_F(SpeculationRuleSetTest, ConsoleWarningForNoVarySearchHintNotAString) { … }
TEST_F(SpeculationRuleSetTest, NoVarySearchHintParseErrorRuleSkipped) { … }
TEST_F(SpeculationRuleSetTest, NoVarySearchHintParseErrorRuleAccepted) { … }
TEST_F(SpeculationRuleSetTest, ValidNoVarySearchHintNoErrorOrWarningMessages) { … }
TEST_F(SpeculationRuleSetTest, DocumentReportsSuccessMetric) { … }
TEST_F(SpeculationRuleSetTest, DocumentReportsParseErrorFromScript) { … }
TEST_F(SpeculationRuleSetTest, DocumentReportsParseErrorFromRequest) { … }
TEST_F(SpeculationRuleSetTest, DocumentReportsParseErrorFromBrowserInjection) { … }
TEST_F(SpeculationRuleSetTest, ImplicitSource) { … }
}
}