OLD | NEW |
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/autocomplete.h" | 5 #include "chrome/browser/autocomplete/autocomplete.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> |
8 | 9 |
9 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
10 #include "base/command_line.h" | 11 #include "base/command_line.h" |
11 #include "base/i18n/number_formatting.h" | 12 #include "base/i18n/number_formatting.h" |
12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
13 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
14 #include "base/string_util.h" | 15 #include "base/string_util.h" |
15 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" | 17 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" |
17 #include "chrome/browser/autocomplete/autocomplete_match.h" | 18 #include "chrome/browser/autocomplete/autocomplete_match.h" |
18 #include "chrome/browser/autocomplete/builtin_provider.h" | 19 #include "chrome/browser/autocomplete/builtin_provider.h" |
19 #include "chrome/browser/autocomplete/extension_app_provider.h" | 20 #include "chrome/browser/autocomplete/extension_app_provider.h" |
20 #include "chrome/browser/autocomplete/history_contents_provider.h" | 21 #include "chrome/browser/autocomplete/history_contents_provider.h" |
21 #include "chrome/browser/autocomplete/history_quick_provider.h" | 22 #include "chrome/browser/autocomplete/history_quick_provider.h" |
22 #include "chrome/browser/autocomplete/history_url_provider.h" | 23 #include "chrome/browser/autocomplete/history_url_provider.h" |
23 #include "chrome/browser/autocomplete/keyword_provider.h" | 24 #include "chrome/browser/autocomplete/keyword_provider.h" |
24 #include "chrome/browser/autocomplete/search_provider.h" | 25 #include "chrome/browser/autocomplete/search_provider.h" |
25 #include "chrome/browser/autocomplete/shortcuts_provider.h" | 26 #include "chrome/browser/autocomplete/shortcuts_provider.h" |
26 #include "chrome/browser/bookmarks/bookmark_model.h" | 27 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 28 #include "chrome/browser/extensions/extension_service.h" |
27 #include "chrome/browser/external_protocol/external_protocol_handler.h" | 29 #include "chrome/browser/external_protocol/external_protocol_handler.h" |
28 #include "chrome/browser/net/url_fixer_upper.h" | 30 #include "chrome/browser/net/url_fixer_upper.h" |
29 #include "chrome/browser/prefs/pref_service.h" | 31 #include "chrome/browser/prefs/pref_service.h" |
30 #include "chrome/browser/profiles/profile.h" | 32 #include "chrome/browser/profiles/profile.h" |
31 #include "chrome/browser/profiles/profile_io_data.h" | 33 #include "chrome/browser/profiles/profile_io_data.h" |
| 34 #include "chrome/browser/search_engines/template_url.h" |
| 35 #include "chrome/browser/search_engines/template_url_service.h" |
| 36 #include "chrome/browser/search_engines/template_url_service_factory.h" |
32 #include "chrome/browser/ui/webui/history_ui.h" | 37 #include "chrome/browser/ui/webui/history_ui.h" |
33 #include "chrome/common/chrome_notification_types.h" | 38 #include "chrome/common/chrome_notification_types.h" |
34 #include "chrome/common/chrome_switches.h" | 39 #include "chrome/common/chrome_switches.h" |
35 #include "chrome/common/pref_names.h" | 40 #include "chrome/common/pref_names.h" |
36 #include "chrome/common/url_constants.h" | 41 #include "chrome/common/url_constants.h" |
37 #include "content/common/notification_service.h" | 42 #include "content/common/notification_service.h" |
38 #include "googleurl/src/gurl.h" | 43 #include "googleurl/src/gurl.h" |
39 #include "googleurl/src/url_canon_ip.h" | 44 #include "googleurl/src/url_canon_ip.h" |
40 #include "googleurl/src/url_util.h" | 45 #include "googleurl/src/url_util.h" |
41 #include "grit/generated_resources.h" | 46 #include "grit/generated_resources.h" |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant); | 648 std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant); |
644 ACMatches::iterator::difference_type default_offset = | 649 ACMatches::iterator::difference_type default_offset = |
645 default_match_ - begin(); | 650 default_match_ - begin(); |
646 if ((insertion_point - begin()) <= default_offset) | 651 if ((insertion_point - begin()) <= default_offset) |
647 ++default_offset; | 652 ++default_offset; |
648 matches_.insert(insertion_point, match); | 653 matches_.insert(insertion_point, match); |
649 default_match_ = begin() + default_offset; | 654 default_match_ = begin() + default_offset; |
650 } | 655 } |
651 | 656 |
652 void AutocompleteResult::SortAndCull(const AutocompleteInput& input) { | 657 void AutocompleteResult::SortAndCull(const AutocompleteInput& input) { |
| 658 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) |
| 659 i->ComputeStrippedDestinationURL(); |
| 660 |
653 // Remove duplicates. | 661 // Remove duplicates. |
654 std::sort(matches_.begin(), matches_.end(), | 662 std::sort(matches_.begin(), matches_.end(), |
655 &AutocompleteMatch::DestinationSortFunc); | 663 &AutocompleteMatch::DestinationSortFunc); |
656 matches_.erase(std::unique(matches_.begin(), matches_.end(), | 664 matches_.erase(std::unique(matches_.begin(), matches_.end(), |
657 &AutocompleteMatch::DestinationsEqual), | 665 &AutocompleteMatch::DestinationsEqual), |
658 matches_.end()); | 666 matches_.end()); |
659 | 667 |
660 // Sort and trim to the most relevant kMaxMatches matches. | 668 // Sort and trim to the most relevant kMaxMatches matches. |
661 const size_t num_matches = std::min(kMaxMatches, matches_.size()); | 669 const size_t num_matches = std::min(kMaxMatches, matches_.size()); |
662 std::partial_sort(matches_.begin(), matches_.begin() + num_matches, | 670 std::partial_sort(matches_.begin(), matches_.begin() + num_matches, |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 // any copied entries. We do this from the time the user stopped typing as some | 794 // any copied entries. We do this from the time the user stopped typing as some |
787 // providers (such as SearchProvider) wait for the user to stop typing before | 795 // providers (such as SearchProvider) wait for the user to stop typing before |
788 // they initiate a query. | 796 // they initiate a query. |
789 static const int kExpireTimeMS = 500; | 797 static const int kExpireTimeMS = 500; |
790 | 798 |
791 AutocompleteController::AutocompleteController( | 799 AutocompleteController::AutocompleteController( |
792 Profile* profile, | 800 Profile* profile, |
793 AutocompleteControllerDelegate* delegate) | 801 AutocompleteControllerDelegate* delegate) |
794 : delegate_(delegate), | 802 : delegate_(delegate), |
795 done_(true), | 803 done_(true), |
796 in_start_(false) { | 804 in_start_(false), |
| 805 profile_(profile) { |
797 search_provider_ = new SearchProvider(this, profile); | 806 search_provider_ = new SearchProvider(this, profile); |
798 providers_.push_back(search_provider_); | 807 providers_.push_back(search_provider_); |
799 // TODO(mrossetti): Remove the following and permanently modify the | 808 // TODO(mrossetti): Remove the following and permanently modify the |
800 // HistoryURLProvider to not search titles once HQP is turned on permanently. | 809 // HistoryURLProvider to not search titles once HQP is turned on permanently. |
801 bool hqp_enabled = !CommandLine::ForCurrentProcess()->HasSwitch( | 810 bool hqp_enabled = !CommandLine::ForCurrentProcess()->HasSwitch( |
802 switches::kDisableHistoryQuickProvider); | 811 switches::kDisableHistoryQuickProvider); |
803 if (hqp_enabled) | 812 if (hqp_enabled) |
804 providers_.push_back(new HistoryQuickProvider(this, profile)); | 813 providers_.push_back(new HistoryQuickProvider(this, profile)); |
805 if (CommandLine::ForCurrentProcess()->HasSwitch( | 814 if (CommandLine::ForCurrentProcess()->HasSwitch( |
806 switches::kEnableShortcutsProvider)) | 815 switches::kEnableShortcutsProvider)) |
(...skipping 21 matching lines...) Expand all Loading... |
828 Stop(false); | 837 Stop(false); |
829 | 838 |
830 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | 839 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) |
831 (*i)->Release(); | 840 (*i)->Release(); |
832 | 841 |
833 providers_.clear(); // Not really necessary. | 842 providers_.clear(); // Not really necessary. |
834 } | 843 } |
835 | 844 |
836 void AutocompleteController::SetProfile(Profile* profile) { | 845 void AutocompleteController::SetProfile(Profile* profile) { |
837 Stop(true); | 846 Stop(true); |
| 847 profile_ = profile; |
838 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | 848 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) |
839 (*i)->SetProfile(profile); | 849 (*i)->SetProfile(profile); |
840 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a | 850 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a |
841 // different profile. | 851 // different profile. |
842 } | 852 } |
843 | 853 |
844 void AutocompleteController::Start( | 854 void AutocompleteController::Start( |
845 const string16& text, | 855 const string16& text, |
846 const string16& desired_tld, | 856 const string16& desired_tld, |
847 bool prevent_inline_autocomplete, | 857 bool prevent_inline_autocomplete, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
941 AutocompleteResult last_result; | 951 AutocompleteResult last_result; |
942 last_result.Swap(&result_); | 952 last_result.Swap(&result_); |
943 | 953 |
944 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 954 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
945 ++i) | 955 ++i) |
946 result_.AppendMatches((*i)->matches()); | 956 result_.AppendMatches((*i)->matches()); |
947 | 957 |
948 // Sort the matches and trim to a small number of "best" matches. | 958 // Sort the matches and trim to a small number of "best" matches. |
949 result_.SortAndCull(input_); | 959 result_.SortAndCull(input_); |
950 | 960 |
| 961 std::set<string16> keywords; |
| 962 for (ACMatches::iterator match(result_.begin()); match != result_.end(); |
| 963 ++match) { |
| 964 if (!match->keyword.empty()) { |
| 965 keywords.insert(match->keyword); |
| 966 } else { |
| 967 string16 keyword = GetKeywordForText(match->fill_into_edit); |
| 968 |
| 969 // Only add the keyword if the match does not have a duplicate keyword |
| 970 // with a more relevant match. |
| 971 if (!keyword.empty() && !keywords.count(keyword)) { |
| 972 match->associated_keyword.reset(new AutocompleteMatch( |
| 973 keyword_provider_->CreateAutocompleteMatch( |
| 974 TemplateURLServiceFactory::GetForProfile(profile_), keyword, |
| 975 input_))); |
| 976 |
| 977 keywords.insert(keyword); |
| 978 } |
| 979 } |
| 980 } |
| 981 |
951 // Need to validate before invoking CopyOldMatches as the old matches are not | 982 // Need to validate before invoking CopyOldMatches as the old matches are not |
952 // valid against the current input. | 983 // valid against the current input. |
953 #ifndef NDEBUG | 984 #ifndef NDEBUG |
954 result_.Validate(); | 985 result_.Validate(); |
955 #endif | 986 #endif |
956 | 987 |
957 if (!done_) { | 988 if (!done_) { |
958 // This conditional needs to match the conditional in Start that invokes | 989 // This conditional needs to match the conditional in Start that invokes |
959 // StartExpireTimer. | 990 // StartExpireTimer. |
960 result_.CopyOldMatches(input_, last_result); | 991 result_.CopyOldMatches(input_, last_result); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 } | 1059 } |
1029 } | 1060 } |
1030 done_ = true; | 1061 done_ = true; |
1031 } | 1062 } |
1032 | 1063 |
1033 void AutocompleteController::StartExpireTimer() { | 1064 void AutocompleteController::StartExpireTimer() { |
1034 if (result_.HasCopiedMatches()) | 1065 if (result_.HasCopiedMatches()) |
1035 expire_timer_.Start(base::TimeDelta::FromMilliseconds(kExpireTimeMS), | 1066 expire_timer_.Start(base::TimeDelta::FromMilliseconds(kExpireTimeMS), |
1036 this, &AutocompleteController::ExpireCopiedEntries); | 1067 this, &AutocompleteController::ExpireCopiedEntries); |
1037 } | 1068 } |
| 1069 |
| 1070 string16 AutocompleteController::GetKeywordForText( |
| 1071 const string16& text) const { |
| 1072 const string16 keyword(TemplateURLService::CleanUserInputKeyword(text)); |
| 1073 |
| 1074 if (keyword.empty()) |
| 1075 return keyword; |
| 1076 |
| 1077 TemplateURLService* url_service = |
| 1078 TemplateURLServiceFactory::GetForProfile(profile_); |
| 1079 if (!url_service) |
| 1080 return string16(); |
| 1081 url_service->Load(); |
| 1082 |
| 1083 // Don't provide a keyword if it doesn't support replacement. |
| 1084 const TemplateURL* const template_url = |
| 1085 url_service->GetTemplateURLForKeyword(keyword); |
| 1086 if (!TemplateURL::SupportsReplacement(template_url)) |
| 1087 return string16(); |
| 1088 |
| 1089 // Don't provide a keyword for inactive/disabled extension keywords. |
| 1090 if (template_url->IsExtensionKeyword()) { |
| 1091 const Extension* extension = profile_->GetExtensionService()-> |
| 1092 GetExtensionById(template_url->GetExtensionId(), false); |
| 1093 if (!extension || |
| 1094 (profile_->IsOffTheRecord() && |
| 1095 !profile_->GetExtensionService()->IsIncognitoEnabled(extension->id()))) |
| 1096 return string16(); |
| 1097 } |
| 1098 |
| 1099 return keyword; |
| 1100 } |
| 1101 |
OLD | NEW |