blob: 5461a5bb73aa5d004c8582dbb269129899451c6a [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#include <vector>
9
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)
Jeremy Roman1aeb1ea2020-06-03 02:40:3428 : web_contents_(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örrie362098d2021-03-09 08:47:0951 const char16_t kInvalidChars[] = {'\r', 0};
[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_)
61 observer.OnFindEmptyText(web_contents_);
62 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;
Jeremy Roman1aeb1ea2020-06-03 02:40:3490 web_contents_->Find(current_find_request_id_, find_text_, std::move(options));
[email protected]9c318862011-02-01 22:27:2491}
92
Evan Stade61ccab72020-01-17 20:17:5193void FindTabHelper::StopFinding(SelectionAction selection_action) {
94 if (selection_action == SelectionAction::kClear) {
[email protected]9c318862011-02-01 22:27:2495 // kClearSelection means the find string has been cleared by the user, but
96 // the UI has not been dismissed. In that case we want to clear the
97 // previously remembered search (http://crbug.com/42639).
Jan Wilken Dörriefa241ba2021-03-11 17:57:0198 previous_find_text_ = std::u16string();
[email protected]9c318862011-02-01 22:27:2499 } else {
100 find_ui_active_ = false;
101 if (!find_text_.empty())
102 previous_find_text_ = find_text_;
103 }
104 find_text_.clear();
Eric Lawrence92b29bf2019-02-15 16:40:24105 last_completed_find_text_.clear();
[email protected]9c318862011-02-01 22:27:24106 find_op_aborted_ = true;
107 last_search_result_ = FindNotificationDetails();
Russell Davis0fa45e92020-09-30 23:09:56108 should_find_match_ = false;
[email protected]216813952011-05-19 22:21:26109
[email protected]815dd9872011-11-23 18:40:30110 content::StopFindAction action;
[email protected]216813952011-05-19 22:21:26111 switch (selection_action) {
Evan Stade61ccab72020-01-17 20:17:51112 case SelectionAction::kClear:
[email protected]815dd9872011-11-23 18:40:30113 action = content::STOP_FIND_ACTION_CLEAR_SELECTION;
[email protected]216813952011-05-19 22:21:26114 break;
Evan Stade61ccab72020-01-17 20:17:51115 case SelectionAction::kKeep:
[email protected]815dd9872011-11-23 18:40:30116 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26117 break;
Evan Stade61ccab72020-01-17 20:17:51118 case SelectionAction::kActivate:
[email protected]815dd9872011-11-23 18:40:30119 action = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
[email protected]216813952011-05-19 22:21:26120 break;
121 default:
122 NOTREACHED();
[email protected]815dd9872011-11-23 18:40:30123 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
[email protected]216813952011-05-19 22:21:26124 }
Jeremy Roman1aeb1ea2020-06-03 02:40:34125 web_contents_->StopFinding(action);
[email protected]9c318862011-02-01 22:27:24126}
127
dmazzoni1a69e2b32014-11-06 20:34:28128void FindTabHelper::ActivateFindInPageResultForAccessibility() {
Jeremy Roman1aeb1ea2020-06-03 02:40:34129 web_contents_->GetMainFrame()->ActivateFindInPageResultForAccessibility(
dmazzoni1a69e2b32014-11-06 20:34:28130 current_find_request_id_);
131}
132
Jan Wilken Dörriefa241ba2021-03-11 17:57:01133std::u16string FindTabHelper::GetInitialSearchText() {
Evan Stade61ccab72020-01-17 20:17:51134 // Try the last thing we searched for in this tab.
135 if (!previous_find_text_.empty())
136 return previous_find_text_;
137
138 // Then defer to the delegate.
Jan Wilken Dörriefa241ba2021-03-11 17:57:01139 return delegate_ ? delegate_->GetSearchPrepopulateText() : std::u16string();
Evan Stade61ccab72020-01-17 20:17:51140}
141
[email protected]59363fc92012-09-05 03:46:31142#if defined(OS_ANDROID)
143void FindTabHelper::ActivateNearestFindResult(float x, float y) {
144 if (!find_op_aborted_ && !find_text_.empty()) {
Jeremy Roman1aeb1ea2020-06-03 02:40:34145 web_contents_->ActivateNearestFindResult(x, y);
[email protected]59363fc92012-09-05 03:46:31146 }
147}
148
149void FindTabHelper::RequestFindMatchRects(int current_version) {
150 if (!find_op_aborted_ && !find_text_.empty())
Jeremy Roman1aeb1ea2020-06-03 02:40:34151 web_contents_->RequestFindMatchRects(current_version);
[email protected]59363fc92012-09-05 03:46:31152}
153#endif
154
[email protected]b888919c2011-09-02 00:32:16155void FindTabHelper::HandleFindReply(int request_id,
156 int number_of_matches,
157 const gfx::Rect& selection_rect,
158 int active_match_ordinal,
159 bool final_update) {
[email protected]9c318862011-02-01 22:27:24160 // Ignore responses for requests that have been aborted.
paulmeyer1cfca292016-04-25 23:25:57161 // Ignore responses for requests from previous sessions. That way we won't act
162 // on stale results when the user has already typed in another query.
163 if (!find_op_aborted_ && request_id >= current_find_session_id_) {
[email protected]9c318862011-02-01 22:27:24164 if (number_of_matches == -1)
165 number_of_matches = last_search_result_.number_of_matches();
166 if (active_match_ordinal == -1)
167 active_match_ordinal = last_search_result_.active_match_ordinal();
168
169 gfx::Rect selection = selection_rect;
[email protected]27e7a0552012-03-16 00:01:17170 if (final_update && active_match_ordinal == 0)
171 selection = gfx::Rect();
172 else if (selection_rect.IsEmpty())
[email protected]9c318862011-02-01 22:27:24173 selection = last_search_result_.selection_rect();
174
175 // Notify the UI, automation and any other observers that a find result was
176 // found.
Evan Stade61ccab72020-01-17 20:17:51177 last_search_result_ =
178 FindNotificationDetails(request_id, number_of_matches, selection,
179 active_match_ordinal, final_update);
Evan Stade70a3cef2019-07-11 20:45:36180 for (auto& observer : observers_)
Jeremy Roman1aeb1ea2020-06-03 02:40:34181 observer.OnFindResultAvailable(web_contents_);
[email protected]9c318862011-02-01 22:27:24182 }
[email protected]9c318862011-02-01 22:27:24183}
François Doray4f51d5d2018-12-03 22:26:24184
185WEB_CONTENTS_USER_DATA_KEY_IMPL(FindTabHelper)
Evan Stade61ccab72020-01-17 20:17:51186
187} // namespace find_in_page