OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 #ifndef COMPONENTS_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ | |
6 #define COMPONENTS_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ | |
7 | |
8 #include <map> | |
9 #include <string> | |
10 #include <vector> | |
11 | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "components/autocomplete/autocomplete_match_type.h" | |
14 #include "components/search_engines/template_url.h" | |
15 #include "content/public/common/page_transition_types.h" | |
16 #include "url/gurl.h" | |
17 | |
18 class AutocompleteProvider; | |
19 class TemplateURL; | |
20 class TemplateURLService; | |
21 | |
22 namespace base { | |
23 class Time; | |
24 } // namespace base | |
25 | |
26 const char kACMatchPropertyInputText[] = "input text"; | |
27 const char kACMatchPropertyContentsPrefix[] = "match contents prefix"; | |
28 const char kACMatchPropertyContentsStartIndex[] = "match contents start index"; | |
29 | |
30 // AutocompleteMatch ---------------------------------------------------------- | |
31 | |
32 // A single result line with classified spans. The autocomplete popup displays | |
33 // the 'contents' and the 'description' (the description is optional) in the | |
34 // autocomplete dropdown, and fills in 'fill_into_edit' into the textbox when | |
35 // that line is selected. fill_into_edit may be the same as 'description' for | |
36 // things like URLs, but may be different for searches or other providers. For | |
37 // example, a search result may say "Search for asdf" as the description, but | |
38 // "asdf" should appear in the box. | |
39 struct AutocompleteMatch { | |
40 // Autocomplete matches contain strings that are classified according to a | |
41 // separate vector of styles. This vector associates flags with particular | |
42 // string segments, and must be in sorted order. All text must be associated | |
43 // with some kind of classification. Even if a match has no distinct | |
44 // segments, its vector should contain an entry at offset 0 with no flags. | |
45 // | |
46 // Example: The user typed "goog" | |
47 // http://www.google.com/ Google | |
48 // ^ ^ ^ ^ ^ | |
49 // 0, | 15, | 4, | |
50 // 11,match 0,match | |
51 // | |
52 // This structure holds the classification information for each span. | |
53 struct ACMatchClassification { | |
54 // The values in here are not mutually exclusive -- use them like a | |
55 // bitfield. This also means we use "int" instead of this enum type when | |
56 // passing the values around, so the compiler doesn't complain. | |
57 enum Style { | |
58 NONE = 0, | |
59 URL = 1 << 0, // A URL | |
60 MATCH = 1 << 1, // A match for the user's search term | |
61 DIM = 1 << 2, // "Helper text" | |
62 }; | |
63 | |
64 ACMatchClassification(size_t offset, int style) | |
65 : offset(offset), | |
66 style(style) { | |
67 } | |
68 | |
69 // Offset within the string that this classification starts | |
70 size_t offset; | |
71 | |
72 int style; | |
73 }; | |
74 | |
75 typedef std::vector<ACMatchClassification> ACMatchClassifications; | |
76 | |
77 // Type used by providers to attach additional, optional information to | |
78 // an AutocompleteMatch. | |
79 typedef std::map<std::string, std::string> AdditionalInfo; | |
80 | |
81 // The type of this match. | |
82 typedef AutocompleteMatchType::Type Type; | |
83 | |
84 // Null-terminated array of characters that are not valid within |contents| | |
85 // and |description| strings. | |
86 static const base::char16 kInvalidChars[]; | |
87 | |
88 AutocompleteMatch(); | |
89 AutocompleteMatch(AutocompleteProvider* provider, | |
90 int relevance, | |
91 bool deletable, | |
92 Type type); | |
93 AutocompleteMatch(const AutocompleteMatch& match); | |
94 ~AutocompleteMatch(); | |
95 | |
96 // Converts |type| to a string representation. Used in logging and debugging. | |
97 AutocompleteMatch& operator=(const AutocompleteMatch& match); | |
98 | |
99 // Converts |type| to a resource identifier for the appropriate icon for this | |
100 // type to show in the completion popup. | |
101 static int TypeToIcon(Type type); | |
102 | |
103 // Comparison function for determining when one match is better than another. | |
104 static bool MoreRelevant(const AutocompleteMatch& elem1, | |
105 const AutocompleteMatch& elem2); | |
106 | |
107 // Comparison function for removing matches with duplicate destinations. | |
108 // Destinations are compared using |stripped_destination_url|. Pairs of | |
109 // matches with empty destinations are treated as differing, since empty | |
110 // destinations are expected for non-navigable matches. | |
111 static bool DestinationsEqual(const AutocompleteMatch& elem1, | |
112 const AutocompleteMatch& elem2); | |
113 | |
114 // Helper functions for classes creating matches: | |
115 // Fills in the classifications for |text|, using |style| as the base style | |
116 // and marking the first instance of |find_text| as a match. (This match | |
117 // will also not be dimmed, if |style| has DIM set.) | |
118 static void ClassifyMatchInString(const base::string16& find_text, | |
119 const base::string16& text, | |
120 int style, | |
121 ACMatchClassifications* classifications); | |
122 | |
123 // Similar to ClassifyMatchInString(), but for cases where the range to mark | |
124 // as matching is already known (avoids calling find()). This can be helpful | |
125 // when find() would be misleading (e.g. you want to mark the second match in | |
126 // a string instead of the first). | |
127 static void ClassifyLocationInString(size_t match_location, | |
128 size_t match_length, | |
129 size_t overall_length, | |
130 int style, | |
131 ACMatchClassifications* classifications); | |
132 | |
133 // Returns a new vector of classifications containing the merged contents of | |
134 // |classifications1| and |classifications2|. | |
135 static ACMatchClassifications MergeClassifications( | |
136 const ACMatchClassifications& classifications1, | |
137 const ACMatchClassifications& classifications2); | |
138 | |
139 // Converts classifications to and from a serialized string representation | |
140 // (using comma-separated integers to sequentially list positions and styles). | |
141 static std::string ClassificationsToString( | |
142 const ACMatchClassifications& classifications); | |
143 static ACMatchClassifications ClassificationsFromString( | |
144 const std::string& serialized_classifications); | |
145 | |
146 // Adds a classification to the end of |classifications| iff its style is | |
147 // different from the last existing classification. |offset| must be larger | |
148 // than the offset of the last classification in |classifications|. | |
149 static void AddLastClassificationIfNecessary( | |
150 ACMatchClassifications* classifications, | |
151 size_t offset, | |
152 int style); | |
153 | |
154 // Removes invalid characters from |text|. Should be called on strings coming | |
155 // from external sources (such as extensions) before assigning to |contents| | |
156 // or |description|. | |
157 static base::string16 SanitizeString(const base::string16& text); | |
158 | |
159 // Convenience function to check if |type| is a search (as opposed to a URL or | |
160 // an extension). | |
161 static bool IsSearchType(Type type); | |
162 | |
163 // Convenience function to check if |type| is a special search suggest type - | |
164 // like entity, personalized, profile or postfix. | |
165 static bool IsSpecializedSearchType(Type type); | |
166 | |
167 // A static version GetTemplateURL() that takes the match's keyword and | |
168 // match's hostname as parameters. In short, returns the TemplateURL | |
169 // associated with |keyword| if it exists; otherwise returns the TemplateURL | |
170 // associated with |host| if it exists. | |
171 static TemplateURL* GetTemplateURLWithKeyword( | |
172 TemplateURLService* template_url_service, | |
173 const base::string16& keyword, | |
174 const std::string& host); | |
175 | |
176 // Returns |url| altered by stripping off "www.", converting https protocol | |
177 // to http, and stripping excess query parameters. These conversions are | |
178 // merely to allow comparisons to remove likely duplicates; these URLs are | |
179 // not used as actual destination URLs. If |template_url_service| is not | |
180 // NULL, it is used to get a template URL corresponding to this match. If | |
181 // the match's keyword is known, it can be passed in. Otherwise, it can be | |
182 // left empty and the template URL (if any) is determined from the | |
183 // destination's hostname. The template URL is used to strip off query args | |
184 // other than the search terms themselves that would otherwise prevent doing | |
185 // proper deduping. | |
186 static GURL GURLToStrippedGURL(const GURL& url, | |
187 TemplateURLService* template_url_service, | |
188 const base::string16& keyword); | |
189 | |
190 // Computes the stripped destination URL (via GURLToStrippedGURL()) and | |
191 // stores the result in |stripped_destination_url|. | |
192 void ComputeStrippedDestinationURL(TemplateURLService* template_url_service); | |
193 | |
194 // Sets |allowed_to_be_default_match| to true if this match is effectively | |
195 // the URL-what-you-typed match (i.e., would be dupped against the UWYT | |
196 // match when AutocompleteResult merges matches). |canonical_input_url| is | |
197 // the AutocompleteInput interpreted as a URL (i.e., | |
198 // AutocompleteInput::canonicalized_url()). | |
199 void EnsureUWYTIsAllowedToBeDefault(const GURL& canonical_input_url, | |
200 TemplateURLService* template_url_service); | |
201 | |
202 // Gets data relevant to whether there should be any special keyword-related | |
203 // UI shown for this match. If this match represents a selected keyword, i.e. | |
204 // the UI should be "in keyword mode", |keyword| will be set to the keyword | |
205 // and |is_keyword_hint| will be set to false. If this match has a non-NULL | |
206 // |associated_keyword|, i.e. we should show a "Press [tab] to search ___" | |
207 // hint and allow the user to toggle into keyword mode, |keyword| will be set | |
208 // to the associated keyword and |is_keyword_hint| will be set to true. Note | |
209 // that only one of these states can be in effect at once. In all other | |
210 // cases, |keyword| will be cleared, even when our member variable |keyword| | |
211 // is non-empty -- such as with non-substituting keywords or matches that | |
212 // represent searches using the default search engine. See also | |
213 // GetSubstitutingExplicitlyInvokedKeyword(). | |
214 void GetKeywordUIState(TemplateURLService* template_url_service, | |
215 base::string16* keyword, | |
216 bool* is_keyword_hint) const; | |
217 | |
218 // Returns |keyword|, but only if it represents a substituting keyword that | |
219 // the user has explicitly invoked. If for example this match represents a | |
220 // search with the default search engine (and the user didn't explicitly | |
221 // invoke its keyword), this returns the empty string. The result is that | |
222 // this function returns a non-empty string in the same cases as when the UI | |
223 // should show up as being "in keyword mode". | |
224 base::string16 GetSubstitutingExplicitlyInvokedKeyword( | |
225 TemplateURLService* template_url_service) const; | |
226 | |
227 // Returns the TemplateURL associated with this match. This may be NULL if | |
228 // the match has no keyword OR if the keyword no longer corresponds to a valid | |
229 // TemplateURL. See comments on |keyword| below. | |
230 // If |allow_fallback_to_destination_host| is true and the keyword does | |
231 // not map to a valid TemplateURL, we'll then check for a TemplateURL that | |
232 // corresponds to the destination_url's hostname. | |
233 TemplateURL* GetTemplateURL(TemplateURLService* template_url_service, | |
234 bool allow_fallback_to_destination_host) const; | |
235 | |
236 // Adds optional information to the |additional_info| dictionary. | |
237 void RecordAdditionalInfo(const std::string& property, | |
238 const std::string& value); | |
239 void RecordAdditionalInfo(const std::string& property, int value); | |
240 void RecordAdditionalInfo(const std::string& property, | |
241 const base::Time& value); | |
242 | |
243 // Returns the value recorded for |property| in the |additional_info| | |
244 // dictionary. Returns the empty string if no such value exists. | |
245 std::string GetAdditionalInfo(const std::string& property) const; | |
246 | |
247 // Returns whether this match is a "verbatim" match: a URL navigation directly | |
248 // to the user's input, a search for the user's input with the default search | |
249 // engine, or a "keyword mode" search for the query portion of the user's | |
250 // input. Note that rare or unusual types that could be considered verbatim, | |
251 // such as keyword engine matches or extension-provided matches, aren't | |
252 // detected by this IsVerbatimType, as the user will not be able to infer | |
253 // what will happen when he or she presses enter in those cases if the match | |
254 // is not shown. | |
255 bool IsVerbatimType() const; | |
256 | |
257 // Returns whether this match or any duplicate of this match can be deleted. | |
258 // This is used to decide whether we should call DeleteMatch(). | |
259 bool SupportsDeletion() const; | |
260 | |
261 // The provider of this match, used to remember which provider the user had | |
262 // selected when the input changes. This may be NULL, in which case there is | |
263 // no provider (or memory of the user's selection). | |
264 AutocompleteProvider* provider; | |
265 | |
266 // The relevance of this match. See table in autocomplete.h for scores | |
267 // returned by various providers. This is used to rank matches among all | |
268 // responding providers, so different providers must be carefully tuned to | |
269 // supply matches with appropriate relevance. | |
270 // | |
271 // TODO(pkasting): http://b/1111299 This should be calculated algorithmically, | |
272 // rather than being a fairly fixed value defined by the table above. | |
273 int relevance; | |
274 | |
275 // How many times this result was typed in / selected from the omnibox. | |
276 // Only set for some providers and result_types. If it is not set, | |
277 // its value is -1. At the time of writing this comment, it is only | |
278 // set for matches from HistoryURL and HistoryQuickProvider. | |
279 int typed_count; | |
280 | |
281 // True if the user should be able to delete this match. | |
282 bool deletable; | |
283 | |
284 // This string is loaded into the location bar when the item is selected | |
285 // by pressing the arrow keys. This may be different than a URL, for example, | |
286 // for search suggestions, this would just be the search terms. | |
287 base::string16 fill_into_edit; | |
288 | |
289 // The inline autocompletion to display after the user's typing in the | |
290 // omnibox, if this match becomes the default match. It may be empty. | |
291 base::string16 inline_autocompletion; | |
292 | |
293 // If false, the omnibox should prevent this match from being the | |
294 // default match. Providers should set this to true only if the | |
295 // user's input, plus any inline autocompletion on this match, would | |
296 // lead the user to expect a navigation to this match's destination. | |
297 // For example, with input "foo", a search for "bar" or navigation | |
298 // to "bar.com" should not set this flag; a navigation to "foo.com" | |
299 // should only set this flag if ".com" will be inline autocompleted; | |
300 // and a navigation to "foo/" (an intranet host) or search for "foo" | |
301 // should set this flag. | |
302 bool allowed_to_be_default_match; | |
303 | |
304 // The URL to actually load when the autocomplete item is selected. This URL | |
305 // should be canonical so we can compare URLs with strcmp to avoid dupes. | |
306 // It may be empty if there is no possible navigation. | |
307 GURL destination_url; | |
308 | |
309 // The destination URL with "www." stripped off for better dupe finding. | |
310 GURL stripped_destination_url; | |
311 | |
312 // The main text displayed in the address bar dropdown. | |
313 base::string16 contents; | |
314 ACMatchClassifications contents_class; | |
315 | |
316 // Additional helper text for each entry, such as a title or description. | |
317 base::string16 description; | |
318 ACMatchClassifications description_class; | |
319 | |
320 // A rich-format version of the display for the dropdown. | |
321 base::string16 answer_contents; | |
322 base::string16 answer_type; | |
323 | |
324 // The transition type to use when the user opens this match. By default | |
325 // this is TYPED. Providers whose matches do not look like URLs should set | |
326 // it to GENERATED. | |
327 content::PageTransition transition; | |
328 | |
329 // True when this match is the "what you typed" match from the history | |
330 // system. | |
331 bool is_history_what_you_typed_match; | |
332 | |
333 // Type of this match. | |
334 Type type; | |
335 | |
336 // Set with a keyword provider match if this match can show a keyword hint. | |
337 // For example, if this is a SearchProvider match for "www.amazon.com", | |
338 // |associated_keyword| could be a KeywordProvider match for "amazon.com". | |
339 scoped_ptr<AutocompleteMatch> associated_keyword; | |
340 | |
341 // The keyword of the TemplateURL the match originated from. This is nonempty | |
342 // for both explicit "keyword mode" matches as well as matches for the default | |
343 // search provider (so, any match for which we're doing substitution); it | |
344 // doesn't imply (alone) that the UI is going to show a keyword hint or | |
345 // keyword mode. For that, see GetKeywordUIState() or | |
346 // GetSubstitutingExplicitlyInvokedKeyword(). | |
347 // | |
348 // CAUTION: The TemplateURL associated with this keyword may be deleted or | |
349 // modified while the AutocompleteMatch is alive. This means anyone who | |
350 // accesses it must perform any necessary sanity checks before blindly using | |
351 // it! | |
352 base::string16 keyword; | |
353 | |
354 // True if this match is from a previous result. | |
355 bool from_previous; | |
356 | |
357 // Optional search terms args. If present, | |
358 // AutocompleteController::UpdateAssistedQueryStats() will incorporate this | |
359 // data with additional data it calculates and pass the completed struct to | |
360 // TemplateURLRef::ReplaceSearchTerms() to reset the match's |destination_url| | |
361 // after the complete set of matches in the AutocompleteResult has been chosen | |
362 // and sorted. Most providers will leave this as NULL, which will cause the | |
363 // AutocompleteController to do no additional transformations. | |
364 scoped_ptr<TemplateURLRef::SearchTermsArgs> search_terms_args; | |
365 | |
366 // Information dictionary into which each provider can optionally record a | |
367 // property and associated value and which is presented in chrome://omnibox. | |
368 AdditionalInfo additional_info; | |
369 | |
370 // A list of matches culled during de-duplication process, retained to | |
371 // ensure if a match is deleted, the duplicates are deleted as well. | |
372 std::vector<AutocompleteMatch> duplicate_matches; | |
373 | |
374 #ifndef NDEBUG | |
375 // Does a data integrity check on this match. | |
376 void Validate() const; | |
377 | |
378 // Checks one text/classifications pair for valid values. | |
379 void ValidateClassifications( | |
380 const base::string16& text, | |
381 const ACMatchClassifications& classifications) const; | |
382 #endif | |
383 }; | |
384 | |
385 typedef AutocompleteMatch::ACMatchClassification ACMatchClassification; | |
386 typedef std::vector<ACMatchClassification> ACMatchClassifications; | |
387 typedef std::vector<AutocompleteMatch> ACMatches; | |
388 | |
389 #endif // COMPONENTS_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ | |
OLD | NEW |