chromium/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h

// 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_