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> | |
9 #include <utility> | |
8 | 10 |
9 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
10 #include "base/command_line.h" | 12 #include "base/command_line.h" |
11 #include "base/i18n/number_formatting.h" | 13 #include "base/i18n/number_formatting.h" |
12 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
13 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
14 #include "base/string_util.h" | 16 #include "base/string_util.h" |
15 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" | 18 #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" |
17 #include "chrome/browser/autocomplete/autocomplete_match.h" | 19 #include "chrome/browser/autocomplete/autocomplete_match.h" |
18 #include "chrome/browser/autocomplete/builtin_provider.h" | 20 #include "chrome/browser/autocomplete/builtin_provider.h" |
19 #include "chrome/browser/autocomplete/extension_app_provider.h" | 21 #include "chrome/browser/autocomplete/extension_app_provider.h" |
20 #include "chrome/browser/autocomplete/history_contents_provider.h" | 22 #include "chrome/browser/autocomplete/history_contents_provider.h" |
21 #include "chrome/browser/autocomplete/history_quick_provider.h" | 23 #include "chrome/browser/autocomplete/history_quick_provider.h" |
22 #include "chrome/browser/autocomplete/history_url_provider.h" | 24 #include "chrome/browser/autocomplete/history_url_provider.h" |
23 #include "chrome/browser/autocomplete/keyword_provider.h" | 25 #include "chrome/browser/autocomplete/keyword_provider.h" |
24 #include "chrome/browser/autocomplete/search_provider.h" | 26 #include "chrome/browser/autocomplete/search_provider.h" |
25 #include "chrome/browser/bookmarks/bookmark_model.h" | 27 #include "chrome/browser/bookmarks/bookmark_model.h" |
28 #include "chrome/browser/extensions/extension_service.h" | |
26 #include "chrome/browser/external_protocol_handler.h" | 29 #include "chrome/browser/external_protocol_handler.h" |
27 #include "chrome/browser/net/url_fixer_upper.h" | 30 #include "chrome/browser/net/url_fixer_upper.h" |
28 #include "chrome/browser/prefs/pref_service.h" | 31 #include "chrome/browser/prefs/pref_service.h" |
29 #include "chrome/browser/profiles/profile.h" | 32 #include "chrome/browser/profiles/profile.h" |
33 #include "chrome/browser/search_engines/template_url.h" | |
34 #include "chrome/browser/search_engines/template_url_model.h" | |
30 #include "chrome/browser/ui/webui/history_ui.h" | 35 #include "chrome/browser/ui/webui/history_ui.h" |
31 #include "chrome/common/chrome_switches.h" | 36 #include "chrome/common/chrome_switches.h" |
32 #include "chrome/common/pref_names.h" | 37 #include "chrome/common/pref_names.h" |
33 #include "chrome/common/url_constants.h" | 38 #include "chrome/common/url_constants.h" |
34 #include "content/common/notification_service.h" | 39 #include "content/common/notification_service.h" |
35 #include "googleurl/src/gurl.h" | 40 #include "googleurl/src/gurl.h" |
36 #include "googleurl/src/url_canon_ip.h" | 41 #include "googleurl/src/url_canon_ip.h" |
37 #include "googleurl/src/url_util.h" | 42 #include "googleurl/src/url_util.h" |
38 #include "grit/generated_resources.h" | 43 #include "grit/generated_resources.h" |
39 #include "grit/theme_resources.h" | 44 #include "grit/theme_resources.h" |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant); | 640 std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant); |
636 ACMatches::iterator::difference_type default_offset = | 641 ACMatches::iterator::difference_type default_offset = |
637 default_match_ - begin(); | 642 default_match_ - begin(); |
638 if ((insertion_point - begin()) <= default_offset) | 643 if ((insertion_point - begin()) <= default_offset) |
639 ++default_offset; | 644 ++default_offset; |
640 matches_.insert(insertion_point, match); | 645 matches_.insert(insertion_point, match); |
641 default_match_ = begin() + default_offset; | 646 default_match_ = begin() + default_offset; |
642 } | 647 } |
643 | 648 |
644 void AutocompleteResult::SortAndCull(const AutocompleteInput& input) { | 649 void AutocompleteResult::SortAndCull(const AutocompleteInput& input) { |
650 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) | |
651 i->ComputeStrippedDestinationURL(); | |
652 | |
645 // Remove duplicates. | 653 // Remove duplicates. |
646 std::sort(matches_.begin(), matches_.end(), | 654 std::sort(matches_.begin(), matches_.end(), |
647 &AutocompleteMatch::DestinationSortFunc); | 655 &AutocompleteMatch::DestinationSortFunc); |
648 matches_.erase(std::unique(matches_.begin(), matches_.end(), | 656 matches_.erase(std::unique(matches_.begin(), matches_.end(), |
649 &AutocompleteMatch::DestinationsEqual), | 657 &AutocompleteMatch::DestinationsEqual), |
650 matches_.end()); | 658 matches_.end()); |
651 | 659 |
652 // Sort and trim to the most relevant kMaxMatches matches. | 660 // Sort and trim to the most relevant kMaxMatches matches. |
653 const size_t num_matches = std::min(kMaxMatches, matches_.size()); | 661 const size_t num_matches = std::min(kMaxMatches, matches_.size()); |
654 std::partial_sort(matches_.begin(), matches_.begin() + num_matches, | 662 std::partial_sort(matches_.begin(), matches_.begin() + num_matches, |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 // any copied entries. We do this from the time the user stopped typing as some | 786 // any copied entries. We do this from the time the user stopped typing as some |
779 // providers (such as SearchProvider) wait for the user to stop typing before | 787 // providers (such as SearchProvider) wait for the user to stop typing before |
780 // they initiate a query. | 788 // they initiate a query. |
781 static const int kExpireTimeMS = 500; | 789 static const int kExpireTimeMS = 500; |
782 | 790 |
783 AutocompleteController::AutocompleteController( | 791 AutocompleteController::AutocompleteController( |
784 Profile* profile, | 792 Profile* profile, |
785 AutocompleteControllerDelegate* delegate) | 793 AutocompleteControllerDelegate* delegate) |
786 : delegate_(delegate), | 794 : delegate_(delegate), |
787 done_(true), | 795 done_(true), |
788 in_start_(false) { | 796 in_start_(false), |
797 profile_(profile) { | |
789 search_provider_ = new SearchProvider(this, profile); | 798 search_provider_ = new SearchProvider(this, profile); |
790 providers_.push_back(search_provider_); | 799 providers_.push_back(search_provider_); |
791 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 800 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
792 switches::kDisableHistoryQuickProvider)) | 801 switches::kDisableHistoryQuickProvider)) |
793 providers_.push_back(new HistoryQuickProvider(this, profile)); | 802 providers_.push_back(new HistoryQuickProvider(this, profile)); |
794 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 803 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
795 switches::kDisableHistoryURLProvider)) | 804 switches::kDisableHistoryURLProvider)) |
796 providers_.push_back(new HistoryURLProvider(this, profile)); | 805 providers_.push_back(new HistoryURLProvider(this, profile)); |
797 providers_.push_back(new KeywordProvider(this, profile)); | 806 providers_.push_back(new KeywordProvider(this, profile)); |
798 providers_.push_back(new HistoryContentsProvider(this, profile)); | 807 providers_.push_back(new HistoryContentsProvider(this, profile)); |
(...skipping 14 matching lines...) Expand all Loading... | |
813 Stop(false); | 822 Stop(false); |
814 | 823 |
815 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | 824 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) |
816 (*i)->Release(); | 825 (*i)->Release(); |
817 | 826 |
818 providers_.clear(); // Not really necessary. | 827 providers_.clear(); // Not really necessary. |
819 } | 828 } |
820 | 829 |
821 void AutocompleteController::SetProfile(Profile* profile) { | 830 void AutocompleteController::SetProfile(Profile* profile) { |
822 Stop(true); | 831 Stop(true); |
832 profile_ = profile; | |
823 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | 833 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) |
824 (*i)->SetProfile(profile); | 834 (*i)->SetProfile(profile); |
825 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a | 835 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a |
826 // different profile. | 836 // different profile. |
827 } | 837 } |
828 | 838 |
829 void AutocompleteController::Start( | 839 void AutocompleteController::Start( |
830 const string16& text, | 840 const string16& text, |
831 const string16& desired_tld, | 841 const string16& desired_tld, |
832 bool prevent_inline_autocomplete, | 842 bool prevent_inline_autocomplete, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
925 AutocompleteResult last_result; | 935 AutocompleteResult last_result; |
926 last_result.Swap(&result_); | 936 last_result.Swap(&result_); |
927 | 937 |
928 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 938 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
929 ++i) | 939 ++i) |
930 result_.AppendMatches((*i)->matches()); | 940 result_.AppendMatches((*i)->matches()); |
931 | 941 |
932 // Sort the matches and trim to a small number of "best" matches. | 942 // Sort the matches and trim to a small number of "best" matches. |
933 result_.SortAndCull(input_); | 943 result_.SortAndCull(input_); |
934 | 944 |
945 std::set<string16> keywords; | |
946 for (ACMatches::iterator match(result_.begin()); match != result_.end(); | |
947 ++match) { | |
948 string16 keyword_text = GetKeywordForText(match->fill_into_edit); | |
Peter Kasting
2011/04/11 23:17:33
Nit: This should be moved inside the first "else"
| |
949 bool is_keyword_hint = false; | |
950 bool is_keyword_mode = false; | |
951 | |
952 // If the current match is a keyword, assign that as the selected keyword. | |
953 if (TemplateURL::SupportsReplacement(match->template_url)) { | |
954 keyword_text.assign(match->template_url->keyword()); | |
Peter Kasting
2011/04/11 23:17:33
Nit: Indent 2, not 4
| |
955 is_keyword_mode = true; | |
956 } else if (!keyword_text.empty()) { | |
957 is_keyword_hint = true; | |
958 } | |
959 | |
960 if (is_keyword_hint || is_keyword_mode) { | |
961 std::pair<std::set<string16>::iterator, bool> result = | |
Peter Kasting
2011/04/11 23:17:33
Nit: Instead of getting the result pair and checki
| |
962 keywords.insert(keyword_text); | |
963 | |
964 // Only add the keyword if the match does not have a duplicate keyword | |
965 // with a more relevant match. | |
966 if (result.second) { | |
967 match->keyword = new AutocompleteMatch::Keyword( | |
Peter Kasting
2011/04/11 23:17:33
Nit: Seems like Keyword's constructor should init
| |
968 keyword_text, is_keyword_hint, is_keyword_mode); | |
969 | |
970 if (is_keyword_hint) | |
971 match->keyword->template_url = profile_->GetTemplateURLModel()-> | |
972 GetTemplateURLForKeyword(keyword_text); | |
973 } | |
974 } | |
975 } | |
976 | |
935 // Need to validate before invoking CopyOldMatches as the old matches are not | 977 // Need to validate before invoking CopyOldMatches as the old matches are not |
936 // valid against the current input. | 978 // valid against the current input. |
937 #ifndef NDEBUG | 979 #ifndef NDEBUG |
938 result_.Validate(); | 980 result_.Validate(); |
939 #endif | 981 #endif |
940 | 982 |
941 if (!done_) { | 983 if (!done_) { |
942 // This conditional needs to match the conditional in Start that invokes | 984 // This conditional needs to match the conditional in Start that invokes |
943 // StartExpireTimer. | 985 // StartExpireTimer. |
944 result_.CopyOldMatches(input_, last_result); | 986 result_.CopyOldMatches(input_, last_result); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
983 } | 1025 } |
984 } | 1026 } |
985 done_ = true; | 1027 done_ = true; |
986 } | 1028 } |
987 | 1029 |
988 void AutocompleteController::StartExpireTimer() { | 1030 void AutocompleteController::StartExpireTimer() { |
989 if (result_.HasCopiedMatches()) | 1031 if (result_.HasCopiedMatches()) |
990 expire_timer_.Start(base::TimeDelta::FromMilliseconds(kExpireTimeMS), | 1032 expire_timer_.Start(base::TimeDelta::FromMilliseconds(kExpireTimeMS), |
991 this, &AutocompleteController::ExpireCopiedEntries); | 1033 this, &AutocompleteController::ExpireCopiedEntries); |
992 } | 1034 } |
1035 | |
1036 string16 AutocompleteController::GetKeywordForText( | |
1037 const string16& text) const { | |
Peter Kasting
2011/04/11 23:17:33
Nit: Indent 4, not 9
| |
1038 // Creates keyword_hint first in case |keyword| is a pointer to |text|. | |
Peter Kasting
2011/04/11 23:17:33
Nit: This comment no longer makes sense.
Also, |k
| |
1039 const string16 keyword_hint(TemplateURLModel::CleanUserInputKeyword(text)); | |
1040 | |
1041 if (keyword_hint.empty()) | |
1042 return keyword_hint; | |
1043 if (!profile_->GetTemplateURLModel()) | |
1044 return string16(); | |
1045 profile_->GetTemplateURLModel()->Load(); | |
1046 | |
1047 // Don't provide a hint if this keyword doesn't support replacement. | |
1048 const TemplateURL* const template_url = | |
1049 profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword_hint); | |
1050 if (!TemplateURL::SupportsReplacement(template_url)) | |
1051 return string16(); | |
1052 | |
1053 // Don't provide a hint for inactive/disabled extension keywords. | |
1054 if (template_url->IsExtensionKeyword()) { | |
1055 const Extension* extension = profile_->GetExtensionService()-> | |
1056 GetExtensionById(template_url->GetExtensionId(), false); | |
1057 if (!extension || | |
1058 (profile_->IsOffTheRecord() && | |
Peter Kasting
2011/04/11 23:17:33
Nit: Indent 4, not 3
| |
1059 !profile_->GetExtensionService()->IsIncognitoEnabled(extension->id()))) | |
1060 return string16(); | |
1061 } | |
Peter Kasting
2011/04/11 23:17:33
Nit: Remove unmatched }
| |
1062 | |
1063 return keyword_hint; | |
1064 } | |
1065 | |
OLD | NEW |