[email protected] | 432954d0 | 2012-01-24 01:18:43 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 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 | #pragma once |
| 8 | |
| 9 | #include <vector> |
| 10 | #include <string> |
| 11 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 12 | #include "base/memory/scoped_ptr.h" |
[email protected] | bca359b | 2012-06-24 07:53:04 | [diff] [blame^] | 13 | #include "chrome/browser/search_engines/template_url.h" |
[email protected] | 2905f74 | 2011-10-13 03:51:58 | [diff] [blame] | 14 | #include "content/public/common/page_transition_types.h" |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 15 | #include "googleurl/src/gurl.h" |
| 16 | |
| 17 | class AutocompleteProvider; |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 18 | class Profile; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 19 | class TemplateURL; |
| 20 | |
| 21 | // AutocompleteMatch ---------------------------------------------------------- |
| 22 | |
| 23 | // A single result line with classified spans. The autocomplete popup displays |
| 24 | // the 'contents' and the 'description' (the description is optional) in the |
| 25 | // autocomplete dropdown, and fills in 'fill_into_edit' into the textbox when |
| 26 | // that line is selected. fill_into_edit may be the same as 'description' for |
| 27 | // things like URLs, but may be different for searches or other providers. For |
| 28 | // example, a search result may say "Search for asdf" as the description, but |
| 29 | // "asdf" should appear in the box. |
| 30 | struct AutocompleteMatch { |
| 31 | // Autocomplete matches contain strings that are classified according to a |
| 32 | // separate vector of styles. This vector associates flags with particular |
| 33 | // string segments, and must be in sorted order. All text must be associated |
| 34 | // with some kind of classification. Even if a match has no distinct |
| 35 | // segments, its vector should contain an entry at offset 0 with no flags. |
| 36 | // |
| 37 | // Example: The user typed "goog" |
| 38 | // http://www.google.com/ Google |
| 39 | // ^ ^ ^ ^ ^ |
| 40 | // 0, | 15, | 4, |
| 41 | // 11,match 0,match |
| 42 | // |
| 43 | // This structure holds the classification information for each span. |
| 44 | struct ACMatchClassification { |
| 45 | // The values in here are not mutually exclusive -- use them like a |
| 46 | // bitfield. This also means we use "int" instead of this enum type when |
| 47 | // passing the values around, so the compiler doesn't complain. |
| 48 | enum Style { |
| 49 | NONE = 0, |
| 50 | URL = 1 << 0, // A URL |
| 51 | MATCH = 1 << 1, // A match for the user's search term |
| 52 | DIM = 1 << 2, // "Helper text" |
| 53 | }; |
| 54 | |
| 55 | ACMatchClassification(size_t offset, int style) |
| 56 | : offset(offset), |
| 57 | style(style) { |
| 58 | } |
| 59 | |
| 60 | // Offset within the string that this classification starts |
| 61 | size_t offset; |
| 62 | |
| 63 | int style; |
| 64 | }; |
| 65 | |
| 66 | typedef std::vector<ACMatchClassification> ACMatchClassifications; |
| 67 | |
| 68 | // The type of this match. |
| 69 | enum Type { |
| 70 | URL_WHAT_YOU_TYPED = 0, // The input as a URL. |
| 71 | HISTORY_URL, // A past page whose URL contains the input. |
| 72 | HISTORY_TITLE, // A past page whose title contains the input. |
| 73 | HISTORY_BODY, // A past page whose body contains the input. |
| 74 | HISTORY_KEYWORD, // A past page whose keyword contains the input. |
| 75 | NAVSUGGEST, // A suggested URL. |
| 76 | SEARCH_WHAT_YOU_TYPED, // The input as a search query (with the default |
| 77 | // engine). |
| 78 | SEARCH_HISTORY, // A past search (with the default engine) |
| 79 | // containing the input. |
| 80 | SEARCH_SUGGEST, // A suggested search (with the default engine). |
| 81 | SEARCH_OTHER_ENGINE, // A search with a non-default engine. |
[email protected] | 8f740548 | 2011-04-13 11:08:52 | [diff] [blame] | 82 | EXTENSION_APP, // An Extension App with a title/url that contains |
| 83 | // the input. |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 84 | NUM_TYPES, |
| 85 | }; |
| 86 | |
[email protected] | 531e034 | 2011-11-10 15:08:41 | [diff] [blame] | 87 | // Null-terminated array of characters that are not valid within |contents| |
| 88 | // and |description| strings. |
| 89 | static const char16 kInvalidChars[]; |
| 90 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 91 | AutocompleteMatch(); |
| 92 | AutocompleteMatch(AutocompleteProvider* provider, |
| 93 | int relevance, |
| 94 | bool deletable, |
| 95 | Type type); |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 96 | AutocompleteMatch(const AutocompleteMatch& match); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 97 | ~AutocompleteMatch(); |
| 98 | |
[email protected] | 432954d0 | 2012-01-24 01:18:43 | [diff] [blame] | 99 | // Converts |type| to a string representation. Used in logging and debugging. |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 100 | AutocompleteMatch& operator=(const AutocompleteMatch& match); |
| 101 | |
| 102 | // Converts |type| to a string representation. Used in logging. |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 103 | static std::string TypeToString(Type type); |
| 104 | |
| 105 | // Converts |type| to a resource identifier for the appropriate icon for this |
| 106 | // type. |
| 107 | static int TypeToIcon(Type type); |
| 108 | |
| 109 | // Comparison function for determining when one match is better than another. |
| 110 | static bool MoreRelevant(const AutocompleteMatch& elem1, |
| 111 | const AutocompleteMatch& elem2); |
| 112 | |
| 113 | // Comparison functions for removing matches with duplicate destinations. |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 114 | // Destinations are compared using |stripped_destination_url|. |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 115 | static bool DestinationSortFunc(const AutocompleteMatch& elem1, |
| 116 | const AutocompleteMatch& elem2); |
| 117 | static bool DestinationsEqual(const AutocompleteMatch& elem1, |
| 118 | const AutocompleteMatch& elem2); |
| 119 | |
| 120 | // Helper functions for classes creating matches: |
| 121 | // Fills in the classifications for |text|, using |style| as the base style |
| 122 | // and marking the first instance of |find_text| as a match. (This match |
| 123 | // will also not be dimmed, if |style| has DIM set.) |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 124 | static void ClassifyMatchInString(const string16& find_text, |
| 125 | const string16& text, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 126 | int style, |
| 127 | ACMatchClassifications* classifications); |
| 128 | |
| 129 | // Similar to ClassifyMatchInString(), but for cases where the range to mark |
| 130 | // as matching is already known (avoids calling find()). This can be helpful |
| 131 | // when find() would be misleading (e.g. you want to mark the second match in |
| 132 | // a string instead of the first). |
| 133 | static void ClassifyLocationInString(size_t match_location, |
| 134 | size_t match_length, |
| 135 | size_t overall_length, |
| 136 | int style, |
| 137 | ACMatchClassifications* classifications); |
| 138 | |
[email protected] | 9d2b5f3b | 2012-03-14 21:34:32 | [diff] [blame] | 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 | |
[email protected] | 531e034 | 2011-11-10 15:08:41 | [diff] [blame] | 154 | // Removes invalid characters from |text|. Should be called on strings coming |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 155 | // from external sources (such as extensions) before assigning to |contents| |
| 156 | // or |description|. |
| 157 | static string16 SanitizeString(const string16& text); |
| 158 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 159 | // Copies the destination_url with "www." stripped off to |
| 160 | // |stripped_destination_url|. This method is invoked internally by the |
| 161 | // AutocompleteController and does not normally need to be invoked. |
| 162 | void ComputeStrippedDestinationURL(); |
| 163 | |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 164 | // Gets data relevant to whether there should be any special keyword-related |
| 165 | // UI shown for this match. If this match represents a selected keyword, i.e. |
| 166 | // the UI should be "in keyword mode", |keyword| will be set to the keyword |
| 167 | // and |is_keyword_hint| will be set to false. If this match has a non-NULL |
| 168 | // |associated_keyword|, i.e. we should show a "Press [tab] to search ___" |
| 169 | // hint and allow the user to toggle into keyword mode, |keyword| will be set |
| 170 | // to the associated keyword and |is_keyword_hint| will be set to true. Note |
| 171 | // that only one of these states can be in effect at once. In all other |
| 172 | // cases, |keyword| will be cleared, even when our member variable |keyword| |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 173 | // is non-empty -- such as with non-substituting keywords or matches that |
| 174 | // represent searches using the default search engine. See also |
| 175 | // GetSubstitutingExplicitlyInvokedKeyword(). |
| 176 | void GetKeywordUIState(Profile* profile, |
| 177 | string16* keyword, |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 178 | bool* is_keyword_hint) const; |
| 179 | |
| 180 | // Returns |keyword|, but only if it represents a substituting keyword that |
| 181 | // the user has explicitly invoked. If for example this match represents a |
| 182 | // search with the default search engine (and the user didn't explicitly |
| 183 | // invoke its keyword), this returns the empty string. The result is that |
| 184 | // this function returns a non-empty string in the same cases as when the UI |
| 185 | // should show up as being "in keyword mode". |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 186 | string16 GetSubstitutingExplicitlyInvokedKeyword(Profile* profile) const; |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 187 | |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 188 | // Returns the TemplateURL associated with this match. This may be NULL if |
| 189 | // the match has no keyword OR if the keyword no longer corresponds to a valid |
| 190 | // TemplateURL. See comments on |keyword| below. |
| 191 | TemplateURL* GetTemplateURL(Profile* profile) const; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 192 | |
[email protected] | d1d0afe | 2010-12-16 18:04:52 | [diff] [blame] | 193 | // The provider of this match, used to remember which provider the user had |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 194 | // selected when the input changes. This may be NULL, in which case there is |
| 195 | // no provider (or memory of the user's selection). |
| 196 | AutocompleteProvider* provider; |
| 197 | |
[email protected] | ffc4487 | 2011-04-06 12:01:43 | [diff] [blame] | 198 | // The relevance of this match. See table in autocomplete.h for scores |
| 199 | // returned by various providers. This is used to rank matches among all |
| 200 | // responding providers, so different providers must be carefully tuned to |
| 201 | // supply matches with appropriate relevance. |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 202 | // |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 203 | // TODO(pkasting): http://b/1111299 This should be calculated algorithmically, |
| 204 | // rather than being a fairly fixed value defined by the table above. |
| 205 | int relevance; |
| 206 | |
[email protected] | cf6256f | 2012-06-12 23:36:01 | [diff] [blame] | 207 | // How many times this result was typed in / selected from the omnibox. |
| 208 | // Only set for some providers and result_types. If it is not set, |
| 209 | // its value is -1. At the time of writing this comment, it is only |
| 210 | // set for matches from HistoryURL and HistoryQuickProvider. |
| 211 | int typed_count; |
| 212 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 213 | // True if the user should be able to delete this match. |
| 214 | bool deletable; |
| 215 | |
| 216 | // This string is loaded into the location bar when the item is selected |
| 217 | // by pressing the arrow keys. This may be different than a URL, for example, |
| 218 | // for search suggestions, this would just be the search terms. |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 219 | string16 fill_into_edit; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 220 | |
| 221 | // The position within fill_into_edit from which we'll display the inline |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 222 | // autocomplete string. This will be string16::npos if this match should |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 223 | // not be inline autocompleted. |
| 224 | size_t inline_autocomplete_offset; |
| 225 | |
| 226 | // The URL to actually load when the autocomplete item is selected. This URL |
| 227 | // should be canonical so we can compare URLs with strcmp to avoid dupes. |
| 228 | // It may be empty if there is no possible navigation. |
| 229 | GURL destination_url; |
| 230 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 231 | // The destination URL with "www." stripped off for better dupe finding. |
| 232 | GURL stripped_destination_url; |
| 233 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 234 | // The main text displayed in the address bar dropdown. |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 235 | string16 contents; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 236 | ACMatchClassifications contents_class; |
| 237 | |
| 238 | // Additional helper text for each entry, such as a title or description. |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 239 | string16 description; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 240 | ACMatchClassifications description_class; |
| 241 | |
| 242 | // The transition type to use when the user opens this match. By default |
| 243 | // this is TYPED. Providers whose matches do not look like URLs should set |
| 244 | // it to GENERATED. |
[email protected] | 2905f74 | 2011-10-13 03:51:58 | [diff] [blame] | 245 | content::PageTransition transition; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 246 | |
| 247 | // True when this match is the "what you typed" match from the history |
| 248 | // system. |
| 249 | bool is_history_what_you_typed_match; |
| 250 | |
| 251 | // Type of this match. |
| 252 | Type type; |
| 253 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 254 | // Set with a keyword provider match if this match can show a keyword hint. |
| 255 | // For example, if this is a SearchProvider match for "www.amazon.com", |
| 256 | // |associated_keyword| could be a KeywordProvider match for "amazon.com". |
| 257 | scoped_ptr<AutocompleteMatch> associated_keyword; |
| 258 | |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 259 | // The keyword of the TemplateURL the match originated from. This is nonempty |
| 260 | // for both explicit "keyword mode" matches as well as matches for the default |
| 261 | // search provider (so, any match for which we're doing substitution); it |
| 262 | // doesn't imply (alone) that the UI is going to show a keyword hint or |
| 263 | // keyword mode. For that, see GetKeywordUIState() or |
| 264 | // GetSubstitutingExplicitlyInvokedKeyword(). |
| 265 | // |
| 266 | // CAUTION: The TemplateURL associated with this keyword may be deleted or |
| 267 | // modified while the AutocompleteMatch is alive. This means anyone who |
| 268 | // accesses it must perform any necessary sanity checks before blindly using |
| 269 | // it! |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 270 | string16 keyword; |
| 271 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 272 | // True if the user has starred the destination URL. |
| 273 | bool starred; |
| 274 | |
[email protected] | 7abfb346 | 2011-01-31 16:43:06 | [diff] [blame] | 275 | // True if this match is from a previous result. |
| 276 | bool from_previous; |
| 277 | |
[email protected] | bca359b | 2012-06-24 07:53:04 | [diff] [blame^] | 278 | // Optional search terms args. If present, |
| 279 | // AutocompleteController::UpdateAssistedQueryStats() will incorporate this |
| 280 | // data with additional data it calculates and pass the completed struct to |
| 281 | // TemplateURLRef::ReplaceSearchTerms() to reset the match's |destination_url| |
| 282 | // after the complete set of matches in the AutocompleteResult has been chosen |
| 283 | // and sorted. Most providers will leave this as NULL, which will cause the |
| 284 | // AutocompleteController to do no additional transformations. |
| 285 | scoped_ptr<TemplateURLRef::SearchTermsArgs> search_terms_args; |
| 286 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 287 | #ifndef NDEBUG |
| 288 | // Does a data integrity check on this match. |
| 289 | void Validate() const; |
| 290 | |
| 291 | // Checks one text/classifications pair for valid values. |
| 292 | void ValidateClassifications( |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 293 | const string16& text, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 294 | const ACMatchClassifications& classifications) const; |
| 295 | #endif |
| 296 | }; |
| 297 | |
| 298 | typedef AutocompleteMatch::ACMatchClassification ACMatchClassification; |
| 299 | typedef std::vector<ACMatchClassification> ACMatchClassifications; |
| 300 | |
| 301 | #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ |