Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/android/contextualsearch/contextual_search_delegate.h" | 5 #include "chrome/browser/android/contextualsearch/contextual_search_delegate.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/json/json_string_value_serializer.h" | 11 #include "base/json/json_string_value_serializer.h" |
| 12 #include "base/json/string_escape.h" | |
| 12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | |
| 14 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 15 #include "chrome/browser/android/contextualsearch/contextual_search_field_trial. h" | 17 #include "chrome/browser/android/contextualsearch/contextual_search_field_trial. h" |
| 16 #include "chrome/browser/android/contextualsearch/resolved_search_term.h" | 18 #include "chrome/browser/android/contextualsearch/resolved_search_term.h" |
| 17 #include "chrome/browser/android/proto/client_discourse_context.pb.h" | 19 #include "chrome/browser/android/proto/client_discourse_context.pb.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/browser/profiles/profile_manager.h" | 21 #include "chrome/browser/profiles/profile_manager.h" |
| 20 #include "chrome/browser/sync/profile_sync_service_factory.h" | 22 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 21 #include "chrome/browser/translate/translate_service.h" | 23 #include "chrome/browser/translate/translate_service.h" |
| 22 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| 23 #include "components/browser_sync/profile_sync_service.h" | 25 #include "components/browser_sync/profile_sync_service.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 48 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; | 50 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; |
| 49 const int kContextualSearchRequestVersion = 2; | 51 const int kContextualSearchRequestVersion = 2; |
| 50 const int kContextualSearchMaxSelection = 100; | 52 const int kContextualSearchMaxSelection = 100; |
| 51 const char kXssiEscape[] = ")]}'\n"; | 53 const char kXssiEscape[] = ")]}'\n"; |
| 52 const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: "; | 54 const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: "; |
| 53 const char kDoPreventPreloadValue[] = "1"; | 55 const char kDoPreventPreloadValue[] = "1"; |
| 54 | 56 |
| 55 // The number of characters that should be shown after the selected expression. | 57 // The number of characters that should be shown after the selected expression. |
| 56 const int kSurroundingSizeForUI = 60; | 58 const int kSurroundingSizeForUI = 60; |
| 57 | 59 |
| 60 // Contextual Cards (aka Now on Tap) integration. | |
| 61 const char kContextualSearchContextualCards[] = "contextual_cards"; | |
| 62 const char kContextualSearchCards[] = "cards"; | |
| 63 const char kContextualSearchSingleCard[] = "singleCard"; | |
| 64 const char kContextualSearchSubTitle[] = "subtitle"; | |
| 65 const char kContextualSearchThumbnailUri[] = "thumbnail.uri"; | |
| 58 // The version of the Now on Tap API that we want to invoke. | 66 // The version of the Now on Tap API that we want to invoke. |
| 59 const int kNowOnTapVersion = 1; | 67 const int kNowOnTapVersion = 1; |
| 60 | 68 |
| 61 } // namespace | 69 } // namespace |
| 62 | 70 |
| 63 // URLFetcher ID, only used for tests: we only have one kind of fetcher. | 71 // URLFetcher ID, only used for tests: we only have one kind of fetcher. |
| 64 const int ContextualSearchDelegate::kContextualSearchURLFetcherID = 1; | 72 const int ContextualSearchDelegate::kContextualSearchURLFetcherID = 1; |
| 65 | 73 |
| 66 // Handles tasks for the ContextualSearchManager in a separable, testable way. | 74 // Handles tasks for the ContextualSearchManager in a separable, testable way. |
| 67 ContextualSearchDelegate::ContextualSearchDelegate( | 75 ContextualSearchDelegate::ContextualSearchDelegate( |
| 68 net::URLRequestContextGetter* url_request_context, | 76 net::URLRequestContextGetter* url_request_context, |
| 69 TemplateURLService* template_url_service, | 77 TemplateURLService* template_url_service, |
| 70 const ContextualSearchDelegate::SearchTermResolutionCallback& | 78 const ContextualSearchDelegate::SearchTermResolutionCallback& |
| 71 search_term_callback, | 79 search_term_callback, |
| 72 const ContextualSearchDelegate::SurroundingTextCallback& | 80 const ContextualSearchDelegate::SurroundingTextCallback& |
| 73 surrounding_callback, | 81 surrounding_callback, |
| 74 const ContextualSearchDelegate::IcingCallback& icing_callback) | 82 const ContextualSearchDelegate::IcingCallback& icing_callback, |
| 83 std::unique_ptr<ContextualSearchFieldTrial> field_trial) | |
| 75 : url_request_context_(url_request_context), | 84 : url_request_context_(url_request_context), |
| 76 template_url_service_(template_url_service), | 85 template_url_service_(template_url_service), |
| 77 search_term_callback_(search_term_callback), | 86 search_term_callback_(search_term_callback), |
| 78 surrounding_callback_(surrounding_callback), | 87 surrounding_callback_(surrounding_callback), |
| 79 icing_callback_(icing_callback) { | 88 icing_callback_(icing_callback), |
| 80 field_trial_.reset(new ContextualSearchFieldTrial()); | 89 field_trial_(std::move(field_trial)) {} |
| 81 } | |
| 82 | 90 |
| 83 ContextualSearchDelegate::~ContextualSearchDelegate() { | 91 ContextualSearchDelegate::~ContextualSearchDelegate() { |
| 84 } | 92 } |
| 85 | 93 |
| 86 void ContextualSearchDelegate::StartSearchTermResolutionRequest( | 94 void ContextualSearchDelegate::StartSearchTermResolutionRequest( |
| 87 const std::string& selection, | 95 const std::string& selection, |
| 88 bool use_resolved_search_term, | 96 bool use_resolved_search_term, |
| 89 content::WebContents* web_contents, | 97 content::WebContents* web_contents, |
| 90 bool may_send_base_page_url) { | 98 bool may_send_base_page_url) { |
| 91 GatherSurroundingTextWithCallback( | 99 GatherSurroundingTextWithCallback( |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 std::string* thumbnail_url, | 458 std::string* thumbnail_url, |
| 451 std::string* caption) { | 459 std::string* caption) { |
| 452 bool contains_xssi_escape = | 460 bool contains_xssi_escape = |
| 453 base::StartsWith(response, kXssiEscape, base::CompareCase::SENSITIVE); | 461 base::StartsWith(response, kXssiEscape, base::CompareCase::SENSITIVE); |
| 454 const std::string& proper_json = | 462 const std::string& proper_json = |
| 455 contains_xssi_escape ? response.substr(sizeof(kXssiEscape) - 1) | 463 contains_xssi_escape ? response.substr(sizeof(kXssiEscape) - 1) |
| 456 : response; | 464 : response; |
| 457 JSONStringValueDeserializer deserializer(proper_json); | 465 JSONStringValueDeserializer deserializer(proper_json); |
| 458 std::unique_ptr<base::Value> root = | 466 std::unique_ptr<base::Value> root = |
| 459 deserializer.Deserialize(nullptr, nullptr); | 467 deserializer.Deserialize(nullptr, nullptr); |
| 460 std::unique_ptr<base::DictionaryValue> dict = | 468 const std::unique_ptr<base::DictionaryValue> dict = |
| 461 base::DictionaryValue::From(std::move(root)); | 469 base::DictionaryValue::From(std::move(root)); |
| 462 if (!dict) | 470 if (!dict) |
| 463 return; | 471 return; |
| 464 | 472 |
| 465 dict->GetString(kContextualSearchPreventPreload, prevent_preload); | 473 dict->GetString(kContextualSearchPreventPreload, prevent_preload); |
| 466 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); | 474 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); |
| 467 dict->GetString(kContextualSearchResponseLanguageParam, lang); | 475 dict->GetString(kContextualSearchResponseLanguageParam, lang); |
| 468 | 476 |
| 469 // For the display_text, if not present fall back to the "search_term". | 477 // For the display_text, if not present fall back to the "search_term". |
| 470 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, | 478 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 489 *alternate_term = selected_text; | 497 *alternate_term = selected_text; |
| 490 } else { | 498 } else { |
| 491 std::string resolved_term; | 499 std::string resolved_term; |
| 492 dict->GetString(kContextualSearchResponseResolvedTermParam, &resolved_term); | 500 dict->GetString(kContextualSearchResponseResolvedTermParam, &resolved_term); |
| 493 if (resolved_term != *search_term) { | 501 if (resolved_term != *search_term) { |
| 494 *alternate_term = resolved_term; | 502 *alternate_term = resolved_term; |
| 495 } | 503 } |
| 496 } | 504 } |
| 497 | 505 |
| 498 if (field_trial_->IsNowOnTapBarIntegrationEnabled()) { | 506 if (field_trial_->IsNowOnTapBarIntegrationEnabled()) { |
| 499 // TODO(donnd): extract thumbnail_url and caption. | 507 DecodeNowOnTapResponse(*dict.get(), caption, thumbnail_url); |
|
Theresa
2016/09/20 19:51:39
nit: I think it makes sense to change "caption" to
Donn Denman
2016/09/20 21:16:36
Mostly done.
The ContextualSearchContext knows of
| |
| 500 } | 508 } |
| 501 } | 509 } |
| 502 | 510 |
| 503 // Extract the Start/End of the mentions in the surrounding text | 511 // Extract the Start/End of the mentions in the surrounding text |
| 504 // for selection-expansion. | 512 // for selection-expansion. |
| 505 void ContextualSearchDelegate::ExtractMentionsStartEnd( | 513 void ContextualSearchDelegate::ExtractMentionsStartEnd( |
| 506 const base::ListValue& mentions_list, | 514 const base::ListValue& mentions_list, |
| 507 int* startResult, | 515 int* startResult, |
| 508 int* endResult) { | 516 int* endResult) { |
| 509 int int_value; | 517 int int_value; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 533 end_offset -= trim; | 541 end_offset -= trim; |
| 534 } | 542 } |
| 535 if (result_text.length() > end_offset + padding_each_side_pinned) { | 543 if (result_text.length() > end_offset + padding_each_side_pinned) { |
| 536 // Trim the end. | 544 // Trim the end. |
| 537 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); | 545 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); |
| 538 } | 546 } |
| 539 *start = start_offset; | 547 *start = start_offset; |
| 540 *end = end_offset; | 548 *end = end_offset; |
| 541 return result_text; | 549 return result_text; |
| 542 } | 550 } |
| 551 | |
| 552 void ContextualSearchDelegate::DecodeNowOnTapResponse( | |
| 553 const base::DictionaryValue& dict, | |
| 554 std::string* subtitle, | |
| 555 std::string* thumbnail) { | |
| 556 const base::DictionaryValue* contextual_cards_dict = nullptr; | |
| 557 if (!dict.GetDictionary(kContextualSearchContextualCards, | |
| 558 &contextual_cards_dict)) | |
| 559 return; | |
| 560 | |
| 561 DCHECK(contextual_cards_dict); | |
|
Theresa
2016/09/20 19:51:40
I don't think this DCHECK is necessary since we re
Donn Denman
2016/09/20 21:16:37
In that case we should remove all of these DCHECKS
| |
| 562 const base::ListValue* card_list = nullptr; | |
| 563 if (!contextual_cards_dict->GetList(kContextualSearchCards, &card_list)) | |
| 564 return; | |
| 565 | |
| 566 DCHECK(card_list); | |
| 567 for (const auto& card : *card_list) { | |
| 568 const base::DictionaryValue* card_dict = nullptr; | |
| 569 if (!card->GetAsDictionary(&card_dict)) | |
| 570 continue; | |
| 571 | |
| 572 DCHECK(card_dict); | |
| 573 const base::DictionaryValue* single_card = nullptr; | |
| 574 if (!card_dict->GetDictionary(kContextualSearchSingleCard, &single_card)) | |
| 575 continue; | |
| 576 | |
| 577 DCHECK(single_card); | |
| 578 single_card->GetString(kContextualSearchSubTitle, subtitle); | |
| 579 single_card->GetString(kContextualSearchThumbnailUri, thumbnail); | |
| 580 return; | |
| 581 } | |
| 582 } | |
| OLD | NEW |