| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/base_search_provider.h" | 5 #include "chrome/browser/autocomplete/base_search_provider.h" |
| 6 | 6 |
| 7 #include "base/i18n/case_conversion.h" | 7 #include "base/i18n/case_conversion.h" |
| 8 #include "base/i18n/icu_string_conversions.h" | |
| 9 #include "base/json/json_string_value_serializer.h" | |
| 10 #include "base/prefs/pref_registry_simple.h" | 8 #include "base/prefs/pref_registry_simple.h" |
| 11 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
| 12 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 14 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" | 12 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" |
| 15 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" | 13 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" |
| 16 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" | 14 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" |
| 17 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" | 15 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" |
| 18 #include "chrome/browser/history/history_service.h" | 16 #include "chrome/browser/history/history_service.h" |
| 19 #include "chrome/browser/history/history_service_factory.h" | 17 #include "chrome/browser/history/history_service_factory.h" |
| 20 #include "chrome/browser/omnibox/omnibox_field_trial.h" | 18 #include "chrome/browser/omnibox/omnibox_field_trial.h" |
| 21 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 22 #include "chrome/browser/search/search.h" | 20 #include "chrome/browser/search/search.h" |
| 23 #include "chrome/browser/search_engines/template_url_service_factory.h" | 21 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 24 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" | 22 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" |
| 25 #include "chrome/browser/sync/profile_sync_service.h" | 23 #include "chrome/browser/sync/profile_sync_service.h" |
| 26 #include "chrome/browser/sync/profile_sync_service_factory.h" | 24 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 27 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
| 28 #include "components/metrics/proto/omnibox_event.pb.h" | 26 #include "components/metrics/proto/omnibox_event.pb.h" |
| 29 #include "components/metrics/proto/omnibox_input_type.pb.h" | 27 #include "components/metrics/proto/omnibox_input_type.pb.h" |
| 30 #include "components/search_engines/template_url.h" | 28 #include "components/search_engines/template_url.h" |
| 31 #include "components/search_engines/template_url_prepopulate_data.h" | 29 #include "components/search_engines/template_url_prepopulate_data.h" |
| 32 #include "components/search_engines/template_url_service.h" | 30 #include "components/search_engines/template_url_service.h" |
| 33 #include "components/sync_driver/sync_prefs.h" | 31 #include "components/sync_driver/sync_prefs.h" |
| 34 #include "content/public/common/url_constants.h" | 32 #include "content/public/common/url_constants.h" |
| 35 #include "net/base/escape.h" | 33 #include "net/base/escape.h" |
| 36 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 34 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 37 #include "net/http/http_response_headers.h" | |
| 38 #include "net/url_request/url_fetcher.h" | 35 #include "net/url_request/url_fetcher.h" |
| 39 #include "net/url_request/url_fetcher_delegate.h" | 36 #include "net/url_request/url_fetcher_delegate.h" |
| 40 #include "url/gurl.h" | 37 #include "url/gurl.h" |
| 41 | 38 |
| 42 using metrics::OmniboxEventProto; | 39 using metrics::OmniboxEventProto; |
| 43 | 40 |
| 44 // SuggestionDeletionHandler ------------------------------------------------- | 41 // SuggestionDeletionHandler ------------------------------------------------- |
| 45 | 42 |
| 46 // This class handles making requests to the server in order to delete | 43 // This class handles making requests to the server in order to delete |
| 47 // personalized suggestions. | 44 // personalized suggestions. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 search_terms_data)); | 284 search_terms_data)); |
| 288 | 285 |
| 289 // Search results don't look like URLs. | 286 // Search results don't look like URLs. |
| 290 match.transition = suggestion.from_keyword_provider() ? | 287 match.transition = suggestion.from_keyword_provider() ? |
| 291 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; | 288 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; |
| 292 | 289 |
| 293 return match; | 290 return match; |
| 294 } | 291 } |
| 295 | 292 |
| 296 // static | 293 // static |
| 297 scoped_ptr<base::Value> BaseSearchProvider::DeserializeJsonData( | |
| 298 std::string json_data) { | |
| 299 // The JSON response should be an array. | |
| 300 for (size_t response_start_index = json_data.find("["), i = 0; | |
| 301 response_start_index != std::string::npos && i < 5; | |
| 302 response_start_index = json_data.find("[", 1), i++) { | |
| 303 // Remove any XSSI guards to allow for JSON parsing. | |
| 304 if (response_start_index > 0) | |
| 305 json_data.erase(0, response_start_index); | |
| 306 | |
| 307 JSONStringValueSerializer deserializer(json_data); | |
| 308 deserializer.set_allow_trailing_comma(true); | |
| 309 int error_code = 0; | |
| 310 scoped_ptr<base::Value> data(deserializer.Deserialize(&error_code, NULL)); | |
| 311 if (error_code == 0) | |
| 312 return data.Pass(); | |
| 313 } | |
| 314 return scoped_ptr<base::Value>(); | |
| 315 } | |
| 316 | |
| 317 // static | |
| 318 bool BaseSearchProvider::ZeroSuggestEnabled( | 294 bool BaseSearchProvider::ZeroSuggestEnabled( |
| 319 const GURL& suggest_url, | 295 const GURL& suggest_url, |
| 320 const TemplateURL* template_url, | 296 const TemplateURL* template_url, |
| 321 OmniboxEventProto::PageClassification page_classification, | 297 OmniboxEventProto::PageClassification page_classification, |
| 322 Profile* profile) { | 298 Profile* profile) { |
| 323 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial()) | 299 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial()) |
| 324 return false; | 300 return false; |
| 325 | 301 |
| 326 // Make sure we are sending the suggest request through HTTPS to prevent | 302 // Make sure we are sending the suggest request through HTTPS to prevent |
| 327 // exposing the current page URL or personalized results without encryption. | 303 // exposing the current page URL or personalized results without encryption. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 // Ensure the request succeeded and that the provider used is still available. | 381 // Ensure the request succeeded and that the provider used is still available. |
| 406 // A verbatim match cannot be generated without this provider, causing errors. | 382 // A verbatim match cannot be generated without this provider, causing errors. |
| 407 const bool request_succeeded = | 383 const bool request_succeeded = |
| 408 source->GetStatus().is_success() && (source->GetResponseCode() == 200) && | 384 source->GetStatus().is_success() && (source->GetResponseCode() == 200) && |
| 409 GetTemplateURL(is_keyword); | 385 GetTemplateURL(is_keyword); |
| 410 | 386 |
| 411 LogFetchComplete(request_succeeded, is_keyword); | 387 LogFetchComplete(request_succeeded, is_keyword); |
| 412 | 388 |
| 413 bool results_updated = false; | 389 bool results_updated = false; |
| 414 if (request_succeeded) { | 390 if (request_succeeded) { |
| 415 const net::HttpResponseHeaders* const response_headers = | 391 std::string json_data = SearchSuggestionParser::ExtractJsonData(source); |
| 416 source->GetResponseHeaders(); | 392 scoped_ptr<base::Value> data( |
| 417 std::string json_data; | 393 SearchSuggestionParser::DeserializeJsonData(json_data)); |
| 418 source->GetResponseAsString(&json_data); | |
| 419 | |
| 420 // JSON is supposed to be UTF-8, but some suggest service providers send | |
| 421 // JSON files in non-UTF-8 encodings. The actual encoding is usually | |
| 422 // specified in the Content-Type header field. | |
| 423 if (response_headers) { | |
| 424 std::string charset; | |
| 425 if (response_headers->GetCharset(&charset)) { | |
| 426 base::string16 data_16; | |
| 427 // TODO(jungshik): Switch to CodePageToUTF8 after it's added. | |
| 428 if (base::CodepageToUTF16(json_data, charset.c_str(), | |
| 429 base::OnStringConversionError::FAIL, | |
| 430 &data_16)) | |
| 431 json_data = base::UTF16ToUTF8(data_16); | |
| 432 } | |
| 433 } | |
| 434 | |
| 435 scoped_ptr<base::Value> data(DeserializeJsonData(json_data)); | |
| 436 if (data && StoreSuggestionResponse(json_data, *data.get())) | 394 if (data && StoreSuggestionResponse(json_data, *data.get())) |
| 437 return; | 395 return; |
| 438 | 396 |
| 439 results_updated = data.get() && ParseSuggestResults( | 397 results_updated = data.get() && ParseSuggestResults( |
| 440 *data.get(), is_keyword, GetResultsToFill(is_keyword)); | 398 *data.get(), is_keyword, GetResultsToFill(is_keyword)); |
| 441 } | 399 } |
| 442 | 400 |
| 443 UpdateMatches(); | 401 UpdateMatches(); |
| 444 if (done_ || results_updated) | 402 if (done_ || results_updated) |
| 445 listener_->OnProviderUpdate(results_updated); | 403 listener_->OnProviderUpdate(results_updated); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 i.first->second.RecordAdditionalInfo(kSuggestMetadataKey, metadata); | 477 i.first->second.RecordAdditionalInfo(kSuggestMetadataKey, metadata); |
| 520 } | 478 } |
| 521 } | 479 } |
| 522 } | 480 } |
| 523 } | 481 } |
| 524 | 482 |
| 525 bool BaseSearchProvider::ParseSuggestResults( | 483 bool BaseSearchProvider::ParseSuggestResults( |
| 526 const base::Value& root_val, | 484 const base::Value& root_val, |
| 527 bool is_keyword_result, | 485 bool is_keyword_result, |
| 528 SearchSuggestionParser::Results* results) { | 486 SearchSuggestionParser::Results* results) { |
| 487 if (!SearchSuggestionParser::ParseSuggestResults( |
| 488 root_val, GetInput(is_keyword_result), |
| 489 ChromeAutocompleteSchemeClassifier(profile_), |
| 490 GetDefaultResultRelevance(), |
| 491 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), |
| 492 is_keyword_result, results)) |
| 493 return false; |
| 494 |
| 529 BitmapFetcherService* image_service = | 495 BitmapFetcherService* image_service = |
| 530 BitmapFetcherServiceFactory::GetForBrowserContext(profile_); | 496 BitmapFetcherServiceFactory::GetForBrowserContext(profile_); |
| 531 DCHECK(image_service); | 497 DCHECK(image_service); |
| 532 | 498 for (std::vector<GURL>::const_iterator it = |
| 533 bool relevances_from_server = false; | 499 results->answers_image_urls.begin(); |
| 534 if (!SearchSuggestionParser::ParseSuggestResults( | 500 it != results->answers_image_urls.end(); ++it) |
| 535 root_val, GetInput(is_keyword_result), | 501 image_service->Prefetch(*it); |
| 536 ChromeAutocompleteSchemeClassifier(profile_), | |
| 537 base::Bind(&BitmapFetcherService::Prefetch, | |
| 538 base::Unretained(image_service)), | |
| 539 GetDefaultResultRelevance(), | |
| 540 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages), | |
| 541 is_keyword_result, &relevances_from_server, results)) | |
| 542 return false; | |
| 543 | 502 |
| 544 field_trial_triggered_ |= results->field_trial_triggered; | 503 field_trial_triggered_ |= results->field_trial_triggered; |
| 545 field_trial_triggered_in_session_ |= results->field_trial_triggered; | 504 field_trial_triggered_in_session_ |= results->field_trial_triggered; |
| 546 SortResults(is_keyword_result, relevances_from_server, results); | 505 SortResults(is_keyword_result, results); |
| 547 return true; | 506 return true; |
| 548 } | 507 } |
| 549 | 508 |
| 550 void BaseSearchProvider::SortResults(bool is_keyword, | 509 void BaseSearchProvider::SortResults(bool is_keyword, |
| 551 bool relevances_from_server, | |
| 552 SearchSuggestionParser::Results* results) { | 510 SearchSuggestionParser::Results* results) { |
| 553 } | 511 } |
| 554 | 512 |
| 555 bool BaseSearchProvider::StoreSuggestionResponse( | 513 bool BaseSearchProvider::StoreSuggestionResponse( |
| 556 const std::string& json_data, | 514 const std::string& json_data, |
| 557 const base::Value& parsed_data) { | 515 const base::Value& parsed_data) { |
| 558 return false; | 516 return false; |
| 559 } | 517 } |
| 560 | 518 |
| 561 void BaseSearchProvider::ModifyProviderInfo( | 519 void BaseSearchProvider::ModifyProviderInfo( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 578 } | 536 } |
| 579 | 537 |
| 580 void BaseSearchProvider::OnDeletionComplete( | 538 void BaseSearchProvider::OnDeletionComplete( |
| 581 bool success, SuggestionDeletionHandler* handler) { | 539 bool success, SuggestionDeletionHandler* handler) { |
| 582 RecordDeletionResult(success); | 540 RecordDeletionResult(success); |
| 583 SuggestionDeletionHandlers::iterator it = std::find( | 541 SuggestionDeletionHandlers::iterator it = std::find( |
| 584 deletion_handlers_.begin(), deletion_handlers_.end(), handler); | 542 deletion_handlers_.begin(), deletion_handlers_.end(), handler); |
| 585 DCHECK(it != deletion_handlers_.end()); | 543 DCHECK(it != deletion_handlers_.end()); |
| 586 deletion_handlers_.erase(it); | 544 deletion_handlers_.erase(it); |
| 587 } | 545 } |
| OLD | NEW |