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