Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / find_bar / find_tab_helper.cc
blob8a3570f750f53f303f90d39e83f7a1d2d391072a
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
7 #include <vector>
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/find_bar/find_bar_state.h"
12 #include "chrome/browser/ui/find_bar/find_bar_state_factory.h"
13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/stop_find_action.h"
17 #include "third_party/WebKit/public/web/WebFindOptions.h"
18 #include "ui/gfx/rect_f.h"
20 using blink::WebFindOptions;
21 using content::WebContents;
23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(FindTabHelper);
25 // static
26 int FindTabHelper::find_request_id_counter_ = -1;
28 FindTabHelper::FindTabHelper(WebContents* web_contents)
29 : content::WebContentsObserver(web_contents),
30 find_ui_active_(false),
31 find_op_aborted_(false),
32 current_find_request_id_(find_request_id_counter_++),
33 last_search_case_sensitive_(false),
34 last_search_result_() {
37 FindTabHelper::~FindTabHelper() {
40 void FindTabHelper::StartFinding(base::string16 search_string,
41 bool forward_direction,
42 bool case_sensitive) {
43 // If search_string is empty, it means FindNext was pressed with a keyboard
44 // shortcut so unless we have something to search for we return early.
45 if (search_string.empty() && find_text_.empty()) {
46 Profile* profile =
47 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
48 base::string16 last_search_prepopulate_text =
49 FindBarStateFactory::GetLastPrepopulateText(profile);
51 // Try the last thing we searched for on this tab, then the last thing
52 // searched for on any tab.
53 if (!previous_find_text_.empty())
54 search_string = previous_find_text_;
55 else if (!last_search_prepopulate_text.empty())
56 search_string = last_search_prepopulate_text;
57 else
58 return;
61 // Keep track of the previous search.
62 previous_find_text_ = find_text_;
64 // This is a FindNext operation if we are searching for the same text again,
65 // or if the passed in search text is empty (FindNext keyboard shortcut). The
66 // exception to this is if the Find was aborted (then we don't want FindNext
67 // because the highlighting has been cleared and we need it to reappear). We
68 // therefore treat FindNext after an aborted Find operation as a full fledged
69 // Find.
70 bool find_next = (find_text_ == search_string || search_string.empty()) &&
71 (last_search_case_sensitive_ == case_sensitive) &&
72 !find_op_aborted_;
73 if (!find_next)
74 current_find_request_id_ = find_request_id_counter_++;
76 if (!search_string.empty())
77 find_text_ = search_string;
78 last_search_case_sensitive_ = case_sensitive;
80 find_op_aborted_ = false;
82 // Keep track of what the last search was across the tabs.
83 Profile* profile =
84 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
85 FindBarState* find_bar_state = FindBarStateFactory::GetForProfile(profile);
86 find_bar_state->set_last_prepopulate_text(find_text_);
88 WebFindOptions options;
89 options.forward = forward_direction;
90 options.matchCase = case_sensitive;
91 options.findNext = find_next;
92 web_contents()->Find(current_find_request_id_, find_text_, options);
95 void FindTabHelper::StopFinding(
96 FindBarController::SelectionAction selection_action) {
97 if (selection_action == FindBarController::kClearSelectionOnPage) {
98 // kClearSelection means the find string has been cleared by the user, but
99 // the UI has not been dismissed. In that case we want to clear the
100 // previously remembered search (http://crbug.com/42639).
101 previous_find_text_ = base::string16();
102 } else {
103 find_ui_active_ = false;
104 if (!find_text_.empty())
105 previous_find_text_ = find_text_;
107 find_text_.clear();
108 find_op_aborted_ = true;
109 last_search_result_ = FindNotificationDetails();
111 content::StopFindAction action;
112 switch (selection_action) {
113 case FindBarController::kClearSelectionOnPage:
114 action = content::STOP_FIND_ACTION_CLEAR_SELECTION;
115 break;
116 case FindBarController::kKeepSelectionOnPage:
117 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
118 break;
119 case FindBarController::kActivateSelectionOnPage:
120 action = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
121 break;
122 default:
123 NOTREACHED();
124 action = content::STOP_FIND_ACTION_KEEP_SELECTION;
126 web_contents()->StopFinding(action);
129 #if defined(OS_ANDROID)
130 void FindTabHelper::ActivateNearestFindResult(float x, float y) {
131 if (!find_op_aborted_ && !find_text_.empty()) {
132 web_contents()->GetRenderViewHost()->ActivateNearestFindResult(
133 current_find_request_id_, x, y);
137 void FindTabHelper::RequestFindMatchRects(int current_version) {
138 if (!find_op_aborted_ && !find_text_.empty())
139 web_contents()->GetRenderViewHost()->RequestFindMatchRects(current_version);
141 #endif
143 void FindTabHelper::HandleFindReply(int request_id,
144 int number_of_matches,
145 const gfx::Rect& selection_rect,
146 int active_match_ordinal,
147 bool final_update) {
148 // Ignore responses for requests that have been aborted.
149 // Ignore responses for requests other than the one we have most recently
150 // issued. That way we won't act on stale results when the user has
151 // already typed in another query.
152 if (!find_op_aborted_ && request_id == current_find_request_id_) {
153 if (number_of_matches == -1)
154 number_of_matches = last_search_result_.number_of_matches();
155 if (active_match_ordinal == -1)
156 active_match_ordinal = last_search_result_.active_match_ordinal();
158 gfx::Rect selection = selection_rect;
159 if (final_update && active_match_ordinal == 0)
160 selection = gfx::Rect();
161 else if (selection_rect.IsEmpty())
162 selection = last_search_result_.selection_rect();
164 // Notify the UI, automation and any other observers that a find result was
165 // found.
166 last_search_result_ = FindNotificationDetails(
167 request_id, number_of_matches, selection, active_match_ordinal,
168 final_update);
169 content::NotificationService::current()->Notify(
170 chrome::NOTIFICATION_FIND_RESULT_AVAILABLE,
171 content::Source<WebContents>(web_contents()),
172 content::Details<FindNotificationDetails>(&last_search_result_));