/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_SpeculationRules_h #define mozilla_dom_SpeculationRules_h #include "mozilla/UniquePtr.h" #include "mozilla/dom/speculationrules_ffi_generated.h" #include "nsCOMPtr.h" #include "nsClassHashtable.h" #include "nsCycleCollectionParticipant.h" #include "nsHashKeys.h" #include "nsTArrayForwardDeclare.h" #include "nsTHashSet.h" class nsIContent; class nsIScriptElement; class nsITimer; class nsIURI; namespace mozilla::dom { class Document; class Element; class SpeculationRuleSet; class SpeculationRules final { public: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SpeculationRules) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(SpeculationRules) explicit SpeculationRules(Document* aDocument); void RegisterFromScript(nsIScriptElement* aScriptElement, UniquePtr aRuleSet); void Unregister(nsIScriptElement* aScriptElement); void ConsiderLoads(); void InnerConsiderLoads(); void AddLink(Element* aElement); void RemoveLink(Element* aElement); void FindMatchingLinks(nsTArray& aLinks); void HoverContentChanged(nsIContent* aContent); void PointerDown(Element* aContent); private: virtual ~SpeculationRules(); // The innermost inclusive flat tree ancestor of aContent that is a link this // document is tracking, or nullptr if there is none. Element* FindInterestedLink(nsIContent* aContent) const; // https://html.spec.whatwg.org/#inner-consider-speculative-loads-steps // Step 7, for those candidate groups that the user's behaviour has shown to // be eager enough. A group is enacted if it is at least as eager as // aTriggerLevel and, when aURL is non-null, is for that URL. Only the least // eager qualifying group per URL is enacted, as it is the one whose tags were // collected from every candidate the user's behaviour justifies. void EnactCandidates(nsIURI* aURL, Eagerness aTriggerLevel); // Arms the hover timer to enact candidates at least as eager as aLevel for // mHoverLink once aDelayMs has passed. void ArmHoverTimer(uint32_t aDelayMs, Eagerness aLevel); void CancelHoverTimer(); static void HoverTimerFired(nsITimer* aTimer, void* aClosure); RefPtr mDocument; // https://html.spec.whatwg.org/#document-sr-sets nsClassHashtable, SpeculationRuleSet> mRuleSetsFromScript; // https://html.spec.whatwg.org/#consider-speculative-loads-microtask-queued bool mConsiderSpeculativeLoadsMicrotaskQueued{false}; // The set of HTML and elements with an href attribute that are // connected to this document. This is tracked so FindMatchingLinks doesn't // have to walk the document tree every time speculative loads are considered. // These are non-owning pointers; the elements should remove themselves when // they are unbound from the document or lose their href attribute. nsTHashSet mLinks; // https://html.spec.whatwg.org/#speculative-load-candidate-group // The representative candidate of each group produced by the last run of // InnerConsiderLoads. Immediate groups have already been enacted; the rest // are kept so a later signal of user interest can enact them. nsTArray mCandidateGroups; // The link the hover timer is waiting on. Owning, as nothing else keeps the // element alive for the duration of the timer. RefPtr mHoverLink; nsCOMPtr mHoverTimer; // The eagerness level the pending hover timer will enact. When the eager // delay is the shorter one, the timer first fires for "eager" candidates and // then re-arms for "moderate" ones. Eagerness mHoverTimerLevel{Eagerness::Eager}; }; } // namespace mozilla::dom #endif // mozilla_dom_SpeculationRules_h