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

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

Issue 17022004: Replace --google-base-suggest-url and --instant-url with --google-base-url. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: 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 (c) 2012 The Chromium Authors. All rights reserved. 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 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/strings/string16.h" 10 #include "base/strings/string16.h"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 // Helper functor for Start(), for sorting keyword matches by quality. 79 // Helper functor for Start(), for sorting keyword matches by quality.
80 class CompareQuality { 80 class CompareQuality {
81 public: 81 public:
82 // A keyword is of higher quality when a greater fraction of it has been 82 // A keyword is of higher quality when a greater fraction of it has been
83 // typed, that is, when it is shorter. 83 // typed, that is, when it is shorter.
84 // 84 //
85 // TODO(pkasting): http://b/740691 Most recent and most frequent keywords are 85 // TODO(pkasting): http://b/740691 Most recent and most frequent keywords are
86 // probably better rankings than the fraction of the keyword typed. We should 86 // probably better rankings than the fraction of the keyword typed. We should
87 // always put any exact matches first no matter what, since the code in 87 // always put any exact matches first no matter what, since the code in
88 // Start() assumes this (and it makes sense). 88 // Start() assumes this (and it makes sense).
89 bool operator()(const string16& keyword1, 89 bool operator()(const TemplateURL* t_url1, const TemplateURL* t_url2) const {
90 const string16& keyword2) const { 90 return t_url1->keyword().length() < t_url2->keyword().length();
91 return keyword1.length() < keyword2.length();
92 } 91 }
93 }; 92 };
94 93
95 // We need our input IDs to be unique across all profiles, so we keep a global 94 // We need our input IDs to be unique across all profiles, so we keep a global
96 // UID that each provider uses. 95 // UID that each provider uses.
97 static int global_input_uid_; 96 static int global_input_uid_;
98 97
99 } // namespace 98 } // namespace
100 99
101 // static 100 // static
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 return string16(); 208 return string16();
210 } 209 }
211 210
212 return keyword; 211 return keyword;
213 } 212 }
214 213
215 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( 214 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
216 const string16& text, 215 const string16& text,
217 const string16& keyword, 216 const string16& keyword,
218 const AutocompleteInput& input) { 217 const AutocompleteInput& input) {
219 return CreateAutocompleteMatch(GetTemplateURLService(), keyword, input, 218 return CreateAutocompleteMatch(
220 keyword.size(), SplitReplacementStringFromInput(text, true), 0); 219 GetTemplateURLService()->GetTemplateURLForKeyword(keyword), input,
220 keyword.length(), SplitReplacementStringFromInput(text, true), 0);
221 } 221 }
222 222
223 void KeywordProvider::Start(const AutocompleteInput& input, 223 void KeywordProvider::Start(const AutocompleteInput& input,
224 bool minimal_changes) { 224 bool minimal_changes) {
225 // This object ensures we end keyword mode if we exit the function without 225 // This object ensures we end keyword mode if we exit the function without
226 // toggling keyword mode to on. 226 // toggling keyword mode to on.
227 ScopedEndExtensionKeywordMode keyword_mode_toggle(this); 227 ScopedEndExtensionKeywordMode keyword_mode_toggle(this);
228 228
229 matches_.clear(); 229 matches_.clear();
230 230
(...skipping 15 matching lines...) Expand all
246 // whatever we do here! 246 // whatever we do here!
247 // 247 //
248 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for 248 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for
249 // keywords, we might suggest keywords that haven't even been partially typed, 249 // keywords, we might suggest keywords that haven't even been partially typed,
250 // if the user uses them enough and isn't obviously typing something else. In 250 // if the user uses them enough and isn't obviously typing something else. In
251 // this case we'd consider all input here to be query input. 251 // this case we'd consider all input here to be query input.
252 string16 keyword, remaining_input; 252 string16 keyword, remaining_input;
253 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) 253 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input))
254 return; 254 return;
255 255
256 TemplateURLService* model = GetTemplateURLService();
257
258 // Get the best matches for this keyword. 256 // Get the best matches for this keyword.
259 // 257 //
260 // NOTE: We could cache the previous keywords and reuse them here in the 258 // NOTE: We could cache the previous keywords and reuse them here in the
261 // |minimal_changes| case, but since we'd still have to recalculate their 259 // |minimal_changes| case, but since we'd still have to recalculate their
262 // relevances and we can just recreate the results synchronously anyway, we 260 // relevances and we can just recreate the results synchronously anyway, we
263 // don't bother. 261 // don't bother.
264 // 262 //
265 // TODO(pkasting): http://b/893701 We should remember the user's use of a 263 // TODO(pkasting): http://b/893701 We should remember the user's use of a
266 // search query both from the autocomplete popup and from web pages 264 // search query both from the autocomplete popup and from web pages
267 // themselves. 265 // themselves.
268 std::vector<string16> keyword_matches; 266 TemplateURLService::TemplateURLVector matches;
269 model->FindMatchingKeywords(keyword, 267 GetTemplateURLService()->FindMatchingKeywords(
270 !remaining_input.empty(), 268 keyword, !remaining_input.empty(), &matches);
271 &keyword_matches);
272 269
273 for (std::vector<string16>::iterator i(keyword_matches.begin()); 270 for (TemplateURLService::TemplateURLVector::iterator i(matches.begin());
274 i != keyword_matches.end(); ) { 271 i != matches.end(); ) {
275 const TemplateURL* template_url = model->GetTemplateURLForKeyword(*i);
276
277 // Prune any extension keywords that are disallowed in incognito mode (if 272 // Prune any extension keywords that are disallowed in incognito mode (if
278 // we're incognito), or disabled. 273 // we're incognito), or disabled.
279 if (profile_ && template_url->IsExtensionKeyword()) { 274 if (profile_ && (*i)->IsExtensionKeyword()) {
280 ExtensionService* service = extensions::ExtensionSystem::Get(profile_)-> 275 ExtensionService* service = extensions::ExtensionSystem::Get(profile_)->
281 extension_service(); 276 extension_service();
282 const extensions::Extension* extension = service->GetExtensionById( 277 const extensions::Extension* extension =
283 template_url->GetExtensionId(), false); 278 service->GetExtensionById((*i)->GetExtensionId(), false);
284 bool enabled = 279 bool enabled =
285 extension && (!profile_->IsOffTheRecord() || 280 extension && (!profile_->IsOffTheRecord() ||
286 service->IsIncognitoEnabled(extension->id())); 281 service->IsIncognitoEnabled(extension->id()));
287 if (!enabled) { 282 if (!enabled) {
288 i = keyword_matches.erase(i); 283 i = matches.erase(i);
289 continue; 284 continue;
290 } 285 }
291 } 286 }
292 287
293 // Prune any substituting keywords if there is no substitution. 288 // Prune any substituting keywords if there is no substitution.
294 if (template_url->SupportsReplacement() && remaining_input.empty() && 289 if ((*i)->SupportsReplacement() && remaining_input.empty() &&
295 !input.allow_exact_keyword_match()) { 290 !input.allow_exact_keyword_match()) {
296 i = keyword_matches.erase(i); 291 i = matches.erase(i);
297 continue; 292 continue;
298 } 293 }
299 294
300 ++i; 295 ++i;
301 } 296 }
302 if (keyword_matches.empty()) 297 if (matches.empty())
303 return; 298 return;
304 std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality()); 299 std::sort(matches.begin(), matches.end(), CompareQuality());
305 300
306 // Limit to one exact or three inexact matches, and mark them up for display 301 // Limit to one exact or three inexact matches, and mark them up for display
307 // in the autocomplete popup. 302 // in the autocomplete popup.
308 // Any exact match is going to be the highest quality match, and thus at the 303 // Any exact match is going to be the highest quality match, and thus at the
309 // front of our vector. 304 // front of our vector.
310 if (keyword_matches.front() == keyword) { 305 if (matches.front()->keyword() == keyword) {
311 const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword); 306 const TemplateURL* template_url = matches.front();
312 const bool is_extension_keyword = template_url->IsExtensionKeyword(); 307 const bool is_extension_keyword = template_url->IsExtensionKeyword();
313 308
314 // Only create an exact match if |remaining_input| is empty or if 309 // Only create an exact match if |remaining_input| is empty or if
315 // this is an extension keyword. If |remaining_input| is a 310 // this is an extension keyword. If |remaining_input| is a
316 // non-empty non-extension keyword (i.e., a regular keyword that 311 // non-empty non-extension keyword (i.e., a regular keyword that
317 // supports replacement and that has extra text following it), 312 // supports replacement and that has extra text following it),
318 // then SearchProvider creates the exact (a.k.a. verbatim) match. 313 // then SearchProvider creates the exact (a.k.a. verbatim) match.
319 if (!remaining_input.empty() && !is_extension_keyword) 314 if (!remaining_input.empty() && !is_extension_keyword)
320 return; 315 return;
321 316
322 // TODO(pkasting): We should probably check that if the user explicitly 317 // TODO(pkasting): We should probably check that if the user explicitly
323 // typed a scheme, that scheme matches the one in |template_url|. 318 // typed a scheme, that scheme matches the one in |template_url|.
324 matches_.push_back(CreateAutocompleteMatch(model, keyword, input, 319 matches_.push_back(CreateAutocompleteMatch(
325 keyword.length(), 320 template_url, input, keyword.length(), remaining_input, -1));
326 remaining_input, -1));
327 321
328 if (profile_ && is_extension_keyword) { 322 if (profile_ && is_extension_keyword) {
329 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { 323 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) {
330 if (template_url->GetExtensionId() != current_keyword_extension_id_) 324 if (template_url->GetExtensionId() != current_keyword_extension_id_)
331 MaybeEndExtensionKeywordMode(); 325 MaybeEndExtensionKeywordMode();
332 if (current_keyword_extension_id_.empty()) 326 if (current_keyword_extension_id_.empty())
333 EnterExtensionKeywordMode(template_url->GetExtensionId()); 327 EnterExtensionKeywordMode(template_url->GetExtensionId());
334 keyword_mode_toggle.StayInKeywordMode(); 328 keyword_mode_toggle.StayInKeywordMode();
335 } 329 }
336 330
(...skipping 20 matching lines...) Expand all
357 profile_, template_url->GetExtensionId(), 351 profile_, template_url->GetExtensionId(),
358 UTF16ToUTF8(remaining_input), current_input_id_); 352 UTF16ToUTF8(remaining_input), current_input_id_);
359 353
360 // We only have to wait for suggest results if there are actually 354 // We only have to wait for suggest results if there are actually
361 // extensions listening for input changes. 355 // extensions listening for input changes.
362 if (have_listeners) 356 if (have_listeners)
363 done_ = false; 357 done_ = false;
364 } 358 }
365 } 359 }
366 } else { 360 } else {
367 if (keyword_matches.size() > kMaxMatches) { 361 if (matches.size() > kMaxMatches)
368 keyword_matches.erase(keyword_matches.begin() + kMaxMatches, 362 matches.erase(matches.begin() + kMaxMatches, matches.end());
369 keyword_matches.end()); 363 for (TemplateURLService::TemplateURLVector::const_iterator i(
370 } 364 matches.begin()); i != matches.end(); ++i) {
371 for (std::vector<string16>::const_iterator i(keyword_matches.begin()); 365 matches_.push_back(CreateAutocompleteMatch(
372 i != keyword_matches.end(); ++i) { 366 *i, input, keyword.length(), remaining_input, -1));
373 matches_.push_back(CreateAutocompleteMatch(model, *i,
374 input, keyword.length(),
375 remaining_input, -1));
376 } 367 }
377 } 368 }
378 } 369 }
379 370
380 void KeywordProvider::Stop(bool clear_cached_results) { 371 void KeywordProvider::Stop(bool clear_cached_results) {
381 done_ = true; 372 done_ = true;
382 MaybeEndExtensionKeywordMode(); 373 MaybeEndExtensionKeywordMode();
383 } 374 }
384 375
385 KeywordProvider::~KeywordProvider() {} 376 KeywordProvider::~KeywordProvider() {}
386 377
387 // static 378 // static
388 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input, 379 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input,
389 string16* keyword, 380 string16* keyword,
390 string16* remaining_input) { 381 string16* remaining_input) {
391 if ((input.type() == AutocompleteInput::INVALID) || 382 if ((input.type() == AutocompleteInput::INVALID) ||
392 (input.type() == AutocompleteInput::FORCED_QUERY)) 383 (input.type() == AutocompleteInput::FORCED_QUERY))
393 return false; 384 return false;
394 385
395 string16 trimmed_input; 386 string16 trimmed_input;
396 TrimWhitespace(input.text(), TRIM_TRAILING, &trimmed_input); 387 TrimWhitespace(input.text(), TRIM_TRAILING, &trimmed_input);
397 *keyword = TemplateURLService::CleanUserInputKeyword( 388 *keyword = TemplateURLService::CleanUserInputKeyword(
398 SplitKeywordFromInput(trimmed_input, true, remaining_input)); 389 SplitKeywordFromInput(trimmed_input, true, remaining_input));
399 return !keyword->empty(); 390 return !keyword->empty();
400 } 391 }
401 392
402 // static 393 // static
403 void KeywordProvider::FillInURLAndContents(
404 const string16& remaining_input,
405 const TemplateURL* element,
406 AutocompleteMatch* match) {
407 DCHECK(!element->short_name().empty());
408 const TemplateURLRef& element_ref = element->url_ref();
409 DCHECK(element_ref.IsValid());
410 int message_id = element->IsExtensionKeyword() ?
411 IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH;
412 if (remaining_input.empty()) {
413 // Allow extension keyword providers to accept empty string input. This is
414 // useful to allow extensions to do something in the case where no input is
415 // entered.
416 if (element_ref.SupportsReplacement() && !element->IsExtensionKeyword()) {
417 // No query input; return a generic, no-destination placeholder.
418 match->contents.assign(
419 l10n_util::GetStringFUTF16(message_id,
420 element->AdjustedShortNameForLocaleDirection(),
421 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
422 match->contents_class.push_back(
423 ACMatchClassification(0, ACMatchClassification::DIM));
424 } else {
425 // Keyword that has no replacement text (aka a shorthand for a URL).
426 match->destination_url = GURL(element->url());
427 match->contents.assign(element->short_name());
428 AutocompleteMatch::ClassifyLocationInString(0, match->contents.length(),
429 match->contents.length(), ACMatchClassification::NONE,
430 &match->contents_class);
431 }
432 } else {
433 // Create destination URL by escaping user input and substituting into
434 // keyword template URL. The escaping here handles whitespace in user
435 // input, but we rely on later canonicalization functions to do more
436 // fixup to make the URL valid if necessary.
437 DCHECK(element_ref.SupportsReplacement());
438 match->destination_url = GURL(element_ref.ReplaceSearchTerms(
439 TemplateURLRef::SearchTermsArgs(remaining_input)));
440 std::vector<size_t> content_param_offsets;
441 match->contents.assign(l10n_util::GetStringFUTF16(message_id,
442 element->short_name(),
443 remaining_input,
444 &content_param_offsets));
445 if (content_param_offsets.size() == 2) {
446 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
447 remaining_input.length(), match->contents.length(),
448 ACMatchClassification::NONE, &match->contents_class);
449 } else {
450 // See comments on an identical NOTREACHED() in search_provider.cc.
451 NOTREACHED();
452 }
453 }
454 }
455
456 // static
457 int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type, 394 int KeywordProvider::CalculateRelevance(AutocompleteInput::Type type,
458 bool complete, 395 bool complete,
459 bool supports_replacement, 396 bool supports_replacement,
460 bool prefer_keyword, 397 bool prefer_keyword,
461 bool allow_exact_keyword_match) { 398 bool allow_exact_keyword_match) {
462 // This function is responsible for scoring suggestions of keywords 399 // This function is responsible for scoring suggestions of keywords
463 // themselves and the suggestion of the verbatim query on an 400 // themselves and the suggestion of the verbatim query on an
464 // extension keyword. SearchProvider::CalculateRelevanceForKeywordVerbatim() 401 // extension keyword. SearchProvider::CalculateRelevanceForKeywordVerbatim()
465 // scores verbatim query suggestions for non-extension keywords. 402 // scores verbatim query suggestions for non-extension keywords.
466 // These two functions are currently in sync, but there's no reason 403 // These two functions are currently in sync, but there's no reason
467 // we couldn't decide in the future to score verbatim matches 404 // we couldn't decide in the future to score verbatim matches
468 // differently for extension and non-extension keywords. If you 405 // differently for extension and non-extension keywords. If you
469 // make such a change, however, you should update this comment to 406 // make such a change, however, you should update this comment to
470 // describe it, so it's clear why the functions diverge. 407 // describe it, so it's clear why the functions diverge.
471 if (!complete) 408 if (!complete)
472 return (type == AutocompleteInput::URL) ? 700 : 450; 409 return (type == AutocompleteInput::URL) ? 700 : 450;
473 if (!supports_replacement || (allow_exact_keyword_match && prefer_keyword)) 410 if (!supports_replacement || (allow_exact_keyword_match && prefer_keyword))
474 return 1500; 411 return 1500;
475 return (allow_exact_keyword_match && (type == AutocompleteInput::QUERY)) ? 412 return (allow_exact_keyword_match && (type == AutocompleteInput::QUERY)) ?
476 1450 : 1100; 413 1450 : 1100;
477 } 414 }
478 415
479 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( 416 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
480 TemplateURLService* model, 417 const TemplateURL* template_url,
481 const string16& keyword,
482 const AutocompleteInput& input, 418 const AutocompleteInput& input,
483 size_t prefix_length, 419 size_t prefix_length,
484 const string16& remaining_input, 420 const string16& remaining_input,
485 int relevance) { 421 int relevance) {
486 DCHECK(model); 422 DCHECK(template_url);
487 // Get keyword data from data store. 423 const bool supports_replacement =
488 TemplateURL* element = model->GetTemplateURLForKeyword(keyword); 424 template_url->url_ref().SupportsReplacement();
489 DCHECK(element);
490 const bool supports_replacement = element->url_ref().SupportsReplacement();
491 425
492 // Create an edit entry of "[keyword] [remaining input]". This is helpful 426 // Create an edit entry of "[keyword] [remaining input]". This is helpful
493 // even when [remaining input] is empty, as the user can select the popup 427 // even when [remaining input] is empty, as the user can select the popup
494 // choice and immediately begin typing in query input. 428 // choice and immediately begin typing in query input.
495 const bool keyword_complete = (prefix_length == keyword.length()); 429 const bool keyword_complete =
430 (prefix_length == template_url->keyword().length());
496 if (relevance < 0) { 431 if (relevance < 0) {
497 relevance = 432 relevance =
498 CalculateRelevance(input.type(), keyword_complete, 433 CalculateRelevance(input.type(), keyword_complete,
499 // When the user wants keyword matches to take 434 // When the user wants keyword matches to take
500 // preference, score them highly regardless of 435 // preference, score them highly regardless of
501 // whether the input provides query text. 436 // whether the input provides query text.
502 supports_replacement, input.prefer_keyword(), 437 supports_replacement, input.prefer_keyword(),
503 input.allow_exact_keyword_match()); 438 input.allow_exact_keyword_match());
504 } 439 }
505 AutocompleteMatch match(this, relevance, false, 440 AutocompleteMatch match(this, relevance, false,
506 supports_replacement ? AutocompleteMatchType::SEARCH_OTHER_ENGINE : 441 supports_replacement ? AutocompleteMatchType::SEARCH_OTHER_ENGINE :
507 AutocompleteMatchType::HISTORY_KEYWORD); 442 AutocompleteMatchType::HISTORY_KEYWORD);
508 match.fill_into_edit.assign(keyword); 443 match.fill_into_edit = template_url->keyword();
509 if (!remaining_input.empty() || !keyword_complete || supports_replacement) 444 if (!remaining_input.empty() || !keyword_complete || supports_replacement)
510 match.fill_into_edit.push_back(L' '); 445 match.fill_into_edit.push_back(L' ');
511 match.fill_into_edit.append(remaining_input); 446 match.fill_into_edit.append(remaining_input);
512 // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd 447 // If we wanted to set |result.inline_autocomplete_offset| correctly, we'd
513 // need CleanUserInputKeyword() to return the amount of adjustment it's made 448 // need CleanUserInputKeyword() to return the amount of adjustment it's made
514 // to the user's input. Because right now inexact keyword matches can't score 449 // to the user's input. Because right now inexact keyword matches can't score
515 // more highly than a "what you typed" match from one of the other providers, 450 // more highly than a "what you typed" match from one of the other providers,
516 // we just don't bother to do this, and leave inline autocompletion off. 451 // we just don't bother to do this, and leave inline autocompletion off.
517 match.inline_autocomplete_offset = string16::npos; 452 match.inline_autocomplete_offset = string16::npos;
518 453
519 // Create destination URL and popup entry content by substituting user input 454 // Create destination URL and popup entry content by substituting user input
520 // into keyword templates. 455 // into keyword templates.
521 FillInURLAndContents(remaining_input, element, &match); 456 FillInURLAndContents(remaining_input, template_url, &match);
522 457
523 match.keyword = keyword; 458 match.keyword = template_url->keyword();
524 match.transition = content::PAGE_TRANSITION_KEYWORD; 459 match.transition = content::PAGE_TRANSITION_KEYWORD;
525 460
526 return match; 461 return match;
527 } 462 }
528 463
464 void KeywordProvider::FillInURLAndContents(const string16& remaining_input,
465 const TemplateURL* element,
466 AutocompleteMatch* match) const {
467 DCHECK(!element->short_name().empty());
468 const TemplateURLRef& element_ref = element->url_ref();
469 DCHECK(element_ref.IsValid());
470 int message_id = element->IsExtensionKeyword() ?
471 IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH;
472 if (remaining_input.empty()) {
473 // Allow extension keyword providers to accept empty string input. This is
474 // useful to allow extensions to do something in the case where no input is
475 // entered.
476 if (element_ref.SupportsReplacement() && !element->IsExtensionKeyword()) {
477 // No query input; return a generic, no-destination placeholder.
478 match->contents.assign(
479 l10n_util::GetStringFUTF16(message_id,
480 element->AdjustedShortNameForLocaleDirection(),
481 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
482 match->contents_class.push_back(
483 ACMatchClassification(0, ACMatchClassification::DIM));
484 } else {
485 // Keyword that has no replacement text (aka a shorthand for a URL).
486 match->destination_url = GURL(element->url());
487 match->contents.assign(element->short_name());
488 AutocompleteMatch::ClassifyLocationInString(0, match->contents.length(),
489 match->contents.length(), ACMatchClassification::NONE,
490 &match->contents_class);
491 }
492 } else {
493 // Create destination URL by escaping user input and substituting into
494 // keyword template URL. The escaping here handles whitespace in user
495 // input, but we rely on later canonicalization functions to do more
496 // fixup to make the URL valid if necessary.
497 DCHECK(element_ref.SupportsReplacement());
498 TemplateURLRef::SearchTermsArgs search_terms_args(remaining_input);
499 search_terms_args.append_extra_query_params =
500 element == GetTemplateURLService()->GetDefaultSearchProvider();
501 match->destination_url =
502 GURL(element_ref.ReplaceSearchTerms(search_terms_args));
503 std::vector<size_t> content_param_offsets;
504 match->contents.assign(l10n_util::GetStringFUTF16(message_id,
505 element->short_name(),
506 remaining_input,
507 &content_param_offsets));
508 if (content_param_offsets.size() == 2) {
509 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
510 remaining_input.length(), match->contents.length(),
511 ACMatchClassification::NONE, &match->contents_class);
512 } else {
513 // See comments on an identical NOTREACHED() in search_provider.cc.
514 NOTREACHED();
515 }
516 }
517 }
518
529 void KeywordProvider::Observe(int type, 519 void KeywordProvider::Observe(int type,
530 const content::NotificationSource& source, 520 const content::NotificationSource& source,
531 const content::NotificationDetails& details) { 521 const content::NotificationDetails& details) {
532 TemplateURLService* model = GetTemplateURLService(); 522 TemplateURLService* model = GetTemplateURLService();
533 const AutocompleteInput& input = extension_suggest_last_input_; 523 const AutocompleteInput& input = extension_suggest_last_input_;
534 524
535 switch (type) { 525 switch (type) {
536 case chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED: 526 case chrome::NOTIFICATION_EXTENSION_OMNIBOX_INPUT_ENTERED:
537 // Input has been accepted, so we're done with this input session. Ensure 527 // Input has been accepted, so we're done with this input session. Ensure
538 // we don't send the OnInputCancelled event, or handle any more stray 528 // we don't send the OnInputCancelled event, or handle any more stray
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 const omnibox_api::SuggestResult& suggestion = 568 const omnibox_api::SuggestResult& suggestion =
579 *suggestions.suggest_results[i]; 569 *suggestions.suggest_results[i];
580 // We want to order these suggestions in descending order, so start with 570 // We want to order these suggestions in descending order, so start with
581 // the relevance of the first result (added synchronously in Start()), 571 // the relevance of the first result (added synchronously in Start()),
582 // and subtract 1 for each subsequent suggestion from the extension. 572 // and subtract 1 for each subsequent suggestion from the extension.
583 // We know that |complete| is true, because we wouldn't get results from 573 // We know that |complete| is true, because we wouldn't get results from
584 // the extension unless the full keyword had been typed. 574 // the extension unless the full keyword had been typed.
585 int first_relevance = CalculateRelevance(input.type(), true, true, 575 int first_relevance = CalculateRelevance(input.type(), true, true,
586 input.prefer_keyword(), input.allow_exact_keyword_match()); 576 input.prefer_keyword(), input.allow_exact_keyword_match());
587 extension_suggest_matches_.push_back(CreateAutocompleteMatch( 577 extension_suggest_matches_.push_back(CreateAutocompleteMatch(
588 model, keyword, input, keyword.length(), 578 model->GetTemplateURLForKeyword(keyword), input, keyword.length(),
589 UTF8ToUTF16(suggestion.content), first_relevance - (i + 1))); 579 UTF8ToUTF16(suggestion.content), first_relevance - (i + 1)));
590 580
591 AutocompleteMatch* match = &extension_suggest_matches_.back(); 581 AutocompleteMatch* match = &extension_suggest_matches_.back();
592 match->contents.assign(UTF8ToUTF16(suggestion.description)); 582 match->contents.assign(UTF8ToUTF16(suggestion.description));
593 match->contents_class = 583 match->contents_class =
594 extensions::StyleTypesToACMatchClassifications(suggestion); 584 extensions::StyleTypesToACMatchClassifications(suggestion);
595 match->description.clear(); 585 match->description.clear();
596 match->description_class.clear(); 586 match->description_class.clear();
597 } 587 }
598 588
(...skipping 30 matching lines...) Expand all
629 } 619 }
630 620
631 void KeywordProvider::MaybeEndExtensionKeywordMode() { 621 void KeywordProvider::MaybeEndExtensionKeywordMode() {
632 if (!current_keyword_extension_id_.empty()) { 622 if (!current_keyword_extension_id_.empty()) {
633 extensions::ExtensionOmniboxEventRouter::OnInputCancelled( 623 extensions::ExtensionOmniboxEventRouter::OnInputCancelled(
634 profile_, current_keyword_extension_id_); 624 profile_, current_keyword_extension_id_);
635 625
636 current_keyword_extension_id_.clear(); 626 current_keyword_extension_id_.clear();
637 } 627 }
638 } 628 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/keyword_provider.h ('k') | chrome/browser/autocomplete/keyword_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698