#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.h"
#include "third_party/blink/renderer/core/editing/finder/find_options.h"
#include "third_party/blink/renderer/core/editing/finder/find_task_controller.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/find_in_page.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/html_details_element.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/scroll/scroll_into_view_util.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
TextFinder::FindMatch::FindMatch(Range* range, int ordinal)
: … { … }
void TextFinder::FindMatch::Trace(Visitor* visitor) const { … }
static void AutoExpandSearchableHiddenElementsUpFrameTree(Range* range) { … }
static void ScrollToVisible(Range* match) { … }
void TextFinder::InitNewSession(const mojom::blink::FindOptions& options) { … }
bool TextFinder::Find(int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options,
bool wrap_within_frame,
bool* active_now) { … }
bool TextFinder::FindInternal(int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options,
bool wrap_within_frame,
bool* active_now,
Range* first_match,
bool wrapped_around) { … }
void TextFinder::ClearActiveFindMatch() { … }
LocalFrame* TextFinder::GetFrame() const { … }
void TextFinder::SetFindEndstateFocusAndSelection() { … }
void TextFinder::StopFindingAndClearSelection() { … }
void TextFinder::ReportFindInPageTerminationToAccessibility() { … }
void TextFinder::ReportFindInPageResultToAccessibility(int identifier) { … }
void TextFinder::StartScopingStringMatches(
int identifier,
const WebString& search_text,
const mojom::blink::FindOptions& options) { … }
void TextFinder::FlushCurrentScopingEffort(int identifier) { … }
void TextFinder::DidFindMatch(int identifier,
int current_total_matches,
Range* result_range) { … }
void TextFinder::UpdateMatches(int identifier,
int found_match_count,
bool finished_whole_request) { … }
void TextFinder::FinishCurrentScopingEffort(int identifier) { … }
void TextFinder::CancelPendingScopingEffort() { … }
void TextFinder::IncreaseMatchCount(int identifier, int count) { … }
void TextFinder::ReportFindInPageSelection(const gfx::Rect& selection_rect,
int active_match_ordinal,
int identifier) { … }
void TextFinder::ResetMatchCount() { … }
void TextFinder::ClearFindMatchesCache() { … }
void TextFinder::InvalidateFindMatchRects() { … }
void TextFinder::UpdateFindMatchRects() { … }
#if BUILDFLAG(IS_ANDROID)
gfx::RectF TextFinder::ActiveFindMatchRect() {
if (!current_active_match_frame_ || !active_match_)
return gfx::RectF();
return FindInPageRectFromRange(EphemeralRange(ActiveMatch()));
}
Vector<gfx::RectF> TextFinder::FindMatchRects() {
UpdateFindMatchRects();
Vector<gfx::RectF> match_rects;
match_rects.reserve(match_rects.size() + find_matches_cache_.size());
for (const FindMatch& match : find_matches_cache_) {
DCHECK(!match.rect_.IsEmpty());
match_rects.push_back(match.rect_);
}
return match_rects;
}
int TextFinder::SelectNearestFindMatch(const gfx::PointF& point,
gfx::Rect* selection_rect) {
int index = NearestFindMatch(point, nullptr);
if (index != -1)
return SelectFindMatch(static_cast<unsigned>(index), selection_rect);
return -1;
}
int TextFinder::NearestFindMatch(const gfx::PointF& point,
float* distance_squared) {
UpdateFindMatchRects();
int nearest = -1;
float nearest_distance_squared = FLT_MAX;
for (wtf_size_t i = 0; i < find_matches_cache_.size(); ++i) {
DCHECK(!find_matches_cache_[i].rect_.IsEmpty());
gfx::Vector2dF offset = point - find_matches_cache_[i].rect_.CenterPoint();
float current_distance_squared = offset.LengthSquared();
if (current_distance_squared < nearest_distance_squared) {
nearest = i;
nearest_distance_squared = current_distance_squared;
}
}
if (distance_squared)
*distance_squared = nearest_distance_squared;
return nearest;
}
int TextFinder::SelectFindMatch(unsigned index, gfx::Rect* selection_rect) {
SECURITY_DCHECK(index < find_matches_cache_.size());
Range* range = find_matches_cache_[index].range_;
if (!range->BoundaryPointsValid() || !range->startContainer()->isConnected())
return -1;
if (!current_active_match_frame_ || !active_match_ ||
!AreRangesEqual(active_match_.Get(), range)) {
active_match_index_ = find_matches_cache_[index].ordinal_ - 1;
current_active_match_frame_ = true;
OwnerFrame().ViewImpl()->SetFocusedFrame(&OwnerFrame());
if (active_match_)
SetMarkerActive(active_match_.Get(), false);
active_match_ = range;
SetMarkerActive(active_match_.Get(), true);
OwnerFrame().GetFrame()->Selection().Clear();
OwnerFrame().GetFrame()->GetDocument()->ClearFocusedElement();
}
gfx::Rect active_match_rect;
gfx::Rect active_match_bounding_box =
ComputeTextRect(EphemeralRange(active_match_.Get()));
if (!active_match_bounding_box.IsEmpty()) {
if (active_match_->FirstNode() &&
active_match_->FirstNode()->GetLayoutObject()) {
scroll_into_view_util::ScrollRectToVisible(
*active_match_->FirstNode()->GetLayoutObject(),
PhysicalRect(active_match_bounding_box),
scroll_into_view_util::CreateScrollIntoViewParams(
ScrollAlignment::CenterIfNeeded(),
ScrollAlignment::CenterIfNeeded(),
mojom::blink::ScrollType::kUser));
active_match_bounding_box =
ComputeTextRect(EphemeralRange(active_match_.Get()));
}
active_match_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame(
active_match_bounding_box);
OwnerFrame().LocalRoot()->FrameWidgetImpl()->ZoomToFindInPageRect(
active_match_rect);
}
if (selection_rect)
*selection_rect = active_match_rect;
return active_match_index_ + 1;
}
#endif
TextFinder::TextFinder(WebLocalFrameImpl& owner_frame)
: … { … }
bool TextFinder::SetMarkerActive(Range* range, bool active) { … }
void TextFinder::UnmarkAllTextMatches() { … }
void TextFinder::InvalidateIfNecessary() { … }
void TextFinder::FlushCurrentScoping() { … }
void TextFinder::InvalidatePaintForTickmarks() { … }
void TextFinder::Trace(Visitor* visitor) const { … }
void TextFinder::Scroll(std::unique_ptr<AsyncScrollContext> context) { … }
void TextFinder::IncreaseMarkerVersion() { … }
}