Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: chrome/browser/ui/omnibox/omnibox_controller.cc

Issue 14698028: Omnibox refactor. OmniboxController now holds an AutocompleteMatch. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased and cleaned-up. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/omnibox/omnibox_controller.h" 5 #include "chrome/browser/ui/omnibox/omnibox_controller.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/autocomplete/autocomplete_classifier.h" 8 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
9 #include "chrome/browser/autocomplete/autocomplete_match.h" 9 #include "chrome/browser/autocomplete/autocomplete_match.h"
10 #include "chrome/browser/autocomplete/search_provider.h" 10 #include "chrome/browser/autocomplete/search_provider.h"
11 #include "chrome/browser/net/predictor.h" 11 #include "chrome/browser/net/predictor.h"
12 #include "chrome/browser/predictors/autocomplete_action_predictor.h" 12 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
13 #include "chrome/browser/prerender/prerender_field_trial.h" 13 #include "chrome/browser/prerender/prerender_field_trial.h"
14 #include "chrome/browser/prerender/prerender_manager.h" 14 #include "chrome/browser/prerender/prerender_manager.h"
15 #include "chrome/browser/prerender/prerender_manager_factory.h" 15 #include "chrome/browser/prerender/prerender_manager_factory.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/search/search.h" 17 #include "chrome/browser/search/search.h"
18 #include "chrome/browser/search_engines/template_url_service.h"
19 #include "chrome/browser/search_engines/template_url_service_factory.h"
18 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h" 20 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
19 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" 21 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
20 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 22 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
21 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h" 23 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
22 #include "chrome/browser/ui/search/instant_controller.h" 24 #include "chrome/browser/ui/search/instant_controller.h"
23 #include "extensions/common/constants.h" 25 #include "extensions/common/constants.h"
24 #include "ui/gfx/rect.h" 26 #include "ui/gfx/rect.h"
25 27
26 using predictors::AutocompleteActionPredictor; 28 using predictors::AutocompleteActionPredictor;
27 29
30 namespace {
31
32 string16 GetDefaultSearchProviderKeyword(Profile* profile) {
33 TemplateURLService* template_url_service =
34 TemplateURLServiceFactory::GetForProfile(profile);
35 if (template_url_service) {
36 TemplateURL* template_url =
37 template_url_service->GetDefaultSearchProvider();
38 if (template_url)
39 return template_url->keyword();
40 }
41 return string16();
42 }
43
44 } // namespace
28 45
29 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model, 46 OmniboxController::OmniboxController(OmniboxEditModel* omnibox_edit_model,
30 Profile* profile) 47 Profile* profile)
31 : omnibox_edit_model_(omnibox_edit_model), 48 : omnibox_edit_model_(omnibox_edit_model),
32 profile_(profile) { 49 profile_(profile) {
33 autocomplete_controller_.reset(new AutocompleteController(profile, this, 50 autocomplete_controller_.reset(new AutocompleteController(profile, this,
34 chrome::IsInstantExtendedAPIEnabled() ? 51 chrome::IsInstantExtendedAPIEnabled() ?
35 AutocompleteClassifier::kInstantExtendedOmniboxProviders : 52 AutocompleteClassifier::kInstantExtendedOmniboxProviders :
36 AutocompleteClassifier::kDefaultOmniboxProviders)); 53 AutocompleteClassifier::kDefaultOmniboxProviders));
37 } 54 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 AutocompleteInput::ALL_MATCHES)); 86 AutocompleteInput::ALL_MATCHES));
70 } 87 }
71 88
72 void OmniboxController::OnResultChanged(bool default_match_changed) { 89 void OmniboxController::OnResultChanged(bool default_match_changed) {
73 // TODO(beaudoin): There should be no need to access the popup when using 90 // TODO(beaudoin): There should be no need to access the popup when using
74 // instant extended, remove this reference. 91 // instant extended, remove this reference.
75 const bool was_open = popup_->IsOpen(); 92 const bool was_open = popup_->IsOpen();
76 if (default_match_changed) { 93 if (default_match_changed) {
77 // The default match has changed, we need to let the OmniboxEditModel know 94 // The default match has changed, we need to let the OmniboxEditModel know
78 // about new inline autocomplete text (blue highlight). 95 // about new inline autocomplete text (blue highlight).
79 string16 inline_autocomplete_text;
80 string16 keyword;
81 bool is_keyword_hint = false;
82 const AutocompleteResult& result = this->result(); 96 const AutocompleteResult& result = this->result();
83 const AutocompleteResult::const_iterator match(result.default_match()); 97 const AutocompleteResult::const_iterator match(result.default_match());
84 if (match != result.end()) { 98 if (match != result.end()) {
99 current_match_ = *match;
100 // The |fill_into_edit| we get may not match what we have in the view at
101 // that time. We're only interested in the inline_autocomplete part, so
102 // update this here.
103 current_match_.fill_into_edit = omnibox_edit_model_->user_text();
Peter Kasting 2013/06/11 22:42:55 I confess, I have no idea what you're doing here.
beaudoin 2013/06/14 21:39:38 This is the "blue text" completion path. In an ide
Peter Kasting 2013/06/15 00:29:21 It seems like the reason we need to change this is
beaudoin 2013/06/17 17:22:33 Yes, I think it would make it easier to understand
85 if ((match->inline_autocomplete_offset != string16::npos) && 104 if ((match->inline_autocomplete_offset != string16::npos) &&
Peter Kasting 2013/06/11 22:42:55 Nit: First condition not necessary, see comments i
beaudoin 2013/06/14 21:39:38 Done.
86 (match->inline_autocomplete_offset < 105 (match->inline_autocomplete_offset <
87 match->fill_into_edit.length())) { 106 match->fill_into_edit.length())) {
88 inline_autocomplete_text = 107 current_match_.inline_autocomplete_offset =
89 match->fill_into_edit.substr(match->inline_autocomplete_offset); 108 current_match_.fill_into_edit.length();
109 current_match_.fill_into_edit += match->fill_into_edit.substr(
110 match->inline_autocomplete_offset);
111 } else {
112 current_match_.inline_autocomplete_offset = string16::npos;
90 } 113 }
91 114
92 if (!prerender::IsOmniboxEnabled(profile_)) 115 if (!prerender::IsOmniboxEnabled(profile_))
93 DoPreconnect(*match); 116 DoPreconnect(*match);
94 117 omnibox_edit_model_->OnCurrentMatchChanged(false);
95 // We could prefetch the alternate nav URL, if any, but because there 118 } else {
96 // can be many of these as a user types an initial series of characters, 119 InvalidateCurrentMatch();
97 // the OS DNS cache could suffer eviction problems for minimal gain. 120 popup_->OnResultChanged();
98 121 omnibox_edit_model_->OnPopupDataChanged(string16(), NULL, string16(),
99 match->GetKeywordUIState(profile_, &keyword, &is_keyword_hint); 122 false);
100 } 123 }
101
102 popup_->OnResultChanged();
103 omnibox_edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
104 keyword, is_keyword_hint);
105 } else { 124 } else {
106 popup_->OnResultChanged(); 125 popup_->OnResultChanged();
107 } 126 }
108 127
128 // TODO(beaudoin): This may no longer be needed now that instant classic is
129 // gone.
109 if (popup_->IsOpen()) { 130 if (popup_->IsOpen()) {
110 // The popup size may have changed, let instant know. 131 // The popup size may have changed, let instant know.
111 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); 132 OnPopupBoundsChanged(popup_->view()->GetTargetBounds());
112 133
113 InstantController* instant_controller = GetInstantController(); 134 InstantController* instant_controller = GetInstantController();
114 if (instant_controller && !omnibox_edit_model_->in_revert()) { 135 if (instant_controller && !omnibox_edit_model_->in_revert()) {
115 instant_controller->HandleAutocompleteResults( 136 instant_controller->HandleAutocompleteResults(
116 *autocomplete_controller_->providers(), 137 *autocomplete_controller_->providers(),
117 autocomplete_controller_->result()); 138 autocomplete_controller_->result());
118 } 139 }
(...skipping 23 matching lines...) Expand all
142 AutocompleteInput::RemoveForcedQueryStringIfNecessary( 163 AutocompleteInput::RemoveForcedQueryStringIfNecessary(
143 autocomplete_controller_->input().type(), &user_text); 164 autocomplete_controller_->input().type(), &user_text);
144 AutocompleteInput::RemoveForcedQueryStringIfNecessary( 165 AutocompleteInput::RemoveForcedQueryStringIfNecessary(
145 autocomplete_controller_->input().type(), &full_text); 166 autocomplete_controller_->input().type(), &full_text);
146 return instant_controller->Update( 167 return instant_controller->Update(
147 match, user_text, full_text, selection_start, selection_end, 168 match, user_text, full_text, selection_start, selection_end,
148 UseVerbatimInstant(just_deleted_text), user_input_in_progress, 169 UseVerbatimInstant(just_deleted_text), user_input_in_progress,
149 popup_->IsOpen(), in_escape_handler, keyword_is_selected); 170 popup_->IsOpen(), in_escape_handler, keyword_is_selected);
150 } 171 }
151 172
173 void OmniboxController::FinalizeInstantQuery(
174 const string16& input_text,
175 const InstantSuggestion& suggestion) {
176 if (!popup_model()->result().empty()) {
177 // When a IME is active and a candidate window is open, we don't show
178 // the omnibox popup, though |result()| may be available. Thus we check
179 // whether result().empty() or not instead of whether IsOpen() or not.
180 // We need the finalization of instant query when result() is available.
Peter Kasting 2013/06/11 22:42:55 Nit: This last sentence isn't grammatical and I do
beaudoin 2013/06/14 21:39:38 Clarified, to the best of my understanding. Done.
181 SearchProvider* search_provider =
182 autocomplete_controller_->search_provider();
183 // There may be no providers during testing; guard against that.
184 if (search_provider)
185 search_provider->FinalizeInstantQuery(input_text, suggestion);
186 }
187 }
188
189 void OmniboxController::SetInstantSuggestion(
190 const InstantSuggestion& suggestion) {
191 switch (suggestion.behavior) {
192
Peter Kasting 2013/06/11 22:42:55 Nit: Extra newline
beaudoin 2013/06/14 21:39:38 Done.
193 case INSTANT_COMPLETE_NOW:
194 // Set blue suggestion text.
195 // TODO(beaudoin): This currently go to the SearchProvider. Instead we
Peter Kasting 2013/06/11 22:42:55 Nit: go -> goes
beaudoin 2013/06/14 21:39:38 Done.
196 // should just create a valid current_match_ and call
197 // omnibox_edit_model_->OnCurrentMatchChanged. This way we can get rid of
198 // FinalizeInstantQuery entirely.
199 if (!suggestion.text.empty())
200 FinalizeInstantQuery(omnibox_edit_model_->GetViewText(), suggestion);
201 break;
Peter Kasting 2013/06/11 22:42:55 Nit: Prefer return to break when they'd do the sam
beaudoin 2013/06/14 21:39:38 Done.
202
203 case INSTANT_COMPLETE_NEVER: {
204 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type);
205
206 // Set gray suggestion text.
207 // Remove "?" if we're in forced query mode.
208 string16 view_text = omnibox_edit_model_->GetViewText();
209 AutocompleteInput::RemoveForcedQueryStringIfNecessary(
210 autocomplete_controller_->input().type(), &view_text);
beaudoin 2013/06/06 14:15:00 Sreeram: I'm using autocomplete_controller->input(
sreeram 2013/06/06 23:32:23 No, not kosher. The gray text is set asynchronousl
beaudoin 2013/06/14 21:39:38 Done.
211 CreateAndSetInstantMatch(view_text, view_text,
212 AutocompleteMatchType::SEARCH_SUGGEST);
213 current_match_.gray_suggestion = suggestion.text;
214
215 // TODO(beaudoin): The following should no longer be needed.
216 SearchProvider* search_provider =
217 autocomplete_controller_->search_provider();
218 if (search_provider)
219 search_provider->ClearInstantSuggestion();
220
221 omnibox_edit_model_->OnCurrentMatchChanged(false);
222 break;
223 }
224
225 case INSTANT_COMPLETE_REPLACE:
226 // Replace the entire omnibox text by the suggestion the user just arrowed
227 // into.
Peter Kasting 2013/06/11 22:42:55 Nit: into -> to
beaudoin 2013/06/14 21:39:38 Done.
228 CreateAndSetInstantMatch(suggestion.text, suggestion.text,
229 suggestion.type == INSTANT_SUGGESTION_SEARCH ?
230 AutocompleteMatchType::SEARCH_SUGGEST :
231 AutocompleteMatchType::URL_WHAT_YOU_TYPED);
232
233 omnibox_edit_model_->OnCurrentMatchChanged(true);
234 break;
235 }
236 }
237
238 void OmniboxController::InvalidateCurrentMatch() {
239 current_match_ = AutocompleteMatch();
240 }
241
152 void OmniboxController::ClearPopupKeywordMode() const { 242 void OmniboxController::ClearPopupKeywordMode() const {
153 if (popup_->IsOpen() && 243 if (popup_->IsOpen() &&
154 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) 244 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD)
155 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); 245 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL);
156 } 246 }
157 247
158 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { 248 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) {
159 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { 249 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) {
160 // Warm up DNS Prefetch cache, or preconnect to a search service. 250 // Warm up DNS Prefetch cache, or preconnect to a search service.
161 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, 251 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // We send the caret position to Instant (so it can determine #1 itself), and 283 // We send the caret position to Instant (so it can determine #1 itself), and
194 // we use a separated widget for displaying the Instant suggest (so it doesn't 284 // we use a separated widget for displaying the Instant suggest (so it doesn't
195 // interfere with #2). So, we don't need to care about the value of 285 // interfere with #2). So, we don't need to care about the value of
196 // input.prevent_inline_autocomplete() here. 286 // input.prevent_inline_autocomplete() here.
197 return just_deleted_text || popup_->selected_line() != 0; 287 return just_deleted_text || popup_->selected_line() != 0;
198 } 288 }
199 289
200 InstantController* OmniboxController::GetInstantController() const { 290 InstantController* OmniboxController::GetInstantController() const {
201 return omnibox_edit_model_->GetInstantController(); 291 return omnibox_edit_model_->GetInstantController();
202 } 292 }
293
294 void OmniboxController::CreateAndSetInstantMatch(
295 string16 query_string,
296 string16 input_text,
297 AutocompleteMatchType::Type match_type) {
298 string16 keyword = GetDefaultSearchProviderKeyword(profile_);
299 if (keyword.empty())
300 return; // CreateSearchSuggestion needs a keyword.
301
302 current_match_ = SearchProvider::CreateSearchSuggestion(
303 profile_,
304 NULL, // autocomplete_provider
Peter Kasting 2013/06/11 22:42:55 Nit: I don't really like commenting particular arg
beaudoin 2013/06/14 21:39:38 Done.
305 AutocompleteInput(),
306 query_string,
307 input_text,
308 0, // relevance
309 match_type,
310 0, // accepted_suggestion
311 false, // is_keyword
312 keyword);
313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698