[email protected] | eac4499 | 2012-02-14 21:39:35 | [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 | |
[email protected] | 371dab1 | 2012-06-01 03:23:55 | [diff] [blame] | 5 | #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 6 | |
[email protected] | 5281d42 | 2012-07-28 21:37:10 | [diff] [blame] | 7 | #include "base/i18n/time_formatting.h" |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 8 | #include "base/logging.h" |
[email protected] | 9d2b5f3b | 2012-03-14 21:34:32 | [diff] [blame] | 9 | #include "base/string_number_conversions.h" |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 10 | #include "base/string_util.h" |
[email protected] | 5281d42 | 2012-07-28 21:37:10 | [diff] [blame] | 11 | #include "base/string16.h" |
| 12 | #include "base/stringprintf.h" |
| 13 | #include "base/time.h" |
| 14 | #include "base/utf_string_conversions.h" |
[email protected] | 30f5bc9 | 2012-06-26 04:14:55 | [diff] [blame] | 15 | #include "chrome/browser/autocomplete/autocomplete_provider.h" |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 16 | #include "chrome/browser/search_engines/template_url.h" |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 17 | #include "chrome/browser/search_engines/template_url_service.h" |
| 18 | #include "chrome/browser/search_engines/template_url_service_factory.h" |
[email protected] | 345e8fda | 2012-09-06 01:07:47 | [diff] [blame] | 19 | #include "content/public/common/url_constants.h" |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 20 | #include "grit/theme_resources.h" |
| 21 | |
[email protected] | 3b81314d | 2012-09-11 02:48:41 | [diff] [blame^] | 22 | namespace { |
| 23 | |
| 24 | bool IsTrivialClassification(const ACMatchClassifications& classifications) { |
| 25 | return classifications.empty() || |
| 26 | ((classifications.size() == 1) && |
| 27 | (classifications.back().style == ACMatchClassification::NONE)); |
| 28 | } |
| 29 | |
| 30 | } // namespace |
| 31 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 32 | // AutocompleteMatch ---------------------------------------------------------- |
| 33 | |
[email protected] | 531e034 | 2011-11-10 15:08:41 | [diff] [blame] | 34 | // static |
| 35 | const char16 AutocompleteMatch::kInvalidChars[] = { |
| 36 | '\n', '\r', '\t', |
| 37 | 0x2028, // Line separator |
| 38 | 0x2029, // Paragraph separator |
| 39 | 0 |
| 40 | }; |
| 41 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 42 | AutocompleteMatch::AutocompleteMatch() |
| 43 | : provider(NULL), |
| 44 | relevance(0), |
[email protected] | cf6256f | 2012-06-12 23:36:01 | [diff] [blame] | 45 | typed_count(-1), |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 46 | deletable(false), |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 47 | inline_autocomplete_offset(string16::npos), |
[email protected] | 2905f74 | 2011-10-13 03:51:58 | [diff] [blame] | 48 | transition(content::PAGE_TRANSITION_GENERATED), |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 49 | is_history_what_you_typed_match(false), |
| 50 | type(SEARCH_WHAT_YOU_TYPED), |
[email protected] | 7abfb346 | 2011-01-31 16:43:06 | [diff] [blame] | 51 | starred(false), |
| 52 | from_previous(false) { |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider, |
| 56 | int relevance, |
| 57 | bool deletable, |
| 58 | Type type) |
| 59 | : provider(provider), |
| 60 | relevance(relevance), |
[email protected] | cf6256f | 2012-06-12 23:36:01 | [diff] [blame] | 61 | typed_count(-1), |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 62 | deletable(deletable), |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 63 | inline_autocomplete_offset(string16::npos), |
[email protected] | 2905f74 | 2011-10-13 03:51:58 | [diff] [blame] | 64 | transition(content::PAGE_TRANSITION_TYPED), |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 65 | is_history_what_you_typed_match(false), |
| 66 | type(type), |
[email protected] | 7abfb346 | 2011-01-31 16:43:06 | [diff] [blame] | 67 | starred(false), |
| 68 | from_previous(false) { |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 69 | } |
| 70 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 71 | AutocompleteMatch::AutocompleteMatch(const AutocompleteMatch& match) |
| 72 | : provider(match.provider), |
| 73 | relevance(match.relevance), |
[email protected] | cf6256f | 2012-06-12 23:36:01 | [diff] [blame] | 74 | typed_count(match.typed_count), |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 75 | deletable(match.deletable), |
| 76 | fill_into_edit(match.fill_into_edit), |
| 77 | inline_autocomplete_offset(match.inline_autocomplete_offset), |
| 78 | destination_url(match.destination_url), |
| 79 | stripped_destination_url(match.stripped_destination_url), |
| 80 | contents(match.contents), |
| 81 | contents_class(match.contents_class), |
| 82 | description(match.description), |
| 83 | description_class(match.description_class), |
| 84 | transition(match.transition), |
| 85 | is_history_what_you_typed_match(match.is_history_what_you_typed_match), |
| 86 | type(match.type), |
[email protected] | bca359b | 2012-06-24 07:53:04 | [diff] [blame] | 87 | associated_keyword(match.associated_keyword.get() ? |
| 88 | new AutocompleteMatch(*match.associated_keyword) : NULL), |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 89 | keyword(match.keyword), |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 90 | starred(match.starred), |
[email protected] | bca359b | 2012-06-24 07:53:04 | [diff] [blame] | 91 | from_previous(match.from_previous), |
| 92 | search_terms_args(match.search_terms_args.get() ? |
| 93 | new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : |
[email protected] | 5281d42 | 2012-07-28 21:37:10 | [diff] [blame] | 94 | NULL), |
| 95 | additional_info(match.additional_info) { |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 96 | } |
| 97 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 98 | AutocompleteMatch::~AutocompleteMatch() { |
| 99 | } |
| 100 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 101 | AutocompleteMatch& AutocompleteMatch::operator=( |
| 102 | const AutocompleteMatch& match) { |
| 103 | if (this == &match) |
| 104 | return *this; |
| 105 | |
| 106 | provider = match.provider; |
| 107 | relevance = match.relevance; |
[email protected] | cf6256f | 2012-06-12 23:36:01 | [diff] [blame] | 108 | typed_count = match.typed_count; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 109 | deletable = match.deletable; |
| 110 | fill_into_edit = match.fill_into_edit; |
| 111 | inline_autocomplete_offset = match.inline_autocomplete_offset; |
| 112 | destination_url = match.destination_url; |
| 113 | stripped_destination_url = match.stripped_destination_url; |
| 114 | contents = match.contents; |
| 115 | contents_class = match.contents_class; |
| 116 | description = match.description; |
| 117 | description_class = match.description_class; |
| 118 | transition = match.transition; |
| 119 | is_history_what_you_typed_match = match.is_history_what_you_typed_match; |
| 120 | type = match.type; |
| 121 | associated_keyword.reset(match.associated_keyword.get() ? |
| 122 | new AutocompleteMatch(*match.associated_keyword) : NULL); |
| 123 | keyword = match.keyword; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 124 | starred = match.starred; |
| 125 | from_previous = match.from_previous; |
[email protected] | bca359b | 2012-06-24 07:53:04 | [diff] [blame] | 126 | search_terms_args.reset(match.search_terms_args.get() ? |
| 127 | new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : NULL); |
[email protected] | 5281d42 | 2012-07-28 21:37:10 | [diff] [blame] | 128 | additional_info = match.additional_info; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 129 | return *this; |
| 130 | } |
| 131 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 132 | // static |
| 133 | std::string AutocompleteMatch::TypeToString(Type type) { |
[email protected] | fc65f27 | 2011-06-28 22:21:30 | [diff] [blame] | 134 | const char* strings[] = { |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 135 | "url-what-you-typed", |
| 136 | "history-url", |
| 137 | "history-title", |
| 138 | "history-body", |
| 139 | "history-keyword", |
| 140 | "navsuggest", |
| 141 | "search-what-you-typed", |
| 142 | "search-history", |
| 143 | "search-suggest", |
| 144 | "search-other-engine", |
[email protected] | 8f740548 | 2011-04-13 11:08:52 | [diff] [blame] | 145 | "extension-app", |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 146 | }; |
[email protected] | fc65f27 | 2011-06-28 22:21:30 | [diff] [blame] | 147 | COMPILE_ASSERT(arraysize(strings) == NUM_TYPES, |
| 148 | strings_array_must_match_type_enum); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 149 | return strings[type]; |
| 150 | } |
| 151 | |
| 152 | // static |
| 153 | int AutocompleteMatch::TypeToIcon(Type type) { |
[email protected] | fc65f27 | 2011-06-28 22:21:30 | [diff] [blame] | 154 | int icons[] = { |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 155 | IDR_OMNIBOX_HTTP, |
| 156 | IDR_OMNIBOX_HTTP, |
[email protected] | c37ad9e | 2012-06-12 04:57:13 | [diff] [blame] | 157 | IDR_OMNIBOX_HTTP, |
| 158 | IDR_OMNIBOX_HTTP, |
| 159 | IDR_OMNIBOX_HTTP, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 160 | IDR_OMNIBOX_HTTP, |
| 161 | IDR_OMNIBOX_SEARCH, |
| 162 | IDR_OMNIBOX_SEARCH, |
| 163 | IDR_OMNIBOX_SEARCH, |
| 164 | IDR_OMNIBOX_SEARCH, |
[email protected] | 8f740548 | 2011-04-13 11:08:52 | [diff] [blame] | 165 | IDR_OMNIBOX_EXTENSION_APP, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 166 | }; |
[email protected] | fc65f27 | 2011-06-28 22:21:30 | [diff] [blame] | 167 | COMPILE_ASSERT(arraysize(icons) == NUM_TYPES, |
| 168 | icons_array_must_match_type_enum); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 169 | return icons[type]; |
| 170 | } |
| 171 | |
| 172 | // static |
| 173 | bool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1, |
| 174 | const AutocompleteMatch& elem2) { |
| 175 | // For equal-relevance matches, we sort alphabetically, so that providers |
| 176 | // who return multiple elements at the same priority get a "stable" sort |
| 177 | // across multiple updates. |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 178 | return (elem1.relevance == elem2.relevance) ? |
| 179 | (elem1.contents < elem2.contents) : (elem1.relevance > elem2.relevance); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | // static |
| 183 | bool AutocompleteMatch::DestinationSortFunc(const AutocompleteMatch& elem1, |
| 184 | const AutocompleteMatch& elem2) { |
| 185 | // Sort identical destination_urls together. Place the most relevant matches |
| 186 | // first, so that when we call std::unique(), these are the ones that get |
| 187 | // preserved. |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 188 | return DestinationsEqual(elem1, elem2) ? MoreRelevant(elem1, elem2) : |
| 189 | (elem1.stripped_destination_url < elem2.stripped_destination_url); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | // static |
| 193 | bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1, |
| 194 | const AutocompleteMatch& elem2) { |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 195 | return elem1.stripped_destination_url == elem2.stripped_destination_url; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | // static |
| 199 | void AutocompleteMatch::ClassifyMatchInString( |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 200 | const string16& find_text, |
| 201 | const string16& text, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 202 | int style, |
| 203 | ACMatchClassifications* classification) { |
| 204 | ClassifyLocationInString(text.find(find_text), find_text.length(), |
| 205 | text.length(), style, classification); |
| 206 | } |
| 207 | |
[email protected] | 24d692aa | 2011-05-25 23:07:58 | [diff] [blame] | 208 | // static |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 209 | void AutocompleteMatch::ClassifyLocationInString( |
| 210 | size_t match_location, |
| 211 | size_t match_length, |
| 212 | size_t overall_length, |
| 213 | int style, |
| 214 | ACMatchClassifications* classification) { |
| 215 | classification->clear(); |
| 216 | |
| 217 | // Don't classify anything about an empty string |
| 218 | // (AutocompleteMatch::Validate() checks this). |
| 219 | if (overall_length == 0) |
| 220 | return; |
| 221 | |
| 222 | // Mark pre-match portion of string (if any). |
| 223 | if (match_location != 0) { |
| 224 | classification->push_back(ACMatchClassification(0, style)); |
| 225 | } |
| 226 | |
| 227 | // Mark matching portion of string. |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 228 | if (match_location == string16::npos) { |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 229 | // No match, above classification will suffice for whole string. |
| 230 | return; |
| 231 | } |
| 232 | // Classifying an empty match makes no sense and will lead to validation |
| 233 | // errors later. |
[email protected] | eac4499 | 2012-02-14 21:39:35 | [diff] [blame] | 234 | DCHECK_GT(match_length, 0U); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 235 | classification->push_back(ACMatchClassification(match_location, |
| 236 | (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM)); |
| 237 | |
| 238 | // Mark post-match portion of string (if any). |
| 239 | const size_t after_match(match_location + match_length); |
| 240 | if (after_match < overall_length) { |
| 241 | classification->push_back(ACMatchClassification(after_match, style)); |
| 242 | } |
| 243 | } |
| 244 | |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 245 | // static |
[email protected] | 3b81314d | 2012-09-11 02:48:41 | [diff] [blame^] | 246 | AutocompleteMatch::ACMatchClassifications |
| 247 | AutocompleteMatch::MergeClassifications( |
| 248 | const ACMatchClassifications& classifications1, |
| 249 | const ACMatchClassifications& classifications2) { |
| 250 | // We must return the empty vector only if both inputs are truly empty. |
| 251 | // The result of merging an empty vector with a single (0, NONE) |
| 252 | // classification is the latter one-entry vector. |
| 253 | if (IsTrivialClassification(classifications1)) |
| 254 | return classifications2.empty() ? classifications1 : classifications2; |
| 255 | if (IsTrivialClassification(classifications2)) |
| 256 | return classifications1; |
| 257 | |
| 258 | ACMatchClassifications output; |
| 259 | for (ACMatchClassifications::const_iterator i = classifications1.begin(), |
| 260 | j = classifications2.begin(); i != classifications1.end();) { |
| 261 | AutocompleteMatch::AddLastClassificationIfNecessary(&output, |
| 262 | std::max(i->offset, j->offset), i->style | j->style); |
| 263 | const size_t next_i_offset = (i + 1) == classifications1.end() ? |
| 264 | static_cast<size_t>(-1) : (i + 1)->offset; |
| 265 | const size_t next_j_offset = (j + 1) == classifications2.end() ? |
| 266 | static_cast<size_t>(-1) : (j + 1)->offset; |
| 267 | if (next_i_offset >= next_j_offset) |
| 268 | ++j; |
| 269 | if (next_j_offset >= next_i_offset) |
| 270 | ++i; |
| 271 | } |
| 272 | |
| 273 | return output; |
| 274 | } |
| 275 | |
| 276 | // static |
[email protected] | 9d2b5f3b | 2012-03-14 21:34:32 | [diff] [blame] | 277 | std::string AutocompleteMatch::ClassificationsToString( |
| 278 | const ACMatchClassifications& classifications) { |
| 279 | std::string serialized_classifications; |
| 280 | for (size_t i = 0; i < classifications.size(); ++i) { |
| 281 | if (i) |
| 282 | serialized_classifications += ','; |
| 283 | serialized_classifications += base::IntToString(classifications[i].offset) + |
| 284 | ',' + base::IntToString(classifications[i].style); |
| 285 | } |
| 286 | return serialized_classifications; |
| 287 | } |
| 288 | |
| 289 | // static |
| 290 | ACMatchClassifications AutocompleteMatch::ClassificationsFromString( |
| 291 | const std::string& serialized_classifications) { |
| 292 | ACMatchClassifications classifications; |
| 293 | std::vector<std::string> tokens; |
| 294 | Tokenize(serialized_classifications, ",", &tokens); |
| 295 | DCHECK(!(tokens.size() & 1)); // The number of tokens should be even. |
| 296 | for (size_t i = 0; i < tokens.size(); i += 2) { |
| 297 | int classification_offset = 0; |
| 298 | int classification_style = ACMatchClassification::NONE; |
| 299 | if (!base::StringToInt(tokens[i], &classification_offset) || |
| 300 | !base::StringToInt(tokens[i + 1], &classification_style)) { |
| 301 | NOTREACHED(); |
| 302 | return classifications; |
| 303 | } |
| 304 | classifications.push_back(ACMatchClassification(classification_offset, |
| 305 | classification_style)); |
| 306 | } |
| 307 | return classifications; |
| 308 | } |
| 309 | |
| 310 | // static |
| 311 | void AutocompleteMatch::AddLastClassificationIfNecessary( |
| 312 | ACMatchClassifications* classifications, |
| 313 | size_t offset, |
| 314 | int style) { |
| 315 | DCHECK(classifications); |
| 316 | if (classifications->empty() || classifications->back().style != style) { |
| 317 | DCHECK(classifications->empty() || |
| 318 | (offset > classifications->back().offset)); |
| 319 | classifications->push_back(ACMatchClassification(offset, style)); |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | // static |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 324 | string16 AutocompleteMatch::SanitizeString(const string16& text) { |
| 325 | // NOTE: This logic is mirrored by |sanitizeString()| in |
[email protected] | 83820d4 | 2011-11-12 22:03:11 | [diff] [blame] | 326 | // schema_generated_bindings.js. |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 327 | string16 result; |
| 328 | TrimWhitespace(text, TRIM_LEADING, &result); |
[email protected] | 531e034 | 2011-11-10 15:08:41 | [diff] [blame] | 329 | RemoveChars(result, kInvalidChars, &result); |
[email protected] | 5595f40d | 2011-10-28 17:29:18 | [diff] [blame] | 330 | return result; |
| 331 | } |
| 332 | |
[email protected] | 749e7ae0 | 2012-09-05 18:47:46 | [diff] [blame] | 333 | // static |
| 334 | bool AutocompleteMatch::IsSearchType(Type type) { |
| 335 | return type == SEARCH_WHAT_YOU_TYPED || |
| 336 | type == SEARCH_HISTORY || |
| 337 | type == SEARCH_SUGGEST || |
| 338 | type == SEARCH_OTHER_ENGINE; |
| 339 | } |
| 340 | |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 341 | void AutocompleteMatch::ComputeStrippedDestinationURL() { |
[email protected] | 345e8fda | 2012-09-06 01:07:47 | [diff] [blame] | 342 | stripped_destination_url = destination_url; |
| 343 | if (!stripped_destination_url.is_valid()) |
| 344 | return; |
| 345 | |
| 346 | // |replacements| keeps all the substitions we're going to make to |
| 347 | // from {destination_url} to {stripped_destination_url}. |need_replacement| |
| 348 | // is a helper variable that helps us keep track of whether we need |
| 349 | // to apply the replacement. |
| 350 | bool needs_replacement = false; |
| 351 | GURL::Replacements replacements; |
| 352 | |
| 353 | // Remove the www. prefix from the host. |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 354 | static const char prefix[] = "www."; |
| 355 | static const size_t prefix_len = arraysize(prefix) - 1; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 356 | std::string host = destination_url.host(); |
[email protected] | 345e8fda | 2012-09-06 01:07:47 | [diff] [blame] | 357 | if (host.compare(0, prefix_len, prefix) == 0) { |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 358 | host = host.substr(prefix_len); |
[email protected] | 345e8fda | 2012-09-06 01:07:47 | [diff] [blame] | 359 | replacements.SetHostStr(host); |
| 360 | needs_replacement = true; |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 361 | } |
[email protected] | 345e8fda | 2012-09-06 01:07:47 | [diff] [blame] | 362 | |
| 363 | // Replace https protocol with http protocol. |
| 364 | if (stripped_destination_url.SchemeIs(chrome::kHttpsScheme)) { |
| 365 | replacements.SetScheme( |
| 366 | chrome::kHttpScheme, |
| 367 | url_parse::Component(0, strlen(chrome::kHttpScheme))); |
| 368 | needs_replacement = true; |
| 369 | } |
| 370 | |
| 371 | if (needs_replacement) |
| 372 | stripped_destination_url = destination_url.ReplaceComponents(replacements); |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 373 | } |
| 374 | |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 375 | void AutocompleteMatch::GetKeywordUIState(Profile* profile, |
| 376 | string16* keyword, |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 377 | bool* is_keyword_hint) const { |
| 378 | *is_keyword_hint = associated_keyword.get() != NULL; |
| 379 | keyword->assign(*is_keyword_hint ? associated_keyword->keyword : |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 380 | GetSubstitutingExplicitlyInvokedKeyword(profile)); |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 381 | } |
| 382 | |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 383 | string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword( |
| 384 | Profile* profile) const { |
[email protected] | 9b74ab5 | 2012-03-30 16:08:07 | [diff] [blame] | 385 | if (transition != content::PAGE_TRANSITION_KEYWORD) |
| 386 | return string16(); |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 387 | const TemplateURL* t_url = GetTemplateURL(profile); |
[email protected] | 9b74ab5 | 2012-03-30 16:08:07 | [diff] [blame] | 388 | return (t_url && t_url->SupportsReplacement()) ? keyword : string16(); |
[email protected] | 033f342 | 2012-03-13 21:24:18 | [diff] [blame] | 389 | } |
| 390 | |
[email protected] | 85b8d6f | 2012-05-08 20:53:47 | [diff] [blame] | 391 | TemplateURL* AutocompleteMatch::GetTemplateURL(Profile* profile) const { |
| 392 | DCHECK(profile); |
| 393 | return keyword.empty() ? NULL : |
| 394 | TemplateURLServiceFactory::GetForProfile(profile)-> |
| 395 | GetTemplateURLForKeyword(keyword); |
[email protected] | 3cb0f8d9 | 2012-02-29 05:43:34 | [diff] [blame] | 396 | } |
| 397 | |
[email protected] | 5281d42 | 2012-07-28 21:37:10 | [diff] [blame] | 398 | void AutocompleteMatch::RecordAdditionalInfo(const std::string& property, |
| 399 | const std::string& value) { |
| 400 | DCHECK(property.size()); |
| 401 | DCHECK(value.size()); |
| 402 | additional_info[property] = value; |
| 403 | } |
| 404 | |
| 405 | void AutocompleteMatch::RecordAdditionalInfo(const std::string& property, |
| 406 | int value) { |
| 407 | RecordAdditionalInfo(property, StringPrintf("%d", value)); |
| 408 | } |
| 409 | |
| 410 | void AutocompleteMatch::RecordAdditionalInfo(const std::string& property, |
| 411 | const base::Time& value) { |
| 412 | RecordAdditionalInfo(property, |
| 413 | UTF16ToUTF8(base::TimeFormatShortDateAndTime(value))); |
| 414 | } |
| 415 | |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 416 | #ifndef NDEBUG |
| 417 | void AutocompleteMatch::Validate() const { |
| 418 | ValidateClassifications(contents, contents_class); |
| 419 | ValidateClassifications(description, description_class); |
| 420 | } |
| 421 | |
| 422 | void AutocompleteMatch::ValidateClassifications( |
[email protected] | a2fedb1e | 2011-01-25 15:23:36 | [diff] [blame] | 423 | const string16& text, |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 424 | const ACMatchClassifications& classifications) const { |
| 425 | if (text.empty()) { |
[email protected] | 37b9573 | 2011-05-26 23:11:09 | [diff] [blame] | 426 | DCHECK(classifications.empty()); |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 427 | return; |
| 428 | } |
| 429 | |
| 430 | // The classifications should always cover the whole string. |
[email protected] | eac4499 | 2012-02-14 21:39:35 | [diff] [blame] | 431 | DCHECK(!classifications.empty()) << "No classification for \"" << text << '"'; |
| 432 | DCHECK_EQ(0U, classifications[0].offset) |
| 433 | << "Classification misses beginning for \"" << text << '"'; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 434 | if (classifications.size() == 1) |
| 435 | return; |
| 436 | |
| 437 | // The classifications should always be sorted. |
| 438 | size_t last_offset = classifications[0].offset; |
| 439 | for (ACMatchClassifications::const_iterator i(classifications.begin() + 1); |
| 440 | i != classifications.end(); ++i) { |
[email protected] | eac4499 | 2012-02-14 21:39:35 | [diff] [blame] | 441 | DCHECK_GT(i->offset, last_offset) |
[email protected] | 6d478b1 | 2012-06-06 12:19:34 | [diff] [blame] | 442 | << " Classification for \"" << text << "\" with offset of " << i->offset |
| 443 | << " is unsorted in relation to last offset of " << last_offset |
| 444 | << ". Provider: " << (provider ? provider->name() : "None") << "."; |
[email protected] | eac4499 | 2012-02-14 21:39:35 | [diff] [blame] | 445 | DCHECK_LT(i->offset, text.length()) |
[email protected] | 6d478b1 | 2012-06-06 12:19:34 | [diff] [blame] | 446 | << " Classification of [" << i->offset << "," << text.length() |
| 447 | << "] is out of bounds for \"" << text << "\". Provider: " |
| 448 | << (provider ? provider->name() : "None") << "."; |
[email protected] | 9ac4009 | 2010-10-27 23:05:26 | [diff] [blame] | 449 | last_offset = i->offset; |
| 450 | } |
| 451 | } |
| 452 | #endif |