blob: e7c60eecce8aac971b651ded8b405204a42228dc [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
avif9ab5d942015-10-15 14:05:449#include "base/strings/string_util.h"
avi655876a2015-12-25 07:18:1510#include "build/build_config.h"
Evan Stade61ccab72020-01-17 20:17:5111#include "components/find_in_page/find_result_observer.h"
12#include "components/find_in_page/find_types.h"
dmazzoni1a69e2b32014-11-06 20:34:2813#include "content/public/browser/render_frame_host.h"
[email protected]d9083482012-01-06 00:38:4614#include "content/public/browser/web_contents.h"
[email protected]815dd9872011-11-23 18:40:3015#include "content/public/common/stop_find_action.h"
Rakina Zata Amni3f77dff2018-09-08 16:19:4316#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
tfarina3b0452d2014-12-31 15:20:0917#include "ui/gfx/geometry/rect_f.h"
[email protected]216813952011-05-19 22:21:2618
[email protected]768c5472011-12-26 19:06:1719using content::WebContents;
[email protected]9c318862011-02-01 22:27:2420
Evan Stade61ccab72020-01-17 20:17:5121namespace find_in_page {
22
[email protected]9c318862011-02-01 22:27:2423// static
[email protected]c90c6ca2011-02-16 20:11:3824int FindTabHelper::find_request_id_counter_ = -1;
[email protected]9c318862011-02-01 22:27:2425
[email protected]d9083482012-01-06 00:38:4626FindTabHelper::FindTabHelper(WebContents* web_contents)
Jeremy Roman1aeb1ea2020-06-03 02:40:3427 : web_contents_(web_contents),
[email protected]9c318862011-02-01 22:27:2428 current_find_request_id_(find_request_id_counter_++),
Evan Stade61ccab72020-01-17 20:17:5129 current_find_session_id_(current_find_request_id_) {}
[email protected]9c318862011-02-01 22:27:2430
Evan Stade0e39ab762019-11-15 01:42:1331FindTabHelper::~FindTabHelper() {
32 for (auto& observer : observers_)
33 observer.OnFindTabHelperDestroyed(this);
34}
Evan Stade70a3cef2019-07-11 20:45:3635
36void FindTabHelper::AddObserver(FindResultObserver* observer) {
37 observers_.AddObserver(observer);
38}
39
40void FindTabHelper::RemoveObserver(FindResultObserver* observer) {
41 observers_.RemoveObserver(observer);
[email protected]9c318862011-02-01 22:27:2442}
43
Jan Wilken Dörriefa241ba2021-03-11 17:57:0144void FindTabHelper::StartFinding(std::u16string search_string,
[email protected]c90c6ca2011-02-16 20:11:3845 bool forward_direction,
Rakina Zata Amnid4ce97f2018-08-17 12:51:4246 bool case_sensitive,
Russell Davis715fe032020-09-16 01:51:0947 bool find_match,
Rakina Zata Amnid4ce97f2018-08-17 12:51:4248 bool run_synchronously_for_testing) {
[email protected]102402c2014-07-09 19:53:3849 // Remove the carriage return character, which generally isn't in web content.
Jan Wilken Dörriecf672362021-03-15 14:16:0150 const char16_t kInvalidChars[] = u"\r";
[email protected]102402c2014-07-09 19:53:3851 base::RemoveChars(search_string, kInvalidChars, &search_string);
52
Russell Davis136df172020-10-15 18:00:4253 // Keep track of what the last search was across the tabs.
54 if (delegate_)
55 delegate_->SetLastSearchText(search_string);
[email protected]9c318862011-02-01 22:27:2456
Russell Davis136df172020-10-15 18:00:4257 if (search_string.empty()) {
58 StopFinding(find_in_page::SelectionAction::kClear);
59 for (auto& observer : observers_)
60 observer.OnFindEmptyText(web_contents_);
61 return;
[email protected]9c318862011-02-01 22:27:2462 }
63
Russell Davis136df172020-10-15 18:00:4264 bool new_session = find_text_ != search_string ||
Russell Davis8a36226c2020-06-05 17:09:5065 (last_search_case_sensitive_ != case_sensitive) ||
66 find_op_aborted_;
paulmeyerc0b762b2016-04-13 11:55:1767
Russell Davisdd2b6782020-09-21 23:55:5668 // Continuing here would just find the same results, potentially causing
69 // some flicker in the highlighting.
70 if (!new_session && !find_match)
71 return;
72
paulmeyerc0b762b2016-04-13 11:55:1773 current_find_request_id_ = find_request_id_counter_++;
Russell Davis8a36226c2020-06-05 17:09:5074 if (new_session)
paulmeyer1cfca292016-04-25 23:25:5775 current_find_session_id_ = current_find_request_id_;
[email protected]9c318862011-02-01 22:27:2476
Russell Davis136df172020-10-15 18:00:4277 previous_find_text_ = find_text_;
78 find_text_ = search_string;
[email protected]9c318862011-02-01 22:27:2479 last_search_case_sensitive_ = case_sensitive;
[email protected]9c318862011-02-01 22:27:2480 find_op_aborted_ = false;
Russell Davis0fa45e92020-09-30 23:09:5681 should_find_match_ = find_match;
[email protected]9c318862011-02-01 22:27:2482
Rakina Zata Amni3f77dff2018-09-08 16:19:4383 auto options = blink::mojom::FindOptions::New();
84 options->forward = forward_direction;
85 options->match_case = case_sensitive;
Russell Davis8a36226c2020-06-05 17:09:5086 options->new_session = new_session;
Russell Davis715fe032020-09-16 01:51:0987 options->find_match = find_match;
Rakina Zata Amni3f77dff2018-09-08 16:19:4388 options->run_synchronously_for_testing = run_synchronously_for_testing;
Jeremy Roman1aeb1ea2020-06-03 02:40:3489 web_contents_->Find(current_find_request_id_, find_text_, std::move(options));
[email protected]9c318862011-02-01 22:27:2490}
91
Evan Stade61ccab72020-01-17 20:17:5192void FindTabHelper::StopFinding(SelectionAction selection_action) {
93 if (selection_action == SelectionAction::kClear) {
[email protected]9c318862011-02-01 22:27:2494 // kClearSelection means the find string has been cleared by the user, but
95 // the UI has not been dismissed. In that case we want to clear the
96 // previously remembered search (http://crbug.com/42639).
Jan Wilken Dörriefa241ba2021-03-11 17:57:0197 previous_find_text_ = std::u16string();
[email protected]9c318862011-02-01 22:27:2498 } else {
99 find_ui_active_ = false;
100 if (!find_text_.empty())
101 previous_find_text_ = find_text_;
102 }
103 find_text_.clear();
Eric Lawrence92b29bf2019-02-15 16:40:24104 last_completed_find_text_.clear();
[email protected]9c318862011-02-01 22:27:24105 find_op_aborted_ = true;
106 last_search_result_ = FindNotificationDetails();
Russell Davis0fa45e92020-09-30 23:09:56107 should_find_match_ = false;
[email protected]216813952011-05-19 22:21:26108
[email protected]815dd9872011-11-23 18:40:30109 content::StopFindAction action;
[email protected]216813952011-05-19 22:21:26110 switch (selection_action) {
Evan Stade61ccab72020-01-17 20:17:51111 case SelectionAction::kClear:
[email protected]815dd9872011-11-23 18:40:30112 action = content::STOP_FIND_ACTION_CLEAR_SELECTION;
[email protected]216813952011-05-19 22:21:26113 break;
Evan Stade61ccab72020-01-17 20:17:51114 case SelectionAction::kKeep:
[email protected]815dd9872011-11-23 18:40:30115 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26116 break;
Evan Stade61ccab72020-01-17 20:17:51117 case SelectionAction::kActivate:
[email protected]815dd9872011-11-23 18:40:30118 action = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
[email protected]216813952011-05-19 22:21:26119 break;
120 default:
121 NOTREACHED();
[email protected]815dd9872011-11-23 18:40:30122 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26123 }
Jeremy Roman1aeb1ea2020-06-03 02:40:34124 web_contents_->StopFinding(action);
[email protected]9c318862011-02-01 22:27:24125}
126
dmazzoni1a69e2b32014-11-06 20:34:28127void FindTabHelper::ActivateFindInPageResultForAccessibility() {
Jeremy Roman1aeb1ea2020-06-03 02:40:34128 web_contents_->GetMainFrame()->ActivateFindInPageResultForAccessibility(
dmazzoni1a69e2b32014-11-06 20:34:28129 current_find_request_id_);
130}
131
Jan Wilken Dörriefa241ba2021-03-11 17:57:01132std::u16string FindTabHelper::GetInitialSearchText() {
Evan Stade61ccab72020-01-17 20:17:51133 // Try the last thing we searched for in this tab.
134 if (!previous_find_text_.empty())
135 return previous_find_text_;
136
137 // Then defer to the delegate.
Jan Wilken Dörriefa241ba2021-03-11 17:57:01138 return delegate_ ? delegate_->GetSearchPrepopulateText() : std::u16string();
Evan Stade61ccab72020-01-17 20:17:51139}
140
[email protected]59363fc92012-09-05 03:46:31141#if defined(OS_ANDROID)
142void FindTabHelper::ActivateNearestFindResult(float x, float y) {
143 if (!find_op_aborted_ && !find_text_.empty()) {
Jeremy Roman1aeb1ea2020-06-03 02:40:34144 web_contents_->ActivateNearestFindResult(x, y);
[email protected]59363fc92012-09-05 03:46:31145 }
146}
147
148void FindTabHelper::RequestFindMatchRects(int current_version) {
149 if (!find_op_aborted_ && !find_text_.empty())
Jeremy Roman1aeb1ea2020-06-03 02:40:34150 web_contents_->RequestFindMatchRects(current_version);
[email protected]59363fc92012-09-05 03:46:31151}
152#endif
153
[email protected]b888919c2011-09-02 00:32:16154void FindTabHelper::HandleFindReply(int request_id,
155 int number_of_matches,
156 const gfx::Rect& selection_rect,
157 int active_match_ordinal,
158 bool final_update) {
[email protected]9c318862011-02-01 22:27:24159 // Ignore responses for requests that have been aborted.
paulmeyer1cfca292016-04-25 23:25:57160 // Ignore responses for requests from previous sessions. That way we won't act
161 // on stale results when the user has already typed in another query.
162 if (!find_op_aborted_ && request_id >= current_find_session_id_) {
[email protected]9c318862011-02-01 22:27:24163 if (number_of_matches == -1)
164 number_of_matches = last_search_result_.number_of_matches();
165 if (active_match_ordinal == -1)
166 active_match_ordinal = last_search_result_.active_match_ordinal();
167
168 gfx::Rect selection = selection_rect;
[email protected]27e7a0552012-03-16 00:01:17169 if (final_update && active_match_ordinal == 0)
170 selection = gfx::Rect();
171 else if (selection_rect.IsEmpty())
[email protected]9c318862011-02-01 22:27:24172 selection = last_search_result_.selection_rect();
173
174 // Notify the UI, automation and any other observers that a find result was
175 // found.
Evan Stade61ccab72020-01-17 20:17:51176 last_search_result_ =
177 FindNotificationDetails(request_id, number_of_matches, selection,
178 active_match_ordinal, final_update);
Evan Stade70a3cef2019-07-11 20:45:36179 for (auto& observer : observers_)
Jeremy Roman1aeb1ea2020-06-03 02:40:34180 observer.OnFindResultAvailable(web_contents_);
[email protected]9c318862011-02-01 22:27:24181 }
[email protected]9c318862011-02-01 22:27:24182}
François Doray4f51d5d2018-12-03 22:26:24183
Daniel Cheng383df852021-10-02 03:28:01184WEB_CONTENTS_USER_DATA_KEY_IMPL(FindTabHelper);
Evan Stade61ccab72020-01-17 20:17:51185
186} // namespace find_in_page