Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 | 54 |
| 55 KeywordProvider::KeywordProvider(ACProviderListener* listener, Profile* profile) | 55 KeywordProvider::KeywordProvider(ACProviderListener* listener, Profile* profile) |
| 56 : AutocompleteProvider(listener, profile, "Keyword"), | 56 : AutocompleteProvider(listener, profile, "Keyword"), |
| 57 model_(NULL), | 57 model_(NULL), |
| 58 current_input_id_(0) { | 58 current_input_id_(0) { |
| 59 // Extension suggestions always come from the original profile, since that's | 59 // Extension suggestions always come from the original profile, since that's |
| 60 // where extensions run. We use the input ID to distinguish whether the | 60 // where extensions run. We use the input ID to distinguish whether the |
| 61 // suggestions are meant for us. | 61 // suggestions are meant for us. |
| 62 registrar_.Add(this, NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY, | 62 registrar_.Add(this, NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY, |
| 63 Source<Profile>(profile->GetOriginalProfile())); | 63 Source<Profile>(profile->GetOriginalProfile())); |
| 64 registrar_.Add(this, | |
| 65 NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED, | |
| 66 Source<Profile>(profile->GetOriginalProfile())); | |
| 64 registrar_.Add(this, NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED, | 67 registrar_.Add(this, NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED, |
| 65 Source<Profile>(profile)); | 68 Source<Profile>(profile)); |
| 66 } | 69 } |
| 67 | 70 |
| 68 KeywordProvider::KeywordProvider(ACProviderListener* listener, | 71 KeywordProvider::KeywordProvider(ACProviderListener* listener, |
| 69 TemplateURLModel* model) | 72 TemplateURLModel* model) |
| 70 : AutocompleteProvider(listener, NULL, "Keyword"), | 73 : AutocompleteProvider(listener, NULL, "Keyword"), |
| 71 model_(model), | 74 model_(model), |
| 72 current_input_id_(0) { | 75 current_input_id_(0) { |
| 73 } | 76 } |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 ACMatchClassification::DIM, | 429 ACMatchClassification::DIM, |
| 427 &result.description_class); | 430 &result.description_class); |
| 428 } | 431 } |
| 429 | 432 |
| 430 return result; | 433 return result; |
| 431 } | 434 } |
| 432 | 435 |
| 433 void KeywordProvider::Observe(NotificationType type, | 436 void KeywordProvider::Observe(NotificationType type, |
| 434 const NotificationSource& source, | 437 const NotificationSource& source, |
| 435 const NotificationDetails& details) { | 438 const NotificationDetails& details) { |
| 436 if (type == NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED) { | 439 TemplateURLModel* model = profile_ ? profile_->GetTemplateURLModel() : model_; |
| 437 // Input has been accepted, so we're done with this input session. Ensure | 440 const AutocompleteInput& input = extension_suggest_last_input_; |
| 438 // we don't send the OnInputCancelled event. | 441 |
| 439 current_keyword_extension_id_.clear(); | 442 switch (type.value) { |
| 440 return; | 443 case NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED: |
| 444 // Input has been accepted, so we're done with this input session. Ensure | |
| 445 // we don't send the OnInputCancelled event. | |
| 446 current_keyword_extension_id_.clear(); | |
| 447 break; | |
|
Peter Kasting
2010/12/06 20:05:53
Nit: Using "return" instead of "break" makes life
Matt Perry
2010/12/07 00:10:18
Done.
| |
| 448 | |
| 449 case NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED: { | |
| 450 // It's possible to change the default suggestion while not in an editing | |
| 451 // session. | |
| 452 std::wstring keyword, remaining_input; | |
| 453 if (matches_.empty() || current_keyword_extension_id_.empty() || | |
| 454 !ExtractKeywordFromInput(input, &keyword, &remaining_input)) | |
|
Peter Kasting
2010/12/06 20:05:53
Is ExtractKeywordFromInput() supposed to guarantee
Matt Perry
2010/12/07 00:10:18
I *think* it should as long as the first 2 clauses
| |
| 455 return; | |
| 456 | |
| 457 const TemplateURL* template_url(model->GetTemplateURLForKeyword(keyword)); | |
| 458 ApplyDefaultSuggestionForExtensionKeyword(profile_, template_url, | |
| 459 WideToUTF16(remaining_input), | |
| 460 &matches_[0]); | |
| 461 listener_->OnProviderUpdate(true); | |
| 462 break; | |
| 463 } | |
| 464 | |
| 465 case NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY: { | |
| 466 const ExtensionOmniboxSuggestions& suggestions = | |
| 467 *Details<ExtensionOmniboxSuggestions>(details).ptr(); | |
| 468 if (suggestions.request_id != current_input_id_) | |
| 469 return; // This is an old result. Just ignore. | |
| 470 | |
| 471 // TODO(mpcomplete): consider clamping the number of suggestions to | |
|
Peter Kasting
2010/12/06 20:05:53
Nit: Doesn't this TODO belong on the next block?
Matt Perry
2010/12/07 00:10:18
I've moved the TODO. I think I'm going to wait unt
| |
| 472 // AutocompleteProvider::kMaxMatches. | |
| 473 std::wstring keyword, remaining_input; | |
| 474 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) { | |
| 475 NOTREACHED(); | |
| 476 return; | |
| 477 } | |
| 478 | |
| 479 for (size_t i = 0; i < suggestions.suggestions.size(); ++i) { | |
| 480 const ExtensionOmniboxSuggestion& suggestion = | |
| 481 suggestions.suggestions[i]; | |
|
Peter Kasting
2010/12/06 20:05:53
Nit: You could probably avoid this temp by using a
Matt Perry
2010/12/07 00:10:18
I also need the index for the relevance calculatio
| |
| 482 // We want to order these suggestions in descending order, so start with | |
| 483 // the relevance of the first result (added synchronously in Start()), | |
| 484 // and subtract 1 for each subsequent suggestion from the extension. | |
| 485 // We know that |complete| is true, because we wouldn't get results from | |
| 486 // the extension unless the full keyword had been typed. | |
| 487 int first_relevance = CalculateRelevance(input.type(), true, | |
| 488 input.prefer_keyword(), input.allow_exact_keyword_match()); | |
| 489 extension_suggest_matches_.push_back(CreateAutocompleteMatch( | |
| 490 model, keyword, input, keyword.length(), | |
| 491 UTF16ToWide(suggestion.content), first_relevance - (i + 1))); | |
| 492 | |
| 493 AutocompleteMatch* match = &extension_suggest_matches_.back(); | |
| 494 match->contents.assign(UTF16ToWide(suggestion.description)); | |
| 495 match->contents_class = suggestion.description_styles; | |
| 496 match->description.clear(); | |
| 497 match->description_class.clear(); | |
| 498 } | |
| 499 | |
| 500 done_ = true; | |
| 501 matches_.insert(matches_.end(), extension_suggest_matches_.begin(), | |
| 502 extension_suggest_matches_.end()); | |
| 503 listener_->OnProviderUpdate(!extension_suggest_matches_.empty()); | |
| 504 break; | |
| 505 } | |
| 506 | |
| 507 default: | |
| 508 NOTREACHED(); | |
| 509 break; | |
| 441 } | 510 } |
| 442 | |
| 443 // TODO(mpcomplete): consider clamping the number of suggestions to | |
| 444 // AutocompleteProvider::kMaxMatches. | |
| 445 DCHECK(type == NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY); | |
| 446 | |
| 447 const ExtensionOmniboxSuggestions& suggestions = | |
| 448 *Details<ExtensionOmniboxSuggestions>(details).ptr(); | |
| 449 if (suggestions.request_id != current_input_id_) | |
| 450 return; // This is an old result. Just ignore. | |
| 451 | |
| 452 const AutocompleteInput& input = extension_suggest_last_input_; | |
| 453 std::wstring keyword, remaining_input; | |
| 454 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) { | |
| 455 NOTREACHED(); | |
| 456 return; | |
| 457 } | |
| 458 | |
| 459 TemplateURLModel* model = | |
| 460 profile_ ? profile_->GetTemplateURLModel() : model_; | |
| 461 | |
| 462 for (size_t i = 0; i < suggestions.suggestions.size(); ++i) { | |
| 463 const ExtensionOmniboxSuggestion& suggestion = suggestions.suggestions[i]; | |
| 464 // We want to order these suggestions in descending order, so start with | |
| 465 // the relevance of the first result (added synchronously in Start()), | |
| 466 // and subtract 1 for each subsequent suggestion from the extension. | |
| 467 // We know that |complete| is true, because we wouldn't get results from | |
| 468 // the extension unless the full keyword had been typed. | |
| 469 int first_relevance = CalculateRelevance(input.type(), true, | |
| 470 input.prefer_keyword(), input.allow_exact_keyword_match()); | |
| 471 extension_suggest_matches_.push_back(CreateAutocompleteMatch( | |
| 472 model, keyword, input, keyword.length(), | |
| 473 UTF16ToWide(suggestion.content), first_relevance - (i + 1))); | |
| 474 | |
| 475 AutocompleteMatch* match = &extension_suggest_matches_.back(); | |
| 476 match->contents.assign(UTF16ToWide(suggestion.description)); | |
| 477 match->contents_class = suggestion.description_styles; | |
| 478 match->description.clear(); | |
| 479 match->description_class.clear(); | |
| 480 } | |
| 481 | |
| 482 done_ = true; | |
| 483 matches_.insert(matches_.end(), extension_suggest_matches_.begin(), | |
| 484 extension_suggest_matches_.end()); | |
| 485 listener_->OnProviderUpdate(!extension_suggest_matches_.empty()); | |
| 486 } | 511 } |
| 487 | 512 |
| 488 void KeywordProvider::EnterExtensionKeywordMode( | 513 void KeywordProvider::EnterExtensionKeywordMode( |
| 489 const std::string& extension_id) { | 514 const std::string& extension_id) { |
| 490 DCHECK(current_keyword_extension_id_.empty()); | 515 DCHECK(current_keyword_extension_id_.empty()); |
| 491 current_keyword_extension_id_ = extension_id; | 516 current_keyword_extension_id_ = extension_id; |
| 492 | 517 |
| 493 ExtensionOmniboxEventRouter::OnInputStarted( | 518 ExtensionOmniboxEventRouter::OnInputStarted( |
| 494 profile_, current_keyword_extension_id_); | 519 profile_, current_keyword_extension_id_); |
| 495 } | 520 } |
| 496 | 521 |
| 497 void KeywordProvider::MaybeEndExtensionKeywordMode() { | 522 void KeywordProvider::MaybeEndExtensionKeywordMode() { |
| 498 if (!current_keyword_extension_id_.empty()) { | 523 if (!current_keyword_extension_id_.empty()) { |
| 499 ExtensionOmniboxEventRouter::OnInputCancelled( | 524 ExtensionOmniboxEventRouter::OnInputCancelled( |
| 500 profile_, current_keyword_extension_id_); | 525 profile_, current_keyword_extension_id_); |
| 501 | 526 |
| 502 current_keyword_extension_id_.clear(); | 527 current_keyword_extension_id_.clear(); |
| 503 } | 528 } |
| 504 } | 529 } |
| OLD | NEW |