1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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_PAGE_SCROLLING_TEXT_FRAGMENT_ANCHOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_ANCHOR_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/page/scrolling/element_fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class LocalFrame;
class KURL;
constexpr char kFragmentDirectivePrefix[] = ":~:";
// Subtract 1 because base::size includes the \0 string terminator.
constexpr size_t kFragmentDirectivePrefixStringLength =
base::size(kFragmentDirectivePrefix) - 1;
constexpr char kTextFragmentIdentifierPrefix[] = "text=";
// Subtract 1 because base::size includes the \0 string terminator.
constexpr size_t kTextFragmentIdentifierPrefixStringLength =
base::size(kTextFragmentIdentifierPrefix) - 1;
class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
public TextFragmentFinder::Client {
public:
static TextFragmentAnchor* TryCreateFragmentDirective(
const KURL& url,
LocalFrame& frame,
bool same_document_navigation,
bool should_scroll);
TextFragmentAnchor(
const Vector<TextFragmentSelector>& text_fragment_selectors,
LocalFrame& frame,
bool should_scroll);
~TextFragmentAnchor() override = default;
bool Invoke() override;
void Installed() override;
void DidScroll(mojom::blink::ScrollType type) override;
void PerformPreRafActions() override;
// Removes text match highlights if any highlight is in view.
bool Dismiss() override;
void Trace(Visitor*) override;
// TextFragmentFinder::Client interface
void DidFindMatch(
const EphemeralRangeInFlatTree& range,
const TextFragmentAnchorMetrics::Match match_metrics) override;
void DidFindAmbiguousMatch() override;
private:
// Called when the search is finished. Reports metrics and activates the
// element fragment anchor if we didn't find a match.
void DidFinishSearch();
void ApplyTargetToCommonAncestor(const EphemeralRangeInFlatTree& range);
void FireBeforeMatchEvent(Element* element);
Vector<TextFragmentFinder> text_fragment_finders_;
Member<LocalFrame> frame_;
bool search_finished_ = false;
// Whether the user has scrolled the page.
bool user_scrolled_ = false;
// Indicates that we should scroll into view the first match that we find, set
// to true each time the anchor is invoked if the user hasn't scrolled.
bool first_match_needs_scroll_ = false;
// Whether we successfully scrolled into view a match at least once, used for
// metrics reporting.
bool did_scroll_into_view_ = false;
// Whether we found a match. Used to determine if we should activate the
// element fragment anchor at the end of searching.
bool did_find_match_ = false;
// If the text fragment anchor is defined as a fragment directive and we don't
// find a match, we fall back to the element anchor if it is present.
Member<ElementFragmentAnchor> element_fragment_anchor_;
// Whether the text fragment anchor has been dismissed yet. This should be
// kept alive until dismissed so we can remove text highlighting.
bool dismissed_ = false;
// Whether we should scroll the anchor into view. This will be false for
// history navigations and reloads, where we want to restore the highlight but
// not scroll into view again.
bool should_scroll_ = false;
enum BeforematchState {
kNoMatchFound, // DidFindMatch has not been called.
kEventQueued, // Beforematch event has been queued, but not fired yet.
kFiredEvent // Beforematch event has been fired.
} beforematch_state_ = kNoMatchFound;
Member<TextFragmentAnchorMetrics> metrics_;
DISALLOW_COPY_AND_ASSIGN(TextFragmentAnchor);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_ANCHOR_H_
|