OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 relevance_(relevance), | 126 relevance_(relevance), |
127 relevance_from_server_(relevance_from_server) { | 127 relevance_from_server_(relevance_from_server) { |
128 } | 128 } |
129 | 129 |
130 SearchProvider::Result::~Result() { | 130 SearchProvider::Result::~Result() { |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 // SearchProvider::SuggestResult ---------------------------------------------- | 134 // SearchProvider::SuggestResult ---------------------------------------------- |
135 | 135 |
136 SearchProvider::SuggestResult::SuggestResult(const string16& suggestion, | 136 SearchProvider::SuggestResult::SuggestResult( |
137 bool from_keyword_provider, | 137 const string16& suggestion, |
138 int relevance, | 138 bool from_keyword_provider, |
139 bool relevance_from_server) | 139 int relevance, |
140 bool relevance_from_server, | |
141 const string16& input_text) | |
140 : Result(from_keyword_provider, relevance, relevance_from_server), | 142 : Result(from_keyword_provider, relevance, relevance_from_server), |
141 suggestion_(suggestion) { | 143 suggestion_(suggestion) { |
144 contents_.assign(suggestion_); | |
Mark P
2013/08/15 18:34:23
This whole blob was moved from CreateSearchSuggest
| |
145 contents_class_.clear(); | |
146 // We do intra-string highlighting for suggestions - the suggested segment | |
147 // will be highlighted, e.g. for input_text = "you" the suggestion may be | |
148 // "youtube", so we'll bold the "tube" section: you*tube*. | |
149 if (input_text != suggestion_) { | |
150 size_t input_position = contents_.find(input_text); | |
151 if (input_position == string16::npos) { | |
152 // The input text is not a substring of the query string, e.g. input | |
153 // text is "slasdot" and the query string is "slashdot", so we bold the | |
154 // whole thing. | |
155 contents_class_.push_back( | |
156 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
157 } else { | |
158 // TODO(beng): ACMatchClassification::MATCH now seems to just mean | |
159 // "bold" this. Consider modifying the terminology. | |
160 // We don't iterate over the string here annotating all matches because | |
161 // it looks odd to have every occurrence of a substring that may be as | |
162 // short as a single character highlighted in a query suggestion result, | |
163 // e.g. for input text "s" and query string "southwest airlines", it | |
164 // looks odd if both the first and last s are highlighted. | |
165 if (input_position != 0) { | |
166 contents_class_.push_back( | |
167 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
168 } | |
169 contents_class_.push_back( | |
170 ACMatchClassification(input_position, ACMatchClassification::NONE)); | |
171 size_t next_fragment_position = input_position + input_text.length(); | |
172 if (next_fragment_position < suggestion_.length()) { | |
173 contents_class_.push_back( | |
174 ACMatchClassification(next_fragment_position, | |
175 ACMatchClassification::MATCH)); | |
176 } | |
177 } | |
178 } else { | |
179 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the | |
180 // default provider or a keyword search provider. | |
181 contents_class_.push_back( | |
182 ACMatchClassification(0, ACMatchClassification::NONE)); | |
183 | |
184 } | |
142 } | 185 } |
143 | 186 |
144 SearchProvider::SuggestResult::~SuggestResult() { | 187 SearchProvider::SuggestResult::~SuggestResult() { |
145 } | 188 } |
146 | 189 |
147 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { | 190 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { |
148 return StartsWith(suggestion_, input, false); | 191 return StartsWith(suggestion_, input, false); |
149 } | 192 } |
150 | 193 |
151 int SearchProvider::SuggestResult::CalculateRelevance( | 194 int SearchProvider::SuggestResult::CalculateRelevance( |
152 const AutocompleteInput& input, | 195 const AutocompleteInput& input, |
153 bool keyword_provider_requested) const { | 196 bool keyword_provider_requested) const { |
154 if (!from_keyword_provider_ && keyword_provider_requested) | 197 if (!from_keyword_provider_ && keyword_provider_requested) |
155 return 100; | 198 return 100; |
156 return ((input.type() == AutocompleteInput::URL) ? 300 : 600); | 199 return ((input.type() == AutocompleteInput::URL) ? 300 : 600); |
157 } | 200 } |
158 | 201 |
159 | 202 |
160 // SearchProvider::NavigationResult ------------------------------------------- | 203 // SearchProvider::NavigationResult ------------------------------------------- |
161 | 204 |
162 SearchProvider::NavigationResult::NavigationResult( | 205 SearchProvider::NavigationResult::NavigationResult( |
163 const AutocompleteProvider& provider, | 206 const AutocompleteProvider& provider, |
164 const GURL& url, | 207 const GURL& url, |
165 const string16& description, | 208 const string16& description, |
166 bool from_keyword_provider, | 209 bool from_keyword_provider, |
167 int relevance, | 210 int relevance, |
168 bool relevance_from_server) | 211 bool relevance_from_server, |
212 const string16& input_text, | |
213 const std::string& languages) | |
169 : Result(from_keyword_provider, relevance, relevance_from_server), | 214 : Result(from_keyword_provider, relevance, relevance_from_server), |
170 url_(url), | 215 url_(url), |
171 formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( | 216 formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( |
172 url, provider.StringForURLDisplay(url, true, false))), | 217 url, provider.StringForURLDisplay(url, true, false))), |
173 description_(description) { | 218 description_(description) { |
174 DCHECK(url_.is_valid()); | 219 DCHECK(url_.is_valid()); |
220 // First look for the user's input inside the fill_into_edit as it would be | |
Mark P
2013/08/15 18:34:23
This whole section is the necessary parts from Nav
msw
2013/08/15 18:51:03
Can we reduce more duplication between the two?
Mark P
2013/08/15 19:28:15
I can't figure out how. Here's the problem: inlin
msw
2013/08/15 19:48:30
I was thinking of a helper function, but only if w
| |
221 // without trimming the scheme, so we can find matches at the beginning of the | |
222 // scheme. | |
223 const string16& untrimmed_fill_into_edit = formatted_url_; | |
224 const URLPrefix* prefix = | |
225 URLPrefix::BestURLPrefix(untrimmed_fill_into_edit, input_text); | |
226 size_t match_start = (prefix == NULL) ? | |
227 untrimmed_fill_into_edit.find(input_text) : prefix->prefix.length(); | |
228 bool trim_http = !HasHTTPScheme(input_text) && (!prefix || (match_start != 0)) ; | |
229 const net::FormatUrlTypes format_types = | |
230 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | |
231 contents_ = net::FormatUrl(url_, languages, | |
232 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | |
233 // If the first match in the untrimmed string was inside a scheme that we | |
234 // trimmed, look for a subsequent match. | |
235 if (match_start == string16::npos) | |
236 match_start = contents_.find(input_text); | |
237 // Safe if |match_start| is npos; also safe if the input is longer than the | |
238 // remaining contents after |match_start|. | |
239 AutocompleteMatch::ClassifyLocationInString(match_start, input_text.length(), | |
240 contents_.length(), ACMatchClassif ication::URL, | |
241 &contents_class_); | |
175 } | 242 } |
176 | 243 |
177 SearchProvider::NavigationResult::~NavigationResult() { | 244 SearchProvider::NavigationResult::~NavigationResult() { |
178 } | 245 } |
179 | 246 |
180 bool SearchProvider::NavigationResult::IsInlineable( | 247 bool SearchProvider::NavigationResult::IsInlineable( |
181 const string16& input) const { | 248 const string16& input) const { |
182 return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; | 249 return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; |
183 } | 250 } |
184 | 251 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 AutocompleteProvider::TYPE_SEARCH), | 319 AutocompleteProvider::TYPE_SEARCH), |
253 providers_(TemplateURLServiceFactory::GetForProfile(profile)), | 320 providers_(TemplateURLServiceFactory::GetForProfile(profile)), |
254 suggest_results_pending_(0), | 321 suggest_results_pending_(0), |
255 field_trial_triggered_(false), | 322 field_trial_triggered_(false), |
256 field_trial_triggered_in_session_(false) { | 323 field_trial_triggered_in_session_(false) { |
257 } | 324 } |
258 | 325 |
259 // static | 326 // static |
260 AutocompleteMatch SearchProvider::CreateSearchSuggestion( | 327 AutocompleteMatch SearchProvider::CreateSearchSuggestion( |
261 AutocompleteProvider* autocomplete_provider, | 328 AutocompleteProvider* autocomplete_provider, |
262 int relevance, | 329 const SuggestResult& result, |
263 AutocompleteMatch::Type type, | 330 AutocompleteMatch::Type type, |
264 const TemplateURL* template_url, | 331 const TemplateURL* template_url, |
265 const string16& query_string, | |
266 const string16& input_text, | 332 const string16& input_text, |
267 const AutocompleteInput& input, | 333 const AutocompleteInput& input, |
268 bool is_keyword, | |
269 int accepted_suggestion, | 334 int accepted_suggestion, |
270 int omnibox_start_margin, | 335 int omnibox_start_margin, |
271 bool append_extra_query_params) { | 336 bool append_extra_query_params) { |
272 AutocompleteMatch match(autocomplete_provider, relevance, false, type); | 337 AutocompleteMatch match( |
338 autocomplete_provider, result.relevance(), false, type); | |
273 | 339 |
274 if (!template_url) | 340 if (!template_url) |
275 return match; | 341 return match; |
276 match.keyword = template_url->keyword(); | 342 match.keyword = template_url->keyword(); |
277 | 343 |
278 match.contents.assign(query_string); | 344 match.contents = result.contents(); |
279 // We do intra-string highlighting for suggestions - the suggested segment | 345 match.contents_class = result.contents_class(); |
280 // will be highlighted, e.g. for input_text = "you" the suggestion may be | 346 if (input_text == result.suggestion()) |
281 // "youtube", so we'll bold the "tube" section: you*tube*. | |
282 if (input_text != query_string) { | |
283 size_t input_position = match.contents.find(input_text); | |
284 if (input_position == string16::npos) { | |
285 // The input text is not a substring of the query string, e.g. input | |
286 // text is "slasdot" and the query string is "slashdot", so we bold the | |
287 // whole thing. | |
288 match.contents_class.push_back( | |
289 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
290 } else { | |
291 // TODO(beng): ACMatchClassification::MATCH now seems to just mean | |
292 // "bold" this. Consider modifying the terminology. | |
293 // We don't iterate over the string here annotating all matches because | |
294 // it looks odd to have every occurrence of a substring that may be as | |
295 // short as a single character highlighted in a query suggestion result, | |
296 // e.g. for input text "s" and query string "southwest airlines", it | |
297 // looks odd if both the first and last s are highlighted. | |
298 if (input_position != 0) { | |
299 match.contents_class.push_back( | |
300 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
301 } | |
302 match.contents_class.push_back( | |
303 ACMatchClassification(input_position, ACMatchClassification::NONE)); | |
304 size_t next_fragment_position = input_position + input_text.length(); | |
305 if (next_fragment_position < query_string.length()) { | |
306 match.contents_class.push_back( | |
307 ACMatchClassification(next_fragment_position, | |
308 ACMatchClassification::MATCH)); | |
309 } | |
310 } | |
311 } else { | |
312 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the | |
313 // default provider or a keyword search provider. | |
314 match.contents_class.push_back( | |
315 ACMatchClassification(0, ACMatchClassification::NONE)); | |
316 match.allowed_to_be_default_match = true; | 347 match.allowed_to_be_default_match = true; |
317 } | |
318 | 348 |
319 // When the user forced a query, we need to make sure all the fill_into_edit | 349 // When the user forced a query, we need to make sure all the fill_into_edit |
320 // values preserve that property. Otherwise, if the user starts editing a | 350 // values preserve that property. Otherwise, if the user starts editing a |
321 // suggestion, non-Search results will suddenly appear. | 351 // suggestion, non-Search results will suddenly appear. |
322 if (input.type() == AutocompleteInput::FORCED_QUERY) | 352 if (input.type() == AutocompleteInput::FORCED_QUERY) |
323 match.fill_into_edit.assign(ASCIIToUTF16("?")); | 353 match.fill_into_edit.assign(ASCIIToUTF16("?")); |
324 if (is_keyword) | 354 if (result.from_keyword_provider()) |
325 match.fill_into_edit.append(match.keyword + char16(' ')); | 355 match.fill_into_edit.append(match.keyword + char16(' ')); |
326 if (!input.prevent_inline_autocomplete() && | 356 if (!input.prevent_inline_autocomplete() && |
327 StartsWith(query_string, input_text, false)) { | 357 StartsWith(result.suggestion(), input_text, false)) { |
328 match.inline_autocompletion = query_string.substr(input_text.length()); | 358 match.inline_autocompletion = |
359 result.suggestion().substr(input_text.length()); | |
329 match.allowed_to_be_default_match = true; | 360 match.allowed_to_be_default_match = true; |
330 } | 361 } |
331 match.fill_into_edit.append(query_string); | 362 match.fill_into_edit.append(result.suggestion()); |
332 | 363 |
333 const TemplateURLRef& search_url = template_url->url_ref(); | 364 const TemplateURLRef& search_url = template_url->url_ref(); |
334 DCHECK(search_url.SupportsReplacement()); | 365 DCHECK(search_url.SupportsReplacement()); |
335 match.search_terms_args.reset( | 366 match.search_terms_args.reset( |
336 new TemplateURLRef::SearchTermsArgs(query_string)); | 367 new TemplateURLRef::SearchTermsArgs(result.suggestion())); |
337 match.search_terms_args->original_query = input_text; | 368 match.search_terms_args->original_query = input_text; |
338 match.search_terms_args->accepted_suggestion = accepted_suggestion; | 369 match.search_terms_args->accepted_suggestion = accepted_suggestion; |
339 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; | 370 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; |
340 match.search_terms_args->append_extra_query_params = | 371 match.search_terms_args->append_extra_query_params = |
341 append_extra_query_params; | 372 append_extra_query_params; |
342 // This is the destination URL sans assisted query stats. This must be set | 373 // This is the destination URL sans assisted query stats. This must be set |
343 // so the AutocompleteController can properly de-dupe; the controller will | 374 // so the AutocompleteController can properly de-dupe; the controller will |
344 // eventually overwrite it before it reaches the user. | 375 // eventually overwrite it before it reaches the user. |
345 match.destination_url = | 376 match.destination_url = |
346 GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get())); | 377 GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get())); |
347 | 378 |
348 // Search results don't look like URLs. | 379 // Search results don't look like URLs. |
349 match.transition = is_keyword ? | 380 match.transition = result.from_keyword_provider() ? |
350 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; | 381 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; |
351 | 382 |
352 return match; | 383 return match; |
353 } | 384 } |
354 | 385 |
355 void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { | 386 void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { |
356 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); | 387 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); |
357 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); | 388 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); |
358 new_entry.set_provider(AsOmniboxEventProviderType()); | 389 new_entry.set_provider(AsOmniboxEventProviderType()); |
359 new_entry.set_provider_done(done_); | 390 new_entry.set_provider_done(done_); |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
899 field_trial_triggered_in_session_ |= triggered; | 930 field_trial_triggered_in_session_ |= triggered; |
900 } | 931 } |
901 | 932 |
902 // Clear the previous results now that new results are available. | 933 // Clear the previous results now that new results are available. |
903 results->suggest_results.clear(); | 934 results->suggest_results.clear(); |
904 results->navigation_results.clear(); | 935 results->navigation_results.clear(); |
905 | 936 |
906 string16 result, title; | 937 string16 result, title; |
907 std::string type; | 938 std::string type; |
908 int relevance = -1; | 939 int relevance = -1; |
940 const std::string& languages = | |
941 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); | |
909 for (size_t index = 0; results_list->GetString(index, &result); ++index) { | 942 for (size_t index = 0; results_list->GetString(index, &result); ++index) { |
910 // Google search may return empty suggestions for weird input characters, | 943 // Google search may return empty suggestions for weird input characters, |
911 // they make no sense at all and can cause problems in our code. | 944 // they make no sense at all and can cause problems in our code. |
912 if (result.empty()) | 945 if (result.empty()) |
913 continue; | 946 continue; |
914 | 947 |
915 // Apply valid suggested relevance scores; discard invalid lists. | 948 // Apply valid suggested relevance scores; discard invalid lists. |
916 if (relevances != NULL && !relevances->GetInteger(index, &relevance)) | 949 if (relevances != NULL && !relevances->GetInteger(index, &relevance)) |
917 relevances = NULL; | 950 relevances = NULL; |
951 string16 contents; | |
952 ACMatchClassifications contents_class; | |
Mark P
2013/08/15 18:34:23
Forgot to delete those two lines, sorry.
| |
918 if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { | 953 if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { |
919 // Do not blindly trust the URL coming from the server to be valid. | 954 // Do not blindly trust the URL coming from the server to be valid. |
920 GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(result), std::string())); | 955 GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(result), std::string())); |
921 if (url.is_valid()) { | 956 if (url.is_valid()) { |
922 if (descriptions != NULL) | 957 if (descriptions != NULL) |
923 descriptions->GetString(index, &title); | 958 descriptions->GetString(index, &title); |
924 results->navigation_results.push_back(NavigationResult( | 959 results->navigation_results.push_back(NavigationResult( |
925 *this, url, title, is_keyword, relevance, true)); | 960 *this, url, title, is_keyword, relevance, true, input_text, language s)); |
926 } | 961 } |
927 } else { | 962 } else { |
928 // TODO(kochi): Improve calculator result presentation. | 963 // TODO(kochi): Improve calculator result presentation. |
929 results->suggest_results.push_back( | 964 results->suggest_results.push_back( |
930 SuggestResult(result, is_keyword, relevance, true)); | 965 SuggestResult(result, is_keyword, relevance, true, input_text)); |
931 } | 966 } |
932 } | 967 } |
933 | 968 |
934 // Apply calculated relevance scores if a valid list was not provided. | 969 // Apply calculated relevance scores if a valid list was not provided. |
935 if (relevances == NULL) { | 970 if (relevances == NULL) { |
936 ApplyCalculatedSuggestRelevance(&results->suggest_results); | 971 ApplyCalculatedSuggestRelevance(&results->suggest_results); |
937 ApplyCalculatedNavigationRelevance(&results->navigation_results); | 972 ApplyCalculatedNavigationRelevance(&results->navigation_results); |
938 } | 973 } |
939 // Keep the result lists sorted. | 974 // Keep the result lists sorted. |
940 const CompareScoredResults comparator = CompareScoredResults(); | 975 const CompareScoredResults comparator = CompareScoredResults(); |
(...skipping 16 matching lines...) Expand all Loading... | |
957 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 992 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
958 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 993 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
959 | 994 |
960 bool relevance_from_server; | 995 bool relevance_from_server; |
961 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); | 996 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); |
962 int did_not_accept_default_suggestion = | 997 int did_not_accept_default_suggestion = |
963 default_results_.suggest_results.empty() ? | 998 default_results_.suggest_results.empty() ? |
964 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 999 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
965 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 1000 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
966 if (verbatim_relevance > 0) { | 1001 if (verbatim_relevance > 0) { |
967 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, | 1002 SuggestResult verbatim( |
968 relevance_from_server, | 1003 input_.text(), false, verbatim_relevance, relevance_from_server, input_. text()); |
1004 AddMatchToMap(verbatim, input_.text(), | |
969 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, | 1005 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
970 did_not_accept_default_suggestion, false, &map); | 1006 did_not_accept_default_suggestion, &map); |
971 } | 1007 } |
972 if (!keyword_input_.text().empty()) { | 1008 if (!keyword_input_.text().empty()) { |
973 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 1009 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
974 // We only create the verbatim search query match for a keyword | 1010 // We only create the verbatim search query match for a keyword |
975 // if it's not an extension keyword. Extension keywords are handled | 1011 // if it's not an extension keyword. Extension keywords are handled |
976 // in KeywordProvider::Start(). (Extensions are complicated...) | 1012 // in KeywordProvider::Start(). (Extensions are complicated...) |
977 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond | 1013 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond |
978 // to the keyword verbatim search query. Do not create other matches | 1014 // to the keyword verbatim search query. Do not create other matches |
979 // of type SEARCH_OTHER_ENGINE. | 1015 // of type SEARCH_OTHER_ENGINE. |
980 if (keyword_url && !keyword_url->IsExtensionKeyword()) { | 1016 if (keyword_url && !keyword_url->IsExtensionKeyword()) { |
981 bool keyword_relevance_from_server; | 1017 bool keyword_relevance_from_server; |
982 const int keyword_verbatim_relevance = | 1018 const int keyword_verbatim_relevance = |
983 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); | 1019 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); |
984 if (keyword_verbatim_relevance > 0) { | 1020 if (keyword_verbatim_relevance > 0) { |
985 AddMatchToMap(keyword_input_.text(), keyword_input_.text(), | 1021 SuggestResult keyword_verbatim( |
986 keyword_verbatim_relevance, keyword_relevance_from_server, | 1022 keyword_input_.text(), true, keyword_verbatim_relevance, |
1023 keyword_relevance_from_server, keyword_input_.text()); | |
1024 AddMatchToMap(keyword_verbatim, keyword_input_.text(), | |
987 AutocompleteMatchType::SEARCH_OTHER_ENGINE, | 1025 AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
988 did_not_accept_keyword_suggestion, true, &map); | 1026 did_not_accept_keyword_suggestion, &map); |
989 } | 1027 } |
990 } | 1028 } |
991 } | 1029 } |
992 AddHistoryResultsToMap(keyword_history_results_, true, | 1030 AddHistoryResultsToMap(keyword_history_results_, true, |
993 did_not_accept_keyword_suggestion, &map); | 1031 did_not_accept_keyword_suggestion, &map); |
994 AddHistoryResultsToMap(default_history_results_, false, | 1032 AddHistoryResultsToMap(default_history_results_, false, |
995 did_not_accept_default_suggestion, &map); | 1033 did_not_accept_default_suggestion, &map); |
996 | 1034 |
997 AddSuggestResultsToMap(keyword_results_.suggest_results, &map); | 1035 AddSuggestResultsToMap(keyword_results_.suggest_results, &map); |
998 AddSuggestResultsToMap(default_results_.suggest_results, &map); | 1036 AddSuggestResultsToMap(default_results_.suggest_results, &map); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 AutocompleteResult::kLowestDefaultScore) || | 1239 AutocompleteResult::kLowestDefaultScore) || |
1202 !HasMultipleWords(scored_results.front().suggestion())) | 1240 !HasMultipleWords(scored_results.front().suggestion())) |
1203 scored_results.clear(); // Didn't detect the case above, score normally. | 1241 scored_results.clear(); // Didn't detect the case above, score normally. |
1204 } | 1242 } |
1205 if (scored_results.empty()) | 1243 if (scored_results.empty()) |
1206 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 1244 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, |
1207 input_multiple_words, input_text, | 1245 input_multiple_words, input_text, |
1208 is_keyword); | 1246 is_keyword); |
1209 for (SuggestResults::const_iterator i(scored_results.begin()); | 1247 for (SuggestResults::const_iterator i(scored_results.begin()); |
1210 i != scored_results.end(); ++i) { | 1248 i != scored_results.end(); ++i) { |
1211 AddMatchToMap(i->suggestion(), input_text, i->relevance(), false, | 1249 AddMatchToMap(*i, input_text, |
1212 AutocompleteMatchType::SEARCH_HISTORY, | 1250 AutocompleteMatchType::SEARCH_HISTORY, |
1213 did_not_accept_suggestion, | 1251 did_not_accept_suggestion, map); |
1214 is_keyword, map); | |
1215 } | 1252 } |
1216 } | 1253 } |
1217 | 1254 |
1218 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( | 1255 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
1219 const HistoryResults& results, | 1256 const HistoryResults& results, |
1220 bool base_prevent_inline_autocomplete, | 1257 bool base_prevent_inline_autocomplete, |
1221 bool input_multiple_words, | 1258 bool input_multiple_words, |
1222 const string16& input_text, | 1259 const string16& input_text, |
1223 bool is_keyword) { | 1260 bool is_keyword) { |
1224 AutocompleteClassifier* classifier = | 1261 AutocompleteClassifier* classifier = |
(...skipping 26 matching lines...) Expand all Loading... | |
1251 AutocompleteMatch match; | 1288 AutocompleteMatch match; |
1252 classifier->Classify(i->term, false, false, &match, NULL); | 1289 classifier->Classify(i->term, false, false, &match, NULL); |
1253 prevent_inline_autocomplete = | 1290 prevent_inline_autocomplete = |
1254 !AutocompleteMatch::IsSearchType(match.type); | 1291 !AutocompleteMatch::IsSearchType(match.type); |
1255 } | 1292 } |
1256 | 1293 |
1257 int relevance = CalculateRelevanceForHistory( | 1294 int relevance = CalculateRelevanceForHistory( |
1258 i->time, is_keyword, !prevent_inline_autocomplete, | 1295 i->time, is_keyword, !prevent_inline_autocomplete, |
1259 prevent_search_history_inlining); | 1296 prevent_search_history_inlining); |
1260 scored_results.push_back( | 1297 scored_results.push_back( |
1261 SuggestResult(i->term, is_keyword, relevance, false)); | 1298 SuggestResult(i->term, is_keyword, relevance, false, input_text)); |
1262 } | 1299 } |
1263 | 1300 |
1264 // History returns results sorted for us. However, we may have docked some | 1301 // History returns results sorted for us. However, we may have docked some |
1265 // results' scores, so things are no longer in order. Do a stable sort to get | 1302 // results' scores, so things are no longer in order. Do a stable sort to get |
1266 // things back in order without otherwise disturbing results with equal | 1303 // things back in order without otherwise disturbing results with equal |
1267 // scores, then force the scores to be unique, so that the order in which | 1304 // scores, then force the scores to be unique, so that the order in which |
1268 // they're shown is deterministic. | 1305 // they're shown is deterministic. |
1269 std::stable_sort(scored_results.begin(), scored_results.end(), | 1306 std::stable_sort(scored_results.begin(), scored_results.end(), |
1270 CompareScoredResults()); | 1307 CompareScoredResults()); |
1271 int last_relevance = 0; | 1308 int last_relevance = 0; |
1272 for (SuggestResults::iterator i(scored_results.begin()); | 1309 for (SuggestResults::iterator i(scored_results.begin()); |
1273 i != scored_results.end(); ++i) { | 1310 i != scored_results.end(); ++i) { |
1274 if ((i != scored_results.begin()) && (i->relevance() >= last_relevance)) | 1311 if ((i != scored_results.begin()) && (i->relevance() >= last_relevance)) |
1275 i->set_relevance(last_relevance - 1); | 1312 i->set_relevance(last_relevance - 1); |
1276 last_relevance = i->relevance(); | 1313 last_relevance = i->relevance(); |
1277 } | 1314 } |
1278 | 1315 |
1279 return scored_results; | 1316 return scored_results; |
1280 } | 1317 } |
1281 | 1318 |
1282 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, | 1319 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, |
1283 MatchMap* map) { | 1320 MatchMap* map) { |
1284 for (size_t i = 0; i < results.size(); ++i) { | 1321 for (size_t i = 0; i < results.size(); ++i) { |
1285 const bool is_keyword = results[i].from_keyword_provider(); | 1322 const string16& input = results[i].from_keyword_provider() ? |
1286 const string16& input = is_keyword ? keyword_input_.text() : input_.text(); | 1323 keyword_input_.text() : input_.text(); |
1287 AddMatchToMap(results[i].suggestion(), input, results[i].relevance(), | 1324 AddMatchToMap(results[i], input, |
1288 results[i].relevance_from_server(), | 1325 AutocompleteMatchType::SEARCH_SUGGEST, i, map); |
1289 AutocompleteMatchType::SEARCH_SUGGEST, i, is_keyword, map); | |
1290 } | 1326 } |
1291 } | 1327 } |
1292 | 1328 |
1293 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { | 1329 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { |
1294 // Use the suggested verbatim relevance score if it is non-negative (valid), | 1330 // Use the suggested verbatim relevance score if it is non-negative (valid), |
1295 // if inline autocomplete isn't prevented (always show verbatim on backspace), | 1331 // if inline autocomplete isn't prevented (always show verbatim on backspace), |
1296 // and if it won't suppress verbatim, leaving no default provider matches. | 1332 // and if it won't suppress verbatim, leaving no default provider matches. |
1297 // Otherwise, if the default provider returned no matches and was still able | 1333 // Otherwise, if the default provider returned no matches and was still able |
1298 // to suppress verbatim, the user would have no search/nav matches and may be | 1334 // to suppress verbatim, the user would have no search/nav matches and may be |
1299 // left unable to search using their default provider from the omnibox. | 1335 // left unable to search using their default provider from the omnibox. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1391 // Don't let scores go below 0. Negative relevance scores are meaningful in | 1427 // Don't let scores go below 0. Negative relevance scores are meaningful in |
1392 // a different way. | 1428 // a different way. |
1393 int base_score; | 1429 int base_score; |
1394 if (is_primary_provider) | 1430 if (is_primary_provider) |
1395 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; | 1431 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; |
1396 else | 1432 else |
1397 base_score = 200; | 1433 base_score = 200; |
1398 return std::max(0, base_score - score_discount); | 1434 return std::max(0, base_score - score_discount); |
1399 } | 1435 } |
1400 | 1436 |
1401 void SearchProvider::AddMatchToMap(const string16& query_string, | 1437 void SearchProvider::AddMatchToMap(const SuggestResult& result, |
1402 const string16& input_text, | 1438 const string16& input_text, |
1403 int relevance, | |
1404 bool relevance_from_server, | |
1405 AutocompleteMatch::Type type, | 1439 AutocompleteMatch::Type type, |
1406 int accepted_suggestion, | 1440 int accepted_suggestion, |
1407 bool is_keyword, | |
1408 MatchMap* map) { | 1441 MatchMap* map) { |
1409 // On non-mobile, ask the instant controller for the appropriate start margin. | 1442 // On non-mobile, ask the instant controller for the appropriate start margin. |
1410 // On mobile the start margin is unused, so leave the value as default there. | 1443 // On mobile the start margin is unused, so leave the value as default there. |
1411 int omnibox_start_margin = chrome::kDisableStartMargin; | 1444 int omnibox_start_margin = chrome::kDisableStartMargin; |
1412 #if !defined(OS_ANDROID) && !defined(IOS) | 1445 #if !defined(OS_ANDROID) && !defined(IOS) |
1413 if (chrome::IsInstantExtendedAPIEnabled()) { | 1446 if (chrome::IsInstantExtendedAPIEnabled()) { |
1414 Browser* browser = | 1447 Browser* browser = |
1415 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); | 1448 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); |
1416 if (browser && browser->instant_controller() && | 1449 if (browser && browser->instant_controller() && |
1417 browser->instant_controller()->instant()) { | 1450 browser->instant_controller()->instant()) { |
1418 omnibox_start_margin = | 1451 omnibox_start_margin = |
1419 browser->instant_controller()->instant()->omnibox_bounds().x(); | 1452 browser->instant_controller()->instant()->omnibox_bounds().x(); |
1420 } | 1453 } |
1421 } | 1454 } |
1422 #endif // !defined(OS_ANDROID) && !defined(IOS) | 1455 #endif // !defined(OS_ANDROID) && !defined(IOS) |
1423 | 1456 |
1424 const TemplateURL* template_url = is_keyword ? | 1457 const TemplateURL* template_url = result.from_keyword_provider() ? |
1425 providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL(); | 1458 providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL(); |
1426 AutocompleteMatch match = CreateSearchSuggestion(this, relevance, type, | 1459 AutocompleteMatch match = CreateSearchSuggestion(this, result, |
1427 template_url, query_string, input_text, input_, is_keyword, | 1460 type, template_url, input_text, input_, accepted_suggestion, |
1428 accepted_suggestion, omnibox_start_margin, | 1461 omnibox_start_margin, |
1429 !is_keyword || providers_.default_provider().empty()); | 1462 !result.from_keyword_provider() || providers_.default_provider().empty()); |
1430 if (!match.destination_url.is_valid()) | 1463 if (!match.destination_url.is_valid()) |
1431 return; | 1464 return; |
1432 match.RecordAdditionalInfo(kRelevanceFromServerKey, | 1465 match.RecordAdditionalInfo(kRelevanceFromServerKey, |
1433 relevance_from_server ? kTrue : kFalse); | 1466 result.relevance_from_server() ? kTrue : kFalse); |
1434 | 1467 |
1435 // Try to add |match| to |map|. If a match for |query_string| is already in | 1468 // Try to add |match| to |map|. If a match for |query_string| is already in |
1436 // |map|, replace it if |match| is more relevant. | 1469 // |map|, replace it if |match| is more relevant. |
1437 // NOTE: Keep this ToLower() call in sync with url_database.cc. | 1470 // NOTE: Keep this ToLower() call in sync with url_database.cc. |
1438 const std::pair<MatchMap::iterator, bool> i( | 1471 const std::pair<MatchMap::iterator, bool> i(map->insert(std::make_pair( |
1439 map->insert(std::make_pair(base::i18n::ToLower(query_string), match))); | 1472 base::i18n::ToLower(result.suggestion()), match))); |
1440 // NOTE: We purposefully do a direct relevance comparison here instead of | 1473 // NOTE: We purposefully do a direct relevance comparison here instead of |
1441 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added | 1474 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added |
1442 // first" rather than "items alphabetically first" when the scores are equal. | 1475 // first" rather than "items alphabetically first" when the scores are equal. |
1443 // The only case this matters is when a user has results with the same score | 1476 // The only case this matters is when a user has results with the same score |
1444 // that differ only by capitalization; because the history system returns | 1477 // that differ only by capitalization; because the history system returns |
1445 // results sorted by recency, this means we'll pick the most recent such | 1478 // results sorted by recency, this means we'll pick the most recent such |
1446 // result even if the precision of our relevance score is too low to | 1479 // result even if the precision of our relevance score is too low to |
1447 // distinguish the two. | 1480 // distinguish the two. |
1448 if (!i.second && (match.relevance > i.first->second.relevance)) | 1481 if (!i.second && (match.relevance > i.first->second.relevance)) |
1449 i.first->second = match; | 1482 i.first->second = match; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1487 net::UnescapeRule::SPACES, NULL, NULL, | 1520 net::UnescapeRule::SPACES, NULL, NULL, |
1488 &inline_autocomplete_offset)); | 1521 &inline_autocomplete_offset)); |
1489 if (!input_.prevent_inline_autocomplete() && | 1522 if (!input_.prevent_inline_autocomplete() && |
1490 (inline_autocomplete_offset != string16::npos)) { | 1523 (inline_autocomplete_offset != string16::npos)) { |
1491 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1524 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
1492 match.allowed_to_be_default_match = true; | 1525 match.allowed_to_be_default_match = true; |
1493 match.inline_autocompletion = | 1526 match.inline_autocompletion = |
1494 match.fill_into_edit.substr(inline_autocomplete_offset); | 1527 match.fill_into_edit.substr(inline_autocomplete_offset); |
1495 } | 1528 } |
1496 | 1529 |
1497 match.contents = net::FormatUrl(navigation.url(), languages, | 1530 match.contents = navigation.contents(); |
1498 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | 1531 match.contents_class = navigation.contents_class(); |
1499 // If the first match in the untrimmed string was inside a scheme that we | |
1500 // trimmed, look for a subsequent match. | |
1501 if (match_start == string16::npos) | |
1502 match_start = match.contents.find(input); | |
1503 // Safe if |match_start| is npos; also safe if the input is longer than the | |
1504 // remaining contents after |match_start|. | |
1505 AutocompleteMatch::ClassifyLocationInString(match_start, input.length(), | |
1506 match.contents.length(), ACMatchClassification::URL, | |
1507 &match.contents_class); | |
1508 | |
1509 match.description = navigation.description(); | 1532 match.description = navigation.description(); |
1510 AutocompleteMatch::ClassifyMatchInString(input, match.description, | 1533 AutocompleteMatch::ClassifyMatchInString(input, match.description, |
1511 ACMatchClassification::NONE, &match.description_class); | 1534 ACMatchClassification::NONE, &match.description_class); |
1512 | 1535 |
1513 match.RecordAdditionalInfo( | 1536 match.RecordAdditionalInfo( |
1514 kRelevanceFromServerKey, | 1537 kRelevanceFromServerKey, |
1515 navigation.relevance_from_server() ? kTrue : kFalse); | 1538 navigation.relevance_from_server() ? kTrue : kFalse); |
1516 | 1539 |
1517 return match; | 1540 return match; |
1518 } | 1541 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1556 it->set_relevance(max_query_relevance); | 1579 it->set_relevance(max_query_relevance); |
1557 it->set_relevance_from_server(relevance_from_server); | 1580 it->set_relevance_from_server(relevance_from_server); |
1558 } | 1581 } |
1559 } | 1582 } |
1560 | 1583 |
1561 void SearchProvider::UpdateDone() { | 1584 void SearchProvider::UpdateDone() { |
1562 // We're done when the timer isn't running, there are no suggest queries | 1585 // We're done when the timer isn't running, there are no suggest queries |
1563 // pending, and we're not waiting on Instant. | 1586 // pending, and we're not waiting on Instant. |
1564 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); | 1587 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
1565 } | 1588 } |
OLD | NEW |