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

Side by Side Diff: chrome/browser/autocomplete/keyword_provider.cc

Issue 6731036: Enabled pressing TAB to cycle through the Omnibox results. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years, 4 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/autocomplete/keyword_provider.h" 5 #include "chrome/browser/autocomplete/keyword_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/string16.h" 10 #include "base/string16.h"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 string16* remaining_input) { 113 string16* remaining_input) {
114 if (!input.allow_exact_keyword_match()) 114 if (!input.allow_exact_keyword_match())
115 return NULL; 115 return NULL;
116 116
117 string16 keyword; 117 string16 keyword;
118 if (!ExtractKeywordFromInput(input, &keyword, remaining_input)) 118 if (!ExtractKeywordFromInput(input, &keyword, remaining_input))
119 return NULL; 119 return NULL;
120 120
121 // Make sure the model is loaded. This is cheap and quickly bails out if 121 // Make sure the model is loaded. This is cheap and quickly bails out if
122 // the model is already loaded. 122 // the model is already loaded.
123 TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile); 123 TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile);
Peter Kasting 2011/08/04 20:07:53 Nit: I wonder if there is a good way to make use o
aaron.randolph 2011/08/04 21:02:50 I can make the helper take a Profile as an argumen
aaron.randolph 2011/08/04 21:22:14 Though to do that, the |model_| check would need t
Peter Kasting 2011/08/04 21:31:42 No, that's precisely what I don't want. That's wh
124 DCHECK(model); 124 DCHECK(model);
125 model->Load(); 125 model->Load();
126 126
127 const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword); 127 const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword);
128 return TemplateURL::SupportsReplacement(template_url) ? template_url : NULL; 128 return TemplateURL::SupportsReplacement(template_url) ? template_url : NULL;
129 } 129 }
130 130
131 string16 KeywordProvider::GetKeywordForText(
132 const string16& text) const {
133 const string16 keyword(TemplateURLService::CleanUserInputKeyword(text));
134
135 if (keyword.empty())
136 return keyword;
137
138 TemplateURLService* url_service = GetTemplateURLService();
139 if (!url_service)
140 return string16();
141 url_service->Load();
142
143 // Don't provide a keyword if it doesn't support replacement.
144 const TemplateURL* const template_url =
145 url_service->GetTemplateURLForKeyword(keyword);
146 if (!TemplateURL::SupportsReplacement(template_url))
147 return string16();
148
149 // Don't provide a keyword for inactive/disabled extension keywords.
150 if (template_url->IsExtensionKeyword()) {
151 const Extension* extension = profile_->GetExtensionService()->
152 GetExtensionById(template_url->GetExtensionId(), false);
153 if (!extension ||
154 (profile_->IsOffTheRecord() &&
155 !profile_->GetExtensionService()->IsIncognitoEnabled(extension->id())))
156 return string16();
157 }
158
159 return keyword;
160 }
161
162 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
163 const string16& keyword,
164 const AutocompleteInput& input) {
165 return CreateAutocompleteMatch(GetTemplateURLService(), keyword, input,
166 keyword.size(), string16(), 0);
167 }
168
131 void KeywordProvider::Start(const AutocompleteInput& input, 169 void KeywordProvider::Start(const AutocompleteInput& input,
132 bool minimal_changes) { 170 bool minimal_changes) {
133 // This object ensures we end keyword mode if we exit the function without 171 // This object ensures we end keyword mode if we exit the function without
134 // toggling keyword mode to on. 172 // toggling keyword mode to on.
135 ScopedEndExtensionKeywordMode keyword_mode_toggle(this); 173 ScopedEndExtensionKeywordMode keyword_mode_toggle(this);
136 174
137 matches_.clear(); 175 matches_.clear();
138 176
139 if (!minimal_changes) { 177 if (!minimal_changes) {
140 done_ = true; 178 done_ = true;
(...skipping 13 matching lines...) Expand all
154 // whatever we do here! 192 // whatever we do here!
155 // 193 //
156 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for 194 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for
157 // keywords, we might suggest keywords that haven't even been partially typed, 195 // keywords, we might suggest keywords that haven't even been partially typed,
158 // if the user uses them enough and isn't obviously typing something else. In 196 // if the user uses them enough and isn't obviously typing something else. In
159 // this case we'd consider all input here to be query input. 197 // this case we'd consider all input here to be query input.
160 string16 keyword, remaining_input; 198 string16 keyword, remaining_input;
161 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) 199 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input))
162 return; 200 return;
163 201
164 // Make sure the model is loaded. This is cheap and quickly bails out if 202 TemplateURLService* model = GetTemplateURLService();
165 // the model is already loaded.
166 TemplateURLService* model =
167 profile_ ?
168 TemplateURLServiceFactory::GetForProfile(profile_) :
169 model_;
170 DCHECK(model);
171 model->Load();
172 203
173 // Get the best matches for this keyword. 204 // Get the best matches for this keyword.
174 // 205 //
175 // NOTE: We could cache the previous keywords and reuse them here in the 206 // NOTE: We could cache the previous keywords and reuse them here in the
176 // |minimal_changes| case, but since we'd still have to recalculate their 207 // |minimal_changes| case, but since we'd still have to recalculate their
177 // relevances and we can just recreate the results synchronously anyway, we 208 // relevances and we can just recreate the results synchronously anyway, we
178 // don't bother. 209 // don't bother.
179 // 210 //
180 // TODO(pkasting): http://b/893701 We should remember the user's use of a 211 // TODO(pkasting): http://b/893701 We should remember the user's use of a
181 // search query both from the autocomplete popup and from web pages 212 // search query both from the autocomplete popup and from web pages
182 // themselves. 213 // themselves.
183 std::vector<string16> keyword_matches; 214 std::vector<string16> keyword_matches;
184 model->FindMatchingKeywords(keyword, 215 model->FindMatchingKeywords(keyword,
185 !remaining_input.empty(), 216 !remaining_input.empty(),
186 &keyword_matches); 217 &keyword_matches);
187 218
188 // Prune any extension keywords that are disallowed in incognito mode (if
189 // we're incognito), or disabled.
190 for (std::vector<string16>::iterator i(keyword_matches.begin()); 219 for (std::vector<string16>::iterator i(keyword_matches.begin());
191 i != keyword_matches.end(); ) { 220 i != keyword_matches.end(); ) {
192 const TemplateURL* template_url(model->GetTemplateURLForKeyword(*i)); 221 const TemplateURL* template_url(model->GetTemplateURLForKeyword(*i));
222
223 // Prune any extension keywords that are disallowed in incognito mode (if
224 // we're incognito), or disabled.
193 if (profile_ && 225 if (profile_ &&
194 input.matches_requested() == AutocompleteInput::ALL_MATCHES && 226 input.matches_requested() == AutocompleteInput::ALL_MATCHES &&
195 template_url->IsExtensionKeyword()) { 227 template_url->IsExtensionKeyword()) {
196 ExtensionService* service = profile_->GetExtensionService(); 228 ExtensionService* service = profile_->GetExtensionService();
197 const Extension* extension = service->GetExtensionById( 229 const Extension* extension = service->GetExtensionById(
198 template_url->GetExtensionId(), false); 230 template_url->GetExtensionId(), false);
199 bool enabled = 231 bool enabled =
200 extension && (!profile_->IsOffTheRecord() || 232 extension && (!profile_->IsOffTheRecord() ||
201 service->IsIncognitoEnabled(extension->id())); 233 service->IsIncognitoEnabled(extension->id()));
202 if (!enabled) { 234 if (!enabled) {
203 i = keyword_matches.erase(i); 235 i = keyword_matches.erase(i);
204 continue; 236 continue;
205 } 237 }
206 } 238 }
239
240 // Prune any substituting keywords if there is no substitution.
241 if (TemplateURL::SupportsReplacement(template_url) &&
242 !input.allow_exact_keyword_match()) {
243 i = keyword_matches.erase(i);
244 continue;
245 }
246
207 ++i; 247 ++i;
208 } 248 }
209 if (keyword_matches.empty()) 249 if (keyword_matches.empty())
210 return; 250 return;
211 std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality()); 251 std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality());
212 252
213 // Limit to one exact or three inexact matches, and mark them up for display 253 // Limit to one exact or three inexact matches, and mark them up for display
214 // in the autocomplete popup. 254 // in the autocomplete popup.
215 // Any exact match is going to be the highest quality match, and thus at the 255 // Any exact match is going to be the highest quality match, and thus at the
216 // front of our vector. 256 // front of our vector.
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 const bool keyword_complete = (prefix_length == keyword.length()); 447 const bool keyword_complete = (prefix_length == keyword.length());
408 if (relevance < 0) { 448 if (relevance < 0) {
409 relevance = 449 relevance =
410 CalculateRelevance(input.type(), keyword_complete, 450 CalculateRelevance(input.type(), keyword_complete,
411 // When the user wants keyword matches to take 451 // When the user wants keyword matches to take
412 // preference, score them highly regardless of 452 // preference, score them highly regardless of
413 // whether the input provides query text. 453 // whether the input provides query text.
414 supports_replacement, input.prefer_keyword(), 454 supports_replacement, input.prefer_keyword(),
415 input.allow_exact_keyword_match()); 455 input.allow_exact_keyword_match());
416 } 456 }
417 AutocompleteMatch result(this, relevance, false, 457 AutocompleteMatch match(this, relevance, false,
418 supports_replacement ? AutocompleteMatch::SEARCH_OTHER_ENGINE : 458 supports_replacement ? AutocompleteMatch::SEARCH_OTHER_ENGINE :
419 AutocompleteMatch::HISTORY_KEYWORD); 459 AutocompleteMatch::HISTORY_KEYWORD);
420 result.fill_into_edit.assign(keyword); 460 match.fill_into_edit.assign(keyword);
421 if (!remaining_input.empty() || !keyword_complete || supports_replacement) 461 if (!remaining_input.empty() || !keyword_complete || supports_replacement)
422 result.fill_into_edit.push_back(L' '); 462 match.fill_into_edit.push_back(L' ');
423 result.fill_into_edit.append(remaining_input); 463 match.fill_into_edit.append(remaining_input);
424 // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd 464 // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd
425 // need CleanUserInputKeyword() to return the amount of adjustment it's made 465 // need CleanUserInputKeyword() to return the amount of adjustment it's made
426 // to the user's input. Because right now inexact keyword matches can't score 466 // to the user's input. Because right now inexact keyword matches can't score
427 // more highly than a "what you typed" match from one of the other providers, 467 // more highly than a "what you typed" match from one of the other providers,
428 // we just don't bother to do this, and leave inline autocompletion off. 468 // we just don't bother to do this, and leave inline autocompletion off.
429 result.inline_autocomplete_offset = string16::npos; 469 match.inline_autocomplete_offset = string16::npos;
430 470
431 // Create destination URL and popup entry content by substituting user input 471 // Create destination URL and popup entry content by substituting user input
432 // into keyword templates. 472 // into keyword templates.
433 FillInURLAndContents(remaining_input, element, &result); 473 FillInURLAndContents(remaining_input, element, &match);
434 474
435 if (supports_replacement) 475 if (supports_replacement)
436 result.template_url = element; 476 match.template_url = element;
437 result.transition = PageTransition::KEYWORD; 477 match.keyword = keyword;
478 match.transition = PageTransition::KEYWORD;
438 479
439 return result; 480 return match;
440 } 481 }
441 482
442 void KeywordProvider::Observe(int type, 483 void KeywordProvider::Observe(int type,
443 const NotificationSource& source, 484 const NotificationSource& source,
444 const NotificationDetails& details) { 485 const NotificationDetails& details) {
445 TemplateURLService* model = 486 TemplateURLService* model = GetTemplateURLService();
446 profile_ ? TemplateURLServiceFactory::GetForProfile(profile_) : model_;
447 const AutocompleteInput& input = extension_suggest_last_input_; 487 const AutocompleteInput& input = extension_suggest_last_input_;
448 488
449 switch (type) { 489 switch (type) {
450 case chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED: 490 case chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED:
451 // Input has been accepted, so we're done with this input session. Ensure 491 // Input has been accepted, so we're done with this input session. Ensure
452 // we don't send the OnInputCancelled event, or handle any more stray 492 // we don't send the OnInputCancelled event, or handle any more stray
453 // suggestions_ready events. 493 // suggestions_ready events.
454 current_keyword_extension_id_.clear(); 494 current_keyword_extension_id_.clear();
455 current_input_id_ = 0; 495 current_input_id_ = 0;
456 return; 496 return;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 listener_->OnProviderUpdate(!extension_suggest_matches_.empty()); 553 listener_->OnProviderUpdate(!extension_suggest_matches_.empty());
514 return; 554 return;
515 } 555 }
516 556
517 default: 557 default:
518 NOTREACHED(); 558 NOTREACHED();
519 return; 559 return;
520 } 560 }
521 } 561 }
522 562
563 TemplateURLService* KeywordProvider::GetTemplateURLService() const {
564 TemplateURLService* service = profile_ ?
565 TemplateURLServiceFactory::GetForProfile(profile_) : model_;
566 // Make sure the model is loaded. This is cheap and quickly bails out if
567 // the model is already loaded.
568 DCHECK(service);
569 service->Load();
570 return service;
571 }
572
523 void KeywordProvider::EnterExtensionKeywordMode( 573 void KeywordProvider::EnterExtensionKeywordMode(
524 const std::string& extension_id) { 574 const std::string& extension_id) {
525 DCHECK(current_keyword_extension_id_.empty()); 575 DCHECK(current_keyword_extension_id_.empty());
526 current_keyword_extension_id_ = extension_id; 576 current_keyword_extension_id_ = extension_id;
527 577
528 ExtensionOmniboxEventRouter::OnInputStarted( 578 ExtensionOmniboxEventRouter::OnInputStarted(
529 profile_, current_keyword_extension_id_); 579 profile_, current_keyword_extension_id_);
530 } 580 }
531 581
532 void KeywordProvider::MaybeEndExtensionKeywordMode() { 582 void KeywordProvider::MaybeEndExtensionKeywordMode() {
533 if (!current_keyword_extension_id_.empty()) { 583 if (!current_keyword_extension_id_.empty()) {
534 ExtensionOmniboxEventRouter::OnInputCancelled( 584 ExtensionOmniboxEventRouter::OnInputCancelled(
535 profile_, current_keyword_extension_id_); 585 profile_, current_keyword_extension_id_);
536 586
537 current_keyword_extension_id_.clear(); 587 current_keyword_extension_id_.clear();
538 } 588 }
539 } 589 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698