• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "base/logging.h"
6 #include "chrome/browser/autocomplete/autocomplete_match.h"
7 #include "grit/theme_resources.h"
8 
9 // AutocompleteMatch ----------------------------------------------------------
10 
AutocompleteMatch()11 AutocompleteMatch::AutocompleteMatch()
12     : provider(NULL),
13       relevance(0),
14       deletable(false),
15       inline_autocomplete_offset(string16::npos),
16       transition(PageTransition::GENERATED),
17       is_history_what_you_typed_match(false),
18       type(SEARCH_WHAT_YOU_TYPED),
19       template_url(NULL),
20       starred(false),
21       from_previous(false) {
22 }
23 
AutocompleteMatch(AutocompleteProvider * provider,int relevance,bool deletable,Type type)24 AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
25                                      int relevance,
26                                      bool deletable,
27                                      Type type)
28     : provider(provider),
29       relevance(relevance),
30       deletable(deletable),
31       inline_autocomplete_offset(string16::npos),
32       transition(PageTransition::TYPED),
33       is_history_what_you_typed_match(false),
34       type(type),
35       template_url(NULL),
36       starred(false),
37       from_previous(false) {
38 }
39 
~AutocompleteMatch()40 AutocompleteMatch::~AutocompleteMatch() {
41 }
42 
43 // static
TypeToString(Type type)44 std::string AutocompleteMatch::TypeToString(Type type) {
45   const char* strings[NUM_TYPES] = {
46     "url-what-you-typed",
47     "history-url",
48     "history-title",
49     "history-body",
50     "history-keyword",
51     "navsuggest",
52     "search-what-you-typed",
53     "search-history",
54     "search-suggest",
55     "search-other-engine",
56     "extension-app",
57   };
58   DCHECK(arraysize(strings) == NUM_TYPES);
59   return strings[type];
60 }
61 
62 // static
TypeToIcon(Type type)63 int AutocompleteMatch::TypeToIcon(Type type) {
64   int icons[NUM_TYPES] = {
65     IDR_OMNIBOX_HTTP,
66     IDR_OMNIBOX_HTTP,
67     IDR_OMNIBOX_HISTORY,
68     IDR_OMNIBOX_HISTORY,
69     IDR_OMNIBOX_HISTORY,
70     IDR_OMNIBOX_HTTP,
71     IDR_OMNIBOX_SEARCH,
72     IDR_OMNIBOX_SEARCH,
73     IDR_OMNIBOX_SEARCH,
74     IDR_OMNIBOX_SEARCH,
75     IDR_OMNIBOX_EXTENSION_APP,
76   };
77   DCHECK(arraysize(icons) == NUM_TYPES);
78   return icons[type];
79 }
80 
81 // static
MoreRelevant(const AutocompleteMatch & elem1,const AutocompleteMatch & elem2)82 bool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1,
83                                      const AutocompleteMatch& elem2) {
84   // For equal-relevance matches, we sort alphabetically, so that providers
85   // who return multiple elements at the same priority get a "stable" sort
86   // across multiple updates.
87   if (elem1.relevance == elem2.relevance)
88     return elem1.contents > elem2.contents;
89 
90   return elem1.relevance > elem2.relevance;
91 }
92 
93 // static
DestinationSortFunc(const AutocompleteMatch & elem1,const AutocompleteMatch & elem2)94 bool AutocompleteMatch::DestinationSortFunc(const AutocompleteMatch& elem1,
95                                             const AutocompleteMatch& elem2) {
96   // Sort identical destination_urls together.  Place the most relevant matches
97   // first, so that when we call std::unique(), these are the ones that get
98   // preserved.
99   return (elem1.destination_url != elem2.destination_url) ?
100       (elem1.destination_url < elem2.destination_url) :
101       MoreRelevant(elem1, elem2);
102 }
103 
104 // static
DestinationsEqual(const AutocompleteMatch & elem1,const AutocompleteMatch & elem2)105 bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1,
106                                           const AutocompleteMatch& elem2) {
107   return elem1.destination_url == elem2.destination_url;
108 }
109 
110 // static
ClassifyMatchInString(const string16 & find_text,const string16 & text,int style,ACMatchClassifications * classification)111 void AutocompleteMatch::ClassifyMatchInString(
112     const string16& find_text,
113     const string16& text,
114     int style,
115     ACMatchClassifications* classification) {
116   ClassifyLocationInString(text.find(find_text), find_text.length(),
117                            text.length(), style, classification);
118 }
119 
ClassifyLocationInString(size_t match_location,size_t match_length,size_t overall_length,int style,ACMatchClassifications * classification)120 void AutocompleteMatch::ClassifyLocationInString(
121     size_t match_location,
122     size_t match_length,
123     size_t overall_length,
124     int style,
125     ACMatchClassifications* classification) {
126   classification->clear();
127 
128   // Don't classify anything about an empty string
129   // (AutocompleteMatch::Validate() checks this).
130   if (overall_length == 0)
131     return;
132 
133   // Mark pre-match portion of string (if any).
134   if (match_location != 0) {
135     classification->push_back(ACMatchClassification(0, style));
136   }
137 
138   // Mark matching portion of string.
139   if (match_location == string16::npos) {
140     // No match, above classification will suffice for whole string.
141     return;
142   }
143   // Classifying an empty match makes no sense and will lead to validation
144   // errors later.
145   DCHECK(match_length > 0);
146   classification->push_back(ACMatchClassification(match_location,
147       (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM));
148 
149   // Mark post-match portion of string (if any).
150   const size_t after_match(match_location + match_length);
151   if (after_match < overall_length) {
152     classification->push_back(ACMatchClassification(after_match, style));
153   }
154 }
155 
156 #ifndef NDEBUG
Validate() const157 void AutocompleteMatch::Validate() const {
158   ValidateClassifications(contents, contents_class);
159   ValidateClassifications(description, description_class);
160 }
161 
ValidateClassifications(const string16 & text,const ACMatchClassifications & classifications) const162 void AutocompleteMatch::ValidateClassifications(
163     const string16& text,
164     const ACMatchClassifications& classifications) const {
165   if (text.empty()) {
166     DCHECK(classifications.size() == 0);
167     return;
168   }
169 
170   // The classifications should always cover the whole string.
171   DCHECK(!classifications.empty()) << "No classification for text";
172   DCHECK(classifications[0].offset == 0) << "Classification misses beginning";
173   if (classifications.size() == 1)
174     return;
175 
176   // The classifications should always be sorted.
177   size_t last_offset = classifications[0].offset;
178   for (ACMatchClassifications::const_iterator i(classifications.begin() + 1);
179        i != classifications.end(); ++i) {
180     DCHECK(i->offset > last_offset) << "Classification unsorted";
181     DCHECK(i->offset < text.length()) << "Classification out of bounds";
182     last_offset = i->offset;
183   }
184 }
185 #endif
186