// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_TEXT_FRAGMENT_ANCHOR_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_TEXT_FRAGMENT_ANCHOR_H_ #include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-blink.h" #include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/renderer/core/annotation/annotation_agent_container_impl.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h" #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics.h" #include "third_party/blink/renderer/core/fragment_directive/text_fragment_finder.h" #include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h" #include "third_party/blink/renderer/core/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { class AnnotationAgentImpl; class DocumentLoader; class LocalFrame; class KURL; class TextDirective; // TextFragmentAnchor is the coordinator class for applying text directives // from the URL (also known as "scroll-to-text") to a document. This class' // purpose is to integrate with Blink's loading and lifecycle states and // execute behavior specific to scroll-to-text. The actual logic of performing // the text search and applying highlights is delegated out to the core // annotation API. The Annotations API performs the text matching while this // class tracks the state of its created annotations and performs necessary // actions based on that state. // // This class has three distinct responsibilities: // // 1) Vet security restrictions and create an annotation for each text // directive in the URL. // 2) Track the state of the first matching directive, apply "effects" to it // (highlight, scroll to it, apply focus, etc.). // 3) Mark non-matching directives as needing to retry their search. The // initial search occurs after parsing completes; if the load event takes // longer this class retries unmatched directives again at the load event. // // A frame will try to create a TextFragmentAnchor when parsing in a document // completes. If the URL has a valid text directive an instance of // TextFragmentAnchor will be created and stored on the LocalFrameView. // TextFragmentAnchor then turns the directive into AnnotationAgents to perform // the text search. // // Each directive is initially searched automatically after creating its // corresponding AnnotationAgentImpl. However, as pages often load content // dynamically, this class may schedule up to two additional search attempts. // One at document load completion and another a short delay after load. // // The anchor performs its operations via the InvokeSelector method which is // invoked repeatedly, each time layout finishes in the document. Thus, the // anchor is guaranteed that layout is clean in InvokeSelector; however, // end-of-layout is a script-forbidden section so no actions that can result in // script being run can be invoked from there. Script-running actions are // performed in finalization py posting an animation frame task. // // TextFragmentAnchor is a state machine that transitions state via // InvokeSelector (and some external events). The state represents the status // of the first matching directive, which is the directive to which effects // will be applied. Here are the state transitions (see the enum definition for // details of each state): // // ┌──────┐ // │ ┌──┴────────────────────────┐ // └───► kSearching ├───────┐ // └─────────────┬─────────────┘ │ // ┌──────┐ │ │ // │ ┌──┴──────────▼─────────────┐ │ // └───► kWaitingForDOMMutations │ │ // └─────────────┬─────────────┘ │ // │ │ // ┌─────────────▼─────────────┐ │ // │ kApplyEffects │◄──────┤ // └─────────────┬─────────────┘ │ // ┌──────┐ │ │ // │ ┌──┴──────────▼─────────────┐ │ // └───► kKeepInView │ │ // └─────────────┬─────────────┘ │ // │ │ // ┌─────────────▼─────────────┐ │ // │ kFinalized │◄──────┘ // └───────────────────────────┘ class CORE_EXPORT TextFragmentAnchor final : public SelectorFragmentAnchor, public AnnotationAgentContainerImpl::Observer { … }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_TEXT_FRAGMENT_ANCHOR_H_