blob: a1d8477ccffdea5011bd6d7e471d8b098aae93fa [file] [log] [blame]
[email protected]e9856c22012-01-27 01:51:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]9c318862011-02-01 22:27:242// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Evan Stade61ccab72020-01-17 20:17:515#include "components/find_in_page/find_tab_helper.h"
[email protected]9c318862011-02-01 22:27:246
Eric Lawrence92b29bf2019-02-15 16:40:247#include <utility>
[email protected]9c318862011-02-01 22:27:248
David Sanders646a03e2022-02-22 14:33:349#include "base/observer_list.h"
avif9ab5d942015-10-15 14:05:4410#include "base/strings/string_util.h"
avi655876a2015-12-25 07:18:1511#include "build/build_config.h"
Evan Stade61ccab72020-01-17 20:17:5112#include "components/find_in_page/find_result_observer.h"
13#include "components/find_in_page/find_types.h"
dmazzoni1a69e2b32014-11-06 20:34:2814#include "content/public/browser/render_frame_host.h"
[email protected]d9083482012-01-06 00:38:4615#include "content/public/browser/web_contents.h"
[email protected]815dd9872011-11-23 18:40:3016#include "content/public/common/stop_find_action.h"
Rakina Zata Amni3f77dff2018-09-08 16:19:4317#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
tfarina3b0452d2014-12-31 15:20:0918#include "ui/gfx/geometry/rect_f.h"
[email protected]216813952011-05-19 22:21:2619
[email protected]768c5472011-12-26 19:06:1720using content::WebContents;
[email protected]9c318862011-02-01 22:27:2421
Evan Stade61ccab72020-01-17 20:17:5122namespace find_in_page {
23
[email protected]9c318862011-02-01 22:27:2424// static
[email protected]c90c6ca2011-02-16 20:11:3825int FindTabHelper::find_request_id_counter_ = -1;
[email protected]9c318862011-02-01 22:27:2426
[email protected]d9083482012-01-06 00:38:4627FindTabHelper::FindTabHelper(WebContents* web_contents)
Dave Tapuskaeeb68792021-11-16 21:38:4028 : content::WebContentsUserData<FindTabHelper>(*web_contents),
[email protected]9c318862011-02-01 22:27:2429 current_find_request_id_(find_request_id_counter_++),
Evan Stade61ccab72020-01-17 20:17:5130 current_find_session_id_(current_find_request_id_) {}
[email protected]9c318862011-02-01 22:27:2431
Evan Stade0e39ab762019-11-15 01:42:1332FindTabHelper::~FindTabHelper() {
33 for (auto& observer : observers_)
34 observer.OnFindTabHelperDestroyed(this);
35}
Evan Stade70a3cef2019-07-11 20:45:3636
37void FindTabHelper::AddObserver(FindResultObserver* observer) {
38 observers_.AddObserver(observer);
39}
40
41void FindTabHelper::RemoveObserver(FindResultObserver* observer) {
42 observers_.RemoveObserver(observer);
[email protected]9c318862011-02-01 22:27:2443}
44
Jan Wilken Dörriefa241ba2021-03-11 17:57:0145void FindTabHelper::StartFinding(std::u16string search_string,
[email protected]c90c6ca2011-02-16 20:11:3846 bool forward_direction,
Rakina Zata Amnid4ce97f2018-08-17 12:51:4247 bool case_sensitive,
Russell Davis715fe032020-09-16 01:51:0948 bool find_match,
Rakina Zata Amnid4ce97f2018-08-17 12:51:4249 bool run_synchronously_for_testing) {
[email protected]102402c2014-07-09 19:53:3850 // Remove the carriage return character, which generally isn't in web content.
Jan Wilken Dörriecf672362021-03-15 14:16:0151 const char16_t kInvalidChars[] = u"\r";
[email protected]102402c2014-07-09 19:53:3852 base::RemoveChars(search_string, kInvalidChars, &search_string);
53
Russell Davis136df172020-10-15 18:00:4254 // Keep track of what the last search was across the tabs.
55 if (delegate_)
56 delegate_->SetLastSearchText(search_string);
[email protected]9c318862011-02-01 22:27:2457
Russell Davis136df172020-10-15 18:00:4258 if (search_string.empty()) {
59 StopFinding(find_in_page::SelectionAction::kClear);
60 for (auto& observer : observers_)
Dave Tapuskaeeb68792021-11-16 21:38:4061 observer.OnFindEmptyText(&GetWebContents());
Russell Davis136df172020-10-15 18:00:4262 return;
[email protected]9c318862011-02-01 22:27:2463 }
64
Russell Davis136df172020-10-15 18:00:4265 bool new_session = find_text_ != search_string ||
Russell Davis8a36226c2020-06-05 17:09:5066 (last_search_case_sensitive_ != case_sensitive) ||
67 find_op_aborted_;
paulmeyerc0b762b2016-04-13 11:55:1768
Russell Davisdd2b6782020-09-21 23:55:5669 // Continuing here would just find the same results, potentially causing
70 // some flicker in the highlighting.
71 if (!new_session && !find_match)
72 return;
73
paulmeyerc0b762b2016-04-13 11:55:1774 current_find_request_id_ = find_request_id_counter_++;
Russell Davis8a36226c2020-06-05 17:09:5075 if (new_session)
paulmeyer1cfca292016-04-25 23:25:5776 current_find_session_id_ = current_find_request_id_;
[email protected]9c318862011-02-01 22:27:2477
Russell Davis136df172020-10-15 18:00:4278 previous_find_text_ = find_text_;
79 find_text_ = search_string;
[email protected]9c318862011-02-01 22:27:2480 last_search_case_sensitive_ = case_sensitive;
[email protected]9c318862011-02-01 22:27:2481 find_op_aborted_ = false;
Russell Davis0fa45e92020-09-30 23:09:5682 should_find_match_ = find_match;
[email protected]9c318862011-02-01 22:27:2483
Rakina Zata Amni3f77dff2018-09-08 16:19:4384 auto options = blink::mojom::FindOptions::New();
85 options->forward = forward_direction;
86 options->match_case = case_sensitive;
Russell Davis8a36226c2020-06-05 17:09:5087 options->new_session = new_session;
Russell Davis715fe032020-09-16 01:51:0988 options->find_match = find_match;
Rakina Zata Amni3f77dff2018-09-08 16:19:4389 options->run_synchronously_for_testing = run_synchronously_for_testing;
Dave Tapuskaeeb68792021-11-16 21:38:4090 GetWebContents().Find(current_find_request_id_, find_text_,
91 std::move(options));
[email protected]9c318862011-02-01 22:27:2492}
93
Evan Stade61ccab72020-01-17 20:17:5194void FindTabHelper::StopFinding(SelectionAction selection_action) {
95 if (selection_action == SelectionAction::kClear) {
[email protected]9c318862011-02-01 22:27:2496 // kClearSelection means the find string has been cleared by the user, but
97 // the UI has not been dismissed. In that case we want to clear the
98 // previously remembered search (http://crbug.com/42639).
Jan Wilken Dörriefa241ba2021-03-11 17:57:0199 previous_find_text_ = std::u16string();
[email protected]9c318862011-02-01 22:27:24100 } else {
101 find_ui_active_ = false;
102 if (!find_text_.empty())
103 previous_find_text_ = find_text_;
104 }
105 find_text_.clear();
Eric Lawrence92b29bf2019-02-15 16:40:24106 last_completed_find_text_.clear();
[email protected]9c318862011-02-01 22:27:24107 find_op_aborted_ = true;
108 last_search_result_ = FindNotificationDetails();
Russell Davis0fa45e92020-09-30 23:09:56109 should_find_match_ = false;
[email protected]216813952011-05-19 22:21:26110
[email protected]815dd9872011-11-23 18:40:30111 content::StopFindAction action;
[email protected]216813952011-05-19 22:21:26112 switch (selection_action) {
Evan Stade61ccab72020-01-17 20:17:51113 case SelectionAction::kClear:
[email protected]815dd9872011-11-23 18:40:30114 action = content::STOP_FIND_ACTION_CLEAR_SELECTION;
[email protected]216813952011-05-19 22:21:26115 break;
Evan Stade61ccab72020-01-17 20:17:51116 case SelectionAction::kKeep:
[email protected]815dd9872011-11-23 18:40:30117 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26118 break;
Evan Stade61ccab72020-01-17 20:17:51119 case SelectionAction::kActivate:
[email protected]815dd9872011-11-23 18:40:30120 action = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
[email protected]216813952011-05-19 22:21:26121 break;
122 default:
123 NOTREACHED();
[email protected]815dd9872011-11-23 18:40:30124 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26125 }
Dave Tapuskaeeb68792021-11-16 21:38:40126 GetWebContents().StopFinding(action);
[email protected]9c318862011-02-01 22:27:24127}
128
dmazzoni1a69e2b32014-11-06 20:34:28129void FindTabHelper::ActivateFindInPageResultForAccessibility() {
Dave Tapuska88d7b2e72022-06-07 21:00:51130 GetWebContents()
131 .GetPrimaryMainFrame()
132 ->ActivateFindInPageResultForAccessibility(current_find_request_id_);
dmazzoni1a69e2b32014-11-06 20:34:28133}
134
Jan Wilken Dörriefa241ba2021-03-11 17:57:01135std::u16string FindTabHelper::GetInitialSearchText() {
Evan Stade61ccab72020-01-17 20:17:51136 // Try the last thing we searched for in this tab.
137 if (!previous_find_text_.empty())
138 return previous_find_text_;
139
140 // Then defer to the delegate.
Jan Wilken Dörriefa241ba2021-03-11 17:57:01141 return delegate_ ? delegate_->GetSearchPrepopulateText() : std::u16string();
Evan Stade61ccab72020-01-17 20:17:51142}
143
Xiaohan Wangbca91f92022-01-15 19:56:21144#if BUILDFLAG(IS_ANDROID)
[email protected]59363fc92012-09-05 03:46:31145void FindTabHelper::ActivateNearestFindResult(float x, float y) {
146 if (!find_op_aborted_ && !find_text_.empty()) {
Dave Tapuskaeeb68792021-11-16 21:38:40147 GetWebContents().ActivateNearestFindResult(x, y);
[email protected]59363fc92012-09-05 03:46:31148 }
149}
150
151void FindTabHelper::RequestFindMatchRects(int current_version) {
152 if (!find_op_aborted_ && !find_text_.empty())
Dave Tapuskaeeb68792021-11-16 21:38:40153 GetWebContents().RequestFindMatchRects(current_version);
[email protected]59363fc92012-09-05 03:46:31154}
155#endif
156
[email protected]b888919c2011-09-02 00:32:16157void FindTabHelper::HandleFindReply(int request_id,
158 int number_of_matches,
159 const gfx::Rect& selection_rect,
160 int active_match_ordinal,
161 bool final_update) {
[email protected]9c318862011-02-01 22:27:24162 // Ignore responses for requests that have been aborted.
paulmeyer1cfca292016-04-25 23:25:57163 // Ignore responses for requests from previous sessions. That way we won't act
164 // on stale results when the user has already typed in another query.
165 if (!find_op_aborted_ && request_id >= current_find_session_id_) {
[email protected]9c318862011-02-01 22:27:24166 if (number_of_matches == -1)
167 number_of_matches = last_search_result_.number_of_matches();
168 if (active_match_ordinal == -1)
169 active_match_ordinal = last_search_result_.active_match_ordinal();
170
171 gfx::Rect selection = selection_rect;
[email protected]27e7a0552012-03-16 00:01:17172 if (final_update && active_match_ordinal == 0)
173 selection = gfx::Rect();
174 else if (selection_rect.IsEmpty())
[email protected]9c318862011-02-01 22:27:24175 selection = last_search_result_.selection_rect();
176
177 // Notify the UI, automation and any other observers that a find result was
178 // found.
Evan Stade61ccab72020-01-17 20:17:51179 last_search_result_ =
180 FindNotificationDetails(request_id, number_of_matches, selection,
181 active_match_ordinal, final_update);
Evan Stade70a3cef2019-07-11 20:45:36182 for (auto& observer : observers_)
Dave Tapuskaeeb68792021-11-16 21:38:40183 observer.OnFindResultAvailable(&GetWebContents());
[email protected]9c318862011-02-01 22:27:24184 }
[email protected]9c318862011-02-01 22:27:24185}
François Doray4f51d5d2018-12-03 22:26:24186
Daniel Cheng383df852021-10-02 03:28:01187WEB_CONTENTS_USER_DATA_KEY_IMPL(FindTabHelper);
Evan Stade61ccab72020-01-17 20:17:51188
189} // namespace find_in_page