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/prefs/pref_service.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" |
14 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "chrome/browser/android/contextualsearch/resolved_search_term.h" |
15 #include "chrome/browser/android/proto/client_discourse_context.pb.h" | 17 #include "chrome/browser/android/proto/client_discourse_context.pb.h" |
16 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/profiles/profile_manager.h" | 19 #include "chrome/browser/profiles/profile_manager.h" |
18 #include "chrome/browser/sync/profile_sync_service.h" | 20 #include "chrome/browser/sync/profile_sync_service.h" |
19 #include "chrome/browser/sync/profile_sync_service_factory.h" | 21 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 22 #include "chrome/browser/translate/translate_service.h" |
| 23 #include "chrome/common/pref_names.h" |
20 #include "components/search_engines/template_url_service.h" | 24 #include "components/search_engines/template_url_service.h" |
21 #include "components/variations/net/variations_http_header_provider.h" | 25 #include "components/variations/net/variations_http_header_provider.h" |
22 #include "components/variations/variations_associated_data.h" | 26 #include "components/variations/variations_associated_data.h" |
23 #include "content/public/browser/android/content_view_core.h" | 27 #include "content/public/browser/android/content_view_core.h" |
24 #include "content/public/browser/web_contents.h" | 28 #include "content/public/browser/web_contents.h" |
25 #include "net/base/escape.h" | 29 #include "net/base/escape.h" |
26 #include "net/url_request/url_fetcher.h" | 30 #include "net/url_request/url_fetcher.h" |
27 #include "url/gurl.h" | 31 #include "url/gurl.h" |
28 | 32 |
29 using content::ContentViewCore; | 33 using content::ContentViewCore; |
30 | 34 |
31 namespace { | 35 namespace { |
32 | 36 |
33 const char kContextualSearchFieldTrialName[] = "ContextualSearch"; | 37 const char kContextualSearchFieldTrialName[] = "ContextualSearch"; |
34 const char kContextualSearchSurroundingSizeParamName[] = "surrounding_size"; | 38 const char kContextualSearchSurroundingSizeParamName[] = "surrounding_size"; |
35 const char kContextualSearchIcingSurroundingSizeParamName[] = | 39 const char kContextualSearchIcingSurroundingSizeParamName[] = |
36 "icing_surrounding_size"; | 40 "icing_surrounding_size"; |
37 const char kContextualSearchResolverURLParamName[] = "resolver_url"; | 41 const char kContextualSearchResolverURLParamName[] = "resolver_url"; |
38 const char kContextualSearchDoNotSendURLParamName[] = "do_not_send_url"; | 42 const char kContextualSearchDoNotSendURLParamName[] = "do_not_send_url"; |
39 const char kContextualSearchResponseDisplayTextParam[] = "display_text"; | 43 const char kContextualSearchResponseDisplayTextParam[] = "display_text"; |
40 const char kContextualSearchResponseSelectedTextParam[] = "selected_text"; | 44 const char kContextualSearchResponseSelectedTextParam[] = "selected_text"; |
41 const char kContextualSearchResponseSearchTermParam[] = "search_term"; | 45 const char kContextualSearchResponseSearchTermParam[] = "search_term"; |
| 46 const char kContextualSearchResponseLanguageParam[] = "lang"; |
42 const char kContextualSearchResponseResolvedTermParam[] = "resolved_term"; | 47 const char kContextualSearchResponseResolvedTermParam[] = "resolved_term"; |
43 const char kContextualSearchPreventPreload[] = "prevent_preload"; | 48 const char kContextualSearchPreventPreload[] = "prevent_preload"; |
44 const char kContextualSearchMentions[] = "mentions"; | 49 const char kContextualSearchMentions[] = "mentions"; |
45 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; | 50 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; |
46 const int kContextualSearchRequestVersion = 2; | 51 const int kContextualSearchRequestVersion = 2; |
47 const char kContextualSearchResolverUrl[] = | 52 const char kContextualSearchResolverUrl[] = |
48 "contextual-search-resolver-url"; | 53 "contextual-search-resolver-url"; |
49 // The default size of the content surrounding the selection to gather, allowing | 54 // The default size of the content surrounding the selection to gather, allowing |
50 // room for other parameters. | 55 // room for other parameters. |
51 const int kContextualSearchDefaultContentSize = 1536; | 56 const int kContextualSearchDefaultContentSize = 1536; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 DCHECK(source == search_term_fetcher_.get()); | 145 DCHECK(source == search_term_fetcher_.get()); |
141 int response_code = source->GetResponseCode(); | 146 int response_code = source->GetResponseCode(); |
142 std::string search_term; | 147 std::string search_term; |
143 std::string display_text; | 148 std::string display_text; |
144 std::string alternate_term; | 149 std::string alternate_term; |
145 std::string prevent_preload; | 150 std::string prevent_preload; |
146 int mention_start = 0; | 151 int mention_start = 0; |
147 int mention_end = 0; | 152 int mention_end = 0; |
148 int start_adjust = 0; | 153 int start_adjust = 0; |
149 int end_adjust = 0; | 154 int end_adjust = 0; |
| 155 std::string context_language; |
| 156 std::string target_language; |
150 | 157 |
151 if (source->GetStatus().is_success() && response_code == 200) { | 158 if (source->GetStatus().is_success() && response_code == 200) { |
152 std::string response; | 159 std::string response; |
153 bool has_string_response = source->GetResponseAsString(&response); | 160 bool has_string_response = source->GetResponseAsString(&response); |
154 DCHECK(has_string_response); | 161 DCHECK(has_string_response); |
155 if (has_string_response) { | 162 if (has_string_response) { |
156 DecodeSearchTermsFromJsonResponse(response, &search_term, &display_text, | 163 DecodeSearchTermFromJsonResponse( |
157 &alternate_term, &prevent_preload, | 164 response, &search_term, &display_text, &alternate_term, |
158 &mention_start, &mention_end); | 165 &prevent_preload, &mention_start, &mention_end, &context_language); |
159 if (mention_start != 0 || mention_end != 0) { | 166 if (mention_start != 0 || mention_end != 0) { |
160 // Sanity check that our selection is non-zero and it is less than | 167 // Sanity check that our selection is non-zero and it is less than |
161 // 100 characters as that would make contextual search bar hide. | 168 // 100 characters as that would make contextual search bar hide. |
162 // We also check that there is at least one character overlap between | 169 // We also check that there is at least one character overlap between |
163 // the new and old selection. | 170 // the new and old selection. |
164 if (mention_start >= mention_end | 171 if (mention_start >= mention_end |
165 || (mention_end - mention_start) > kContextualSearchMaxSelection | 172 || (mention_end - mention_start) > kContextualSearchMaxSelection |
166 || mention_end <= context_->start_offset | 173 || mention_end <= context_->start_offset |
167 || mention_start >= context_->end_offset) { | 174 || mention_start >= context_->end_offset) { |
168 start_adjust = 0; | 175 start_adjust = 0; |
169 end_adjust = 0; | 176 end_adjust = 0; |
170 } else { | 177 } else { |
171 start_adjust = mention_start - context_->start_offset; | 178 start_adjust = mention_start - context_->start_offset; |
172 end_adjust = mention_end - context_->end_offset; | 179 end_adjust = mention_end - context_->end_offset; |
173 } | 180 } |
174 } | 181 } |
175 } | 182 } |
176 } | 183 } |
177 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID; | 184 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID; |
178 search_term_callback_.Run( | 185 ResolvedSearchTerm resolved_search_term( |
179 is_invalid, response_code, search_term, display_text, alternate_term, | 186 is_invalid, response_code, search_term, display_text, alternate_term, |
180 prevent_preload == kDoPreventPreloadValue, start_adjust, end_adjust); | 187 prevent_preload == kDoPreventPreloadValue, start_adjust, end_adjust, |
| 188 context_language); |
| 189 search_term_callback_.Run(resolved_search_term); |
181 | 190 |
182 // The ContextualSearchContext is consumed once the request has completed. | 191 // The ContextualSearchContext is consumed once the request has completed. |
183 context_.reset(); | 192 context_.reset(); |
184 } | 193 } |
185 | 194 |
186 // TODO(jeremycho): Remove selected_text and base_page_url CGI parameters. | 195 // TODO(jeremycho): Remove selected_text and base_page_url CGI parameters. |
187 GURL ContextualSearchDelegate::BuildRequestUrl() { | 196 GURL ContextualSearchDelegate::BuildRequestUrl() { |
188 // TODO(jeremycho): Confirm this is the right way to handle TemplateURL fails. | 197 // TODO(jeremycho): Confirm this is the right way to handle TemplateURL fails. |
189 if (!template_url_service_ || | 198 if (!template_url_service_ || |
190 !template_url_service_->GetDefaultSearchProvider()) { | 199 !template_url_service_->GetDefaultSearchProvider()) { |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 if (service == NULL || !service->CanSyncStart() || | 417 if (service == NULL || !service->CanSyncStart() || |
409 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()) | 418 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()) |
410 .Has(syncer::PROXY_TABS) || | 419 .Has(syncer::PROXY_TABS) || |
411 !service->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)) { | 420 !service->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)) { |
412 return false; | 421 return false; |
413 } | 422 } |
414 | 423 |
415 return true; | 424 return true; |
416 } | 425 } |
417 | 426 |
| 427 // Gets the target language from the translate service using the user's profile. |
| 428 std::string ContextualSearchDelegate::GetTargetLanguage() { |
| 429 Profile* profile = ProfileManager::GetActiveUserProfile(); |
| 430 PrefService* pref_service = profile->GetPrefs(); |
| 431 std::string result = TranslateService::GetTargetLanguage(pref_service); |
| 432 DCHECK(!result.empty()); |
| 433 return result; |
| 434 } |
| 435 |
| 436 // Returns the accept languages preference string. |
| 437 std::string ContextualSearchDelegate::GetAcceptLanguages() { |
| 438 Profile* profile = ProfileManager::GetActiveUserProfile(); |
| 439 PrefService* pref_service = profile->GetPrefs(); |
| 440 return pref_service->GetString(prefs::kAcceptLanguages); |
| 441 } |
| 442 |
418 // Decodes the given response from the search term resolution request and sets | 443 // Decodes the given response from the search term resolution request and sets |
419 // the value of the given parameters. | 444 // the value of the given parameters. |
420 void ContextualSearchDelegate::DecodeSearchTermsFromJsonResponse( | 445 void ContextualSearchDelegate::DecodeSearchTermFromJsonResponse( |
421 const std::string& response, | 446 const std::string& response, |
422 std::string* search_term, | 447 std::string* search_term, |
423 std::string* display_text, | 448 std::string* display_text, |
424 std::string* alternate_term, | 449 std::string* alternate_term, |
425 std::string* prevent_preload, | 450 std::string* prevent_preload, |
426 int* mention_start, | 451 int* mention_start, |
427 int* mention_end) { | 452 int* mention_end, |
| 453 std::string* lang) { |
428 bool contains_xssi_escape = response.find(kXssiEscape) == 0; | 454 bool contains_xssi_escape = response.find(kXssiEscape) == 0; |
429 const std::string& proper_json = | 455 const std::string& proper_json = |
430 contains_xssi_escape ? response.substr(strlen(kXssiEscape)) : response; | 456 contains_xssi_escape ? response.substr(strlen(kXssiEscape)) : response; |
431 JSONStringValueDeserializer deserializer(proper_json); | 457 JSONStringValueDeserializer deserializer(proper_json); |
432 scoped_ptr<base::Value> root = deserializer.Deserialize(NULL, NULL); | 458 scoped_ptr<base::Value> root = deserializer.Deserialize(NULL, NULL); |
433 | 459 |
434 if (root.get() != NULL && root->IsType(base::Value::TYPE_DICTIONARY)) { | 460 if (root.get() != NULL && root->IsType(base::Value::TYPE_DICTIONARY)) { |
435 base::DictionaryValue* dict = | 461 base::DictionaryValue* dict = |
436 static_cast<base::DictionaryValue*>(root.get()); | 462 static_cast<base::DictionaryValue*>(root.get()); |
437 dict->GetString(kContextualSearchPreventPreload, prevent_preload); | 463 dict->GetString(kContextualSearchPreventPreload, prevent_preload); |
438 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); | 464 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); |
| 465 dict->GetString(kContextualSearchResponseLanguageParam, lang); |
439 // For the display_text, if not present fall back to the "search_term". | 466 // For the display_text, if not present fall back to the "search_term". |
440 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, | 467 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, |
441 display_text)) { | 468 display_text)) { |
442 *display_text = *search_term; | 469 *display_text = *search_term; |
443 } | 470 } |
444 // Extract mentions for selection expansion. | 471 // Extract mentions for selection expansion. |
445 base::ListValue* mentions_list = NULL; | 472 base::ListValue* mentions_list = NULL; |
446 dict->GetList(kContextualSearchMentions, &mentions_list); | 473 dict->GetList(kContextualSearchMentions, &mentions_list); |
447 if (mentions_list != NULL && mentions_list->GetSize() >= 2) | 474 if (mentions_list != NULL && mentions_list->GetSize() >= 2) |
448 ExtractMentionsStartEnd(*mentions_list, mention_start, mention_end); | 475 ExtractMentionsStartEnd(*mentions_list, mention_start, mention_end); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 end_offset -= trim; | 551 end_offset -= trim; |
525 } | 552 } |
526 if (result_text.length() > end_offset + padding_each_side_pinned) { | 553 if (result_text.length() > end_offset + padding_each_side_pinned) { |
527 // Trim the end. | 554 // Trim the end. |
528 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); | 555 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); |
529 } | 556 } |
530 *start = start_offset; | 557 *start = start_offset; |
531 *end = end_offset; | 558 *end = end_offset; |
532 return result_text; | 559 return result_text; |
533 } | 560 } |
OLD | NEW |