| 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/base64.h" | 10 #include "base/base64.h" |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 125 |
| 126 | 126 |
| 127 // SearchProvider ------------------------------------------------------------- | 127 // SearchProvider ------------------------------------------------------------- |
| 128 | 128 |
| 129 // static | 129 // static |
| 130 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; | 130 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; |
| 131 | 131 |
| 132 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, | 132 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, |
| 133 TemplateURLService* template_url_service, | 133 TemplateURLService* template_url_service, |
| 134 Profile* profile) | 134 Profile* profile) |
| 135 : BaseSearchProvider(listener, template_url_service, profile, | 135 : BaseSearchProvider(template_url_service, profile, |
| 136 AutocompleteProvider::TYPE_SEARCH), | 136 AutocompleteProvider::TYPE_SEARCH), |
| 137 listener_(listener), |
| 138 suggest_results_pending_(0), |
| 137 providers_(template_url_service) { | 139 providers_(template_url_service) { |
| 138 } | 140 } |
| 139 | 141 |
| 140 // static | 142 // static |
| 141 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { | 143 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { |
| 142 return match.GetAdditionalInfo(kSuggestMetadataKey); | 144 return match.GetAdditionalInfo(kSuggestMetadataKey); |
| 143 } | 145 } |
| 144 | 146 |
| 145 void SearchProvider::ResetSession() { | 147 void SearchProvider::ResetSession() { |
| 146 field_trial_triggered_in_session_ = false; | 148 field_trial_triggered_in_session_ = false; |
| 147 } | 149 } |
| 148 | 150 |
| 149 SearchProvider::~SearchProvider() { | 151 SearchProvider::~SearchProvider() { |
| 150 } | 152 } |
| 151 | 153 |
| 152 void SearchProvider::UpdateMatchContentsClass( | |
| 153 const base::string16& input_text, | |
| 154 SearchSuggestionParser::Results* results) { | |
| 155 for (SearchSuggestionParser::SuggestResults::iterator sug_it = | |
| 156 results->suggest_results.begin(); | |
| 157 sug_it != results->suggest_results.end(); ++sug_it) { | |
| 158 sug_it->ClassifyMatchContents(false, input_text); | |
| 159 } | |
| 160 const std::string languages( | |
| 161 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); | |
| 162 for (SearchSuggestionParser::NavigationResults::iterator nav_it = | |
| 163 results->navigation_results.begin(); | |
| 164 nav_it != results->navigation_results.end(); ++nav_it) { | |
| 165 nav_it->CalculateAndClassifyMatchContents(false, input_text, languages); | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 // static | 154 // static |
| 170 int SearchProvider::CalculateRelevanceForKeywordVerbatim( | 155 int SearchProvider::CalculateRelevanceForKeywordVerbatim( |
| 171 metrics::OmniboxInputType::Type type, | 156 metrics::OmniboxInputType::Type type, |
| 172 bool prefer_keyword) { | 157 bool prefer_keyword) { |
| 173 // This function is responsible for scoring verbatim query matches | 158 // This function is responsible for scoring verbatim query matches |
| 174 // for non-extension keywords. KeywordProvider::CalculateRelevance() | 159 // for non-extension keywords. KeywordProvider::CalculateRelevance() |
| 175 // scores verbatim query matches for extension keywords, as well as | 160 // scores verbatim query matches for extension keywords, as well as |
| 176 // for keyword matches (i.e., suggestions of a keyword itself, not a | 161 // for keyword matches (i.e., suggestions of a keyword itself, not a |
| 177 // suggestion of a query on a keyword search engine). These two | 162 // suggestion of a query on a keyword search engine). These two |
| 178 // functions are currently in sync, but there's no reason we | 163 // functions are currently in sync, but there's no reason we |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 243 } |
| 259 | 244 |
| 260 input_ = input; | 245 input_ = input; |
| 261 | 246 |
| 262 DoHistoryQuery(minimal_changes); | 247 DoHistoryQuery(minimal_changes); |
| 263 DoAnswersQuery(input); | 248 DoAnswersQuery(input); |
| 264 StartOrStopSuggestQuery(minimal_changes); | 249 StartOrStopSuggestQuery(minimal_changes); |
| 265 UpdateMatches(); | 250 UpdateMatches(); |
| 266 } | 251 } |
| 267 | 252 |
| 268 void SearchProvider::SortResults(bool is_keyword, | |
| 269 SearchSuggestionParser::Results* results) { | |
| 270 // Ignore suggested scores for non-keyword matches in keyword mode; if the | |
| 271 // server is allowed to score these, it could interfere with the user's | |
| 272 // ability to get good keyword results. | |
| 273 const bool abandon_suggested_scores = | |
| 274 !is_keyword && !providers_.keyword_provider().empty(); | |
| 275 // Apply calculated relevance scores to suggestions if valid relevances were | |
| 276 // not provided or we're abandoning suggested scores entirely. | |
| 277 if (!results->relevances_from_server || abandon_suggested_scores) { | |
| 278 ApplyCalculatedSuggestRelevance(&results->suggest_results); | |
| 279 ApplyCalculatedNavigationRelevance(&results->navigation_results); | |
| 280 // If abandoning scores entirely, also abandon the verbatim score. | |
| 281 if (abandon_suggested_scores) | |
| 282 results->verbatim_relevance = -1; | |
| 283 } | |
| 284 | |
| 285 // Keep the result lists sorted. | |
| 286 const CompareScoredResults comparator = CompareScoredResults(); | |
| 287 std::stable_sort(results->suggest_results.begin(), | |
| 288 results->suggest_results.end(), | |
| 289 comparator); | |
| 290 std::stable_sort(results->navigation_results.begin(), | |
| 291 results->navigation_results.end(), | |
| 292 comparator); | |
| 293 } | |
| 294 | |
| 295 const TemplateURL* SearchProvider::GetTemplateURL(bool is_keyword) const { | 253 const TemplateURL* SearchProvider::GetTemplateURL(bool is_keyword) const { |
| 296 return is_keyword ? providers_.GetKeywordProviderURL() | 254 return is_keyword ? providers_.GetKeywordProviderURL() |
| 297 : providers_.GetDefaultProviderURL(); | 255 : providers_.GetDefaultProviderURL(); |
| 298 } | 256 } |
| 299 | 257 |
| 300 const AutocompleteInput SearchProvider::GetInput(bool is_keyword) const { | 258 const AutocompleteInput SearchProvider::GetInput(bool is_keyword) const { |
| 301 return is_keyword ? keyword_input_ : input_; | 259 return is_keyword ? keyword_input_ : input_; |
| 302 } | 260 } |
| 303 | 261 |
| 304 SearchSuggestionParser::Results* SearchProvider::GetResultsToFill( | |
| 305 bool is_keyword) { | |
| 306 return is_keyword ? &keyword_results_ : &default_results_; | |
| 307 } | |
| 308 | |
| 309 bool SearchProvider::ShouldAppendExtraParams( | 262 bool SearchProvider::ShouldAppendExtraParams( |
| 310 const SearchSuggestionParser::SuggestResult& result) const { | 263 const SearchSuggestionParser::SuggestResult& result) const { |
| 311 return !result.from_keyword_provider() || | 264 return !result.from_keyword_provider() || |
| 312 providers_.default_provider().empty(); | 265 providers_.default_provider().empty(); |
| 313 } | 266 } |
| 314 | 267 |
| 315 void SearchProvider::StopSuggest() { | 268 void SearchProvider::StopSuggest() { |
| 316 // Increment the appropriate field in the histogram by the number of | 269 // Increment the appropriate field in the histogram by the number of |
| 317 // pending requests that were invalidated. | 270 // pending requests that were invalidated. |
| 318 for (int i = 0; i < suggest_results_pending_; ++i) | 271 for (int i = 0; i < suggest_results_pending_; ++i) |
| 319 LogOmniboxSuggestRequest(REQUEST_INVALIDATED); | 272 LogOmniboxSuggestRequest(REQUEST_INVALIDATED); |
| 320 suggest_results_pending_ = 0; | 273 suggest_results_pending_ = 0; |
| 321 timer_.Stop(); | 274 timer_.Stop(); |
| 322 // Stop any in-progress URL fetches. | 275 // Stop any in-progress URL fetches. |
| 323 keyword_fetcher_.reset(); | 276 keyword_fetcher_.reset(); |
| 324 default_fetcher_.reset(); | 277 default_fetcher_.reset(); |
| 325 } | 278 } |
| 326 | 279 |
| 327 void SearchProvider::ClearAllResults() { | 280 void SearchProvider::ClearAllResults() { |
| 328 keyword_results_.Clear(); | 281 keyword_results_.Clear(); |
| 329 default_results_.Clear(); | 282 default_results_.Clear(); |
| 330 } | 283 } |
| 331 | 284 |
| 332 int SearchProvider::GetDefaultResultRelevance() const { | |
| 333 return -1; | |
| 334 } | |
| 335 | |
| 336 void SearchProvider::RecordDeletionResult(bool success) { | 285 void SearchProvider::RecordDeletionResult(bool success) { |
| 337 if (success) { | 286 if (success) { |
| 338 base::RecordAction( | 287 base::RecordAction( |
| 339 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); | 288 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); |
| 340 } else { | 289 } else { |
| 341 base::RecordAction( | 290 base::RecordAction( |
| 342 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); | 291 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); |
| 343 } | 292 } |
| 344 } | 293 } |
| 345 | 294 |
| 295 void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { |
| 296 DCHECK(!done_); |
| 297 --suggest_results_pending_; |
| 298 DCHECK_GE(suggest_results_pending_, 0); // Should never go negative. |
| 299 |
| 300 const bool is_keyword = source == keyword_fetcher_.get(); |
| 301 |
| 302 // Ensure the request succeeded and that the provider used is still available. |
| 303 // A verbatim match cannot be generated without this provider, causing errors. |
| 304 const bool request_succeeded = |
| 305 source->GetStatus().is_success() && (source->GetResponseCode() == 200) && |
| 306 GetTemplateURL(is_keyword); |
| 307 |
| 308 LogFetchComplete(request_succeeded, is_keyword); |
| 309 |
| 310 bool results_updated = false; |
| 311 if (request_succeeded) { |
| 312 scoped_ptr<base::Value> data(SearchSuggestionParser::DeserializeJsonData( |
| 313 SearchSuggestionParser::ExtractJsonData(source))); |
| 314 if (data) { |
| 315 SearchSuggestionParser::Results* results = |
| 316 is_keyword ? &keyword_results_ : &default_results_; |
| 317 results_updated = ParseSuggestResults(*data, -1, is_keyword, results); |
| 318 if (results_updated) |
| 319 SortResults(is_keyword, results); |
| 320 } |
| 321 } |
| 322 UpdateMatches(); |
| 323 if (done_ || results_updated) |
| 324 listener_->OnProviderUpdate(results_updated); |
| 325 } |
| 326 |
| 327 void SearchProvider::UpdateMatchContentsClass( |
| 328 const base::string16& input_text, |
| 329 SearchSuggestionParser::Results* results) { |
| 330 for (SearchSuggestionParser::SuggestResults::iterator sug_it = |
| 331 results->suggest_results.begin(); |
| 332 sug_it != results->suggest_results.end(); ++sug_it) { |
| 333 sug_it->ClassifyMatchContents(false, input_text); |
| 334 } |
| 335 const std::string languages( |
| 336 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
| 337 for (SearchSuggestionParser::NavigationResults::iterator nav_it = |
| 338 results->navigation_results.begin(); |
| 339 nav_it != results->navigation_results.end(); ++nav_it) { |
| 340 nav_it->CalculateAndClassifyMatchContents(false, input_text, languages); |
| 341 } |
| 342 } |
| 343 |
| 344 void SearchProvider::SortResults(bool is_keyword, |
| 345 SearchSuggestionParser::Results* results) { |
| 346 // Ignore suggested scores for non-keyword matches in keyword mode; if the |
| 347 // server is allowed to score these, it could interfere with the user's |
| 348 // ability to get good keyword results. |
| 349 const bool abandon_suggested_scores = |
| 350 !is_keyword && !providers_.keyword_provider().empty(); |
| 351 // Apply calculated relevance scores to suggestions if valid relevances were |
| 352 // not provided or we're abandoning suggested scores entirely. |
| 353 if (!results->relevances_from_server || abandon_suggested_scores) { |
| 354 ApplyCalculatedSuggestRelevance(&results->suggest_results); |
| 355 ApplyCalculatedNavigationRelevance(&results->navigation_results); |
| 356 // If abandoning scores entirely, also abandon the verbatim score. |
| 357 if (abandon_suggested_scores) |
| 358 results->verbatim_relevance = -1; |
| 359 } |
| 360 |
| 361 // Keep the result lists sorted. |
| 362 const CompareScoredResults comparator = CompareScoredResults(); |
| 363 std::stable_sort(results->suggest_results.begin(), |
| 364 results->suggest_results.end(), |
| 365 comparator); |
| 366 std::stable_sort(results->navigation_results.begin(), |
| 367 results->navigation_results.end(), |
| 368 comparator); |
| 369 } |
| 370 |
| 346 void SearchProvider::LogFetchComplete(bool success, bool is_keyword) { | 371 void SearchProvider::LogFetchComplete(bool success, bool is_keyword) { |
| 347 LogOmniboxSuggestRequest(REPLY_RECEIVED); | 372 LogOmniboxSuggestRequest(REPLY_RECEIVED); |
| 348 // Record response time for suggest requests sent to Google. We care | 373 // Record response time for suggest requests sent to Google. We care |
| 349 // only about the common case: the Google default provider used in | 374 // only about the common case: the Google default provider used in |
| 350 // non-keyword mode. | 375 // non-keyword mode. |
| 351 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 376 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
| 352 if (!is_keyword && default_url && | 377 if (!is_keyword && default_url && |
| 353 (TemplateURLPrepopulateData::GetEngineType( | 378 (TemplateURLPrepopulateData::GetEngineType( |
| 354 *default_url, | 379 *default_url, |
| 355 providers_.template_url_service()->search_terms_data()) == | 380 providers_.template_url_service()->search_terms_data()) == |
| 356 SEARCH_ENGINE_GOOGLE)) { | 381 SEARCH_ENGINE_GOOGLE)) { |
| 357 const base::TimeDelta elapsed_time = | 382 const base::TimeDelta elapsed_time = |
| 358 base::TimeTicks::Now() - time_suggest_request_sent_; | 383 base::TimeTicks::Now() - time_suggest_request_sent_; |
| 359 if (success) { | 384 if (success) { |
| 360 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", | 385 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", |
| 361 elapsed_time); | 386 elapsed_time); |
| 362 } else { | 387 } else { |
| 363 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", | 388 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", |
| 364 elapsed_time); | 389 elapsed_time); |
| 365 } | 390 } |
| 366 } | 391 } |
| 367 } | 392 } |
| 368 | 393 |
| 369 bool SearchProvider::IsKeywordFetcher(const net::URLFetcher* fetcher) const { | |
| 370 return fetcher == keyword_fetcher_.get(); | |
| 371 } | |
| 372 | |
| 373 void SearchProvider::UpdateMatches() { | 394 void SearchProvider::UpdateMatches() { |
| 374 ConvertResultsToAutocompleteMatches(); | 395 ConvertResultsToAutocompleteMatches(); |
| 375 | 396 |
| 376 // Check constraints that may be violated by suggested relevances. | 397 // Check constraints that may be violated by suggested relevances. |
| 377 if (!matches_.empty() && | 398 if (!matches_.empty() && |
| 378 (default_results_.HasServerProvidedScores() || | 399 (default_results_.HasServerProvidedScores() || |
| 379 keyword_results_.HasServerProvidedScores())) { | 400 keyword_results_.HasServerProvidedScores())) { |
| 380 // These blocks attempt to repair undesirable behavior by suggested | 401 // These blocks attempt to repair undesirable behavior by suggested |
| 381 // relevances with minimal impact, preserving other suggested relevances. | 402 // relevances with minimal impact, preserving other suggested relevances. |
| 382 | 403 |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 last_answer_seen_.query_type = match->answer_type; | 1262 last_answer_seen_.query_type = match->answer_type; |
| 1242 } | 1263 } |
| 1243 | 1264 |
| 1244 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { | 1265 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { |
| 1245 // If the query text starts with trimmed input, this is valid prefetch data. | 1266 // If the query text starts with trimmed input, this is valid prefetch data. |
| 1246 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, | 1267 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, |
| 1247 base::CollapseWhitespace(input.text(), false), | 1268 base::CollapseWhitespace(input.text(), false), |
| 1248 false) ? | 1269 false) ? |
| 1249 last_answer_seen_ : AnswersQueryData(); | 1270 last_answer_seen_ : AnswersQueryData(); |
| 1250 } | 1271 } |
| OLD | NEW |