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

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: Fixed failing browser tests. 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 AutocompleteInput::ALL_MATCHES)); 93 AutocompleteInput::ALL_MATCHES));
77 } 94 }
78 95
79 void OmniboxController::OnResultChanged(bool default_match_changed) { 96 void OmniboxController::OnResultChanged(bool default_match_changed) {
80 // TODO(beaudoin): There should be no need to access the popup when using 97 // TODO(beaudoin): There should be no need to access the popup when using
81 // instant extended, remove this reference. 98 // instant extended, remove this reference.
82 const bool was_open = popup_->IsOpen(); 99 const bool was_open = popup_->IsOpen();
83 if (default_match_changed) { 100 if (default_match_changed) {
84 // The default match has changed, we need to let the OmniboxEditModel know 101 // The default match has changed, we need to let the OmniboxEditModel know
85 // about new inline autocomplete text (blue highlight). 102 // about new inline autocomplete text (blue highlight).
86 string16 inline_autocomplete_text;
87 string16 keyword;
88 bool is_keyword_hint = false;
89 const AutocompleteResult& result = this->result(); 103 const AutocompleteResult& result = this->result();
90 const AutocompleteResult::const_iterator match(result.default_match()); 104 const AutocompleteResult::const_iterator match(result.default_match());
91 if (match != result.end()) { 105 if (match != result.end()) {
92 if ((match->inline_autocomplete_offset != string16::npos) && 106 current_match_ = *match;
93 (match->inline_autocomplete_offset < 107 // TODO(beaudoin): This code could be made simpler if AutocompleteMatch
94 match->fill_into_edit.length())) { 108 // had an |inline_autocompletion| instead of |inline_autocomplete_offset|.
95 inline_autocomplete_text = 109 // The |fill_into_edit| we get may not match what we have in the view at
96 match->fill_into_edit.substr(match->inline_autocomplete_offset); 110 // that time. We're only interested in the inline_autocomplete part, so
111 // update this here.
112 current_match_.fill_into_edit = omnibox_edit_model_->user_text();
113 if (match->inline_autocomplete_offset < match->fill_into_edit.length()) {
114 current_match_.inline_autocomplete_offset =
115 current_match_.fill_into_edit.length();
116 current_match_.fill_into_edit += match->fill_into_edit.substr(
117 match->inline_autocomplete_offset);
118 } else {
119 current_match_.inline_autocomplete_offset = string16::npos;
97 } 120 }
98 121
99 if (!prerender::IsOmniboxEnabled(profile_)) 122 if (!prerender::IsOmniboxEnabled(profile_))
100 DoPreconnect(*match); 123 DoPreconnect(*match);
101 124 omnibox_edit_model_->OnCurrentMatchChanged(false);
102 // We could prefetch the alternate nav URL, if any, but because there 125 } else {
103 // can be many of these as a user types an initial series of characters, 126 InvalidateCurrentMatch();
104 // the OS DNS cache could suffer eviction problems for minimal gain. 127 popup_->OnResultChanged();
105 128 omnibox_edit_model_->OnPopupDataChanged(string16(), NULL, string16(),
106 match->GetKeywordUIState(profile_, &keyword, &is_keyword_hint); 129 false);
107 } 130 }
108
109 popup_->OnResultChanged();
110 omnibox_edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
111 keyword, is_keyword_hint);
112 } else { 131 } else {
113 popup_->OnResultChanged(); 132 popup_->OnResultChanged();
114 } 133 }
115 134
135 // TODO(beaudoin): This may no longer be needed now that instant classic is
136 // gone.
116 if (popup_->IsOpen()) { 137 if (popup_->IsOpen()) {
117 // The popup size may have changed, let instant know. 138 // The popup size may have changed, let instant know.
118 OnPopupBoundsChanged(popup_->view()->GetTargetBounds()); 139 OnPopupBoundsChanged(popup_->view()->GetTargetBounds());
119 140
120 #if defined(HTML_INSTANT_EXTENDED_POPUP) 141 #if defined(HTML_INSTANT_EXTENDED_POPUP)
121 InstantController* instant_controller = GetInstantController(); 142 InstantController* instant_controller = GetInstantController();
122 if (instant_controller && !omnibox_edit_model_->in_revert()) { 143 if (instant_controller && !omnibox_edit_model_->in_revert()) {
123 instant_controller->HandleAutocompleteResults( 144 instant_controller->HandleAutocompleteResults(
124 *autocomplete_controller_->providers(), 145 *autocomplete_controller_->providers(),
125 autocomplete_controller_->result()); 146 autocomplete_controller_->result());
(...skipping 29 matching lines...) Expand all
155 autocomplete_controller_->input().type(), &full_text); 176 autocomplete_controller_->input().type(), &full_text);
156 return instant_controller->Update( 177 return instant_controller->Update(
157 match, user_text, full_text, selection_start, selection_end, 178 match, user_text, full_text, selection_start, selection_end,
158 UseVerbatimInstant(just_deleted_text), user_input_in_progress, 179 UseVerbatimInstant(just_deleted_text), user_input_in_progress,
159 popup_->IsOpen(), in_escape_handler, keyword_is_selected); 180 popup_->IsOpen(), in_escape_handler, keyword_is_selected);
160 #else 181 #else
161 return false; 182 return false;
162 #endif 183 #endif
163 } 184 }
164 185
186 void OmniboxController::FinalizeInstantQuery(
187 const string16& input_text,
188 const InstantSuggestion& suggestion) {
189 // Should only get called for the HTML popup.
190 #if defined(HTML_INSTANT_EXTENDED_POPUP)
191 if (!popup_model()->result().empty()) {
192 // We need to finalize the instant query in all cases where the
193 // |popup_model| holds some result. It is not enough to check whether the
194 // popup is open, since when an IME is active the popup may be closed while
195 // |popup_model| contains a non-empty result.
196 SearchProvider* search_provider =
197 autocomplete_controller_->search_provider();
198 // There may be no providers during testing; guard against that.
199 if (search_provider)
200 search_provider->FinalizeInstantQuery(input_text, suggestion);
201 }
202 #endif
203 }
204
205 void OmniboxController::SetInstantSuggestion(
206 const InstantSuggestion& suggestion) {
207 // Should only get called for the HTML popup.
208 #if defined(HTML_INSTANT_EXTENDED_POPUP)
209 switch (suggestion.behavior) {
210 case INSTANT_COMPLETE_NOW:
211 // Set blue suggestion text.
212 // TODO(beaudoin): This currently goes to the SearchProvider. Instead we
213 // should just create a valid current_match_ and call
214 // omnibox_edit_model_->OnCurrentMatchChanged. This way we can get rid of
215 // FinalizeInstantQuery entirely.
216 if (!suggestion.text.empty())
217 FinalizeInstantQuery(omnibox_edit_model_->GetViewText(), suggestion);
218 return;
219
220 case INSTANT_COMPLETE_NEVER: {
221 DCHECK_EQ(INSTANT_SUGGESTION_SEARCH, suggestion.type);
222
223 // Set gray suggestion text.
224 // Remove "?" if we're in forced query mode.
225 gray_suggestion_ = suggestion.text;
226
227 // TODO(beaudoin): The following should no longer be needed once the
228 // instant suggestion no longer goes through the search provider.
229 SearchProvider* search_provider =
230 autocomplete_controller_->search_provider();
231 if (search_provider)
232 search_provider->ClearInstantSuggestion();
233
234 omnibox_edit_model_->OnGrayTextChanged();
235 return;
236 }
237
238 case INSTANT_COMPLETE_REPLACE:
239 // Replace the entire omnibox text by the suggestion the user just arrowed
240 // to.
241 CreateAndSetInstantMatch(suggestion.text, suggestion.text,
242 suggestion.type == INSTANT_SUGGESTION_SEARCH ?
243 AutocompleteMatchType::SEARCH_SUGGEST :
244 AutocompleteMatchType::URL_WHAT_YOU_TYPED);
245
246 omnibox_edit_model_->OnCurrentMatchChanged(true);
247 return;
248 }
249 #endif
250 }
251
252 void OmniboxController::InvalidateCurrentMatch() {
253 current_match_ = AutocompleteMatch();
254 }
255
256 const AutocompleteMatch& OmniboxController::CurrentMatch(
257 GURL* alternate_nav_url) const {
258 if (alternate_nav_url && current_match_.destination_url.is_valid()) {
259 *alternate_nav_url = AutocompleteResult::ComputeAlternateNavUrl(
260 autocomplete_controller_->input(), current_match_);
261 }
262
263 return current_match_;
264 }
265
266
165 void OmniboxController::ClearPopupKeywordMode() const { 267 void OmniboxController::ClearPopupKeywordMode() const {
166 if (popup_->IsOpen() && 268 if (popup_->IsOpen() &&
167 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD) 269 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD)
168 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL); 270 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL);
169 } 271 }
170 272
171 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) { 273 void OmniboxController::DoPreconnect(const AutocompleteMatch& match) {
172 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) { 274 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) {
173 // Warm up DNS Prefetch cache, or preconnect to a search service. 275 // Warm up DNS Prefetch cache, or preconnect to a search service.
174 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, 276 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 // We send the caret position to Instant (so it can determine #1 itself), and 308 // We send the caret position to Instant (so it can determine #1 itself), and
207 // we use a separated widget for displaying the Instant suggest (so it doesn't 309 // we use a separated widget for displaying the Instant suggest (so it doesn't
208 // interfere with #2). So, we don't need to care about the value of 310 // interfere with #2). So, we don't need to care about the value of
209 // input.prevent_inline_autocomplete() here. 311 // input.prevent_inline_autocomplete() here.
210 return just_deleted_text || popup_->selected_line() != 0; 312 return just_deleted_text || popup_->selected_line() != 0;
211 } 313 }
212 314
213 InstantController* OmniboxController::GetInstantController() const { 315 InstantController* OmniboxController::GetInstantController() const {
214 return omnibox_edit_model_->GetInstantController(); 316 return omnibox_edit_model_->GetInstantController();
215 } 317 }
318
319 void OmniboxController::CreateAndSetInstantMatch(
320 string16 query_string,
321 string16 input_text,
322 AutocompleteMatchType::Type match_type) {
323 string16 keyword = GetDefaultSearchProviderKeyword(profile_);
324 if (keyword.empty())
325 return; // CreateSearchSuggestion needs a keyword.
326
327 current_match_ = SearchProvider::CreateSearchSuggestion(
328 profile_, NULL, AutocompleteInput(), query_string, input_text, 0,
329 match_type, 0, false, keyword, -1);
330 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/omnibox/omnibox_controller.h ('k') | chrome/browser/ui/omnibox/omnibox_edit_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698