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" |
(...skipping 23 matching lines...) Expand all Loading... | |
34 const char kContextualSearchSurroundingSizeParamName[] = "surrounding_size"; | 34 const char kContextualSearchSurroundingSizeParamName[] = "surrounding_size"; |
35 const char kContextualSearchIcingSurroundingSizeParamName[] = | 35 const char kContextualSearchIcingSurroundingSizeParamName[] = |
36 "icing_surrounding_size"; | 36 "icing_surrounding_size"; |
37 const char kContextualSearchResolverURLParamName[] = "resolver_url"; | 37 const char kContextualSearchResolverURLParamName[] = "resolver_url"; |
38 const char kContextualSearchDoNotSendURLParamName[] = "do_not_send_url"; | 38 const char kContextualSearchDoNotSendURLParamName[] = "do_not_send_url"; |
39 const char kContextualSearchResponseDisplayTextParam[] = "display_text"; | 39 const char kContextualSearchResponseDisplayTextParam[] = "display_text"; |
40 const char kContextualSearchResponseSelectedTextParam[] = "selected_text"; | 40 const char kContextualSearchResponseSelectedTextParam[] = "selected_text"; |
41 const char kContextualSearchResponseSearchTermParam[] = "search_term"; | 41 const char kContextualSearchResponseSearchTermParam[] = "search_term"; |
42 const char kContextualSearchResponseResolvedTermParam[] = "resolved_term"; | 42 const char kContextualSearchResponseResolvedTermParam[] = "resolved_term"; |
43 const char kContextualSearchPreventPreload[] = "prevent_preload"; | 43 const char kContextualSearchPreventPreload[] = "prevent_preload"; |
44 const char kContextualSearchMentions[] = "mentions"; | |
44 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; | 45 const char kContextualSearchServerEndpoint[] = "_/contextualsearch?"; |
45 const int kContextualSearchRequestVersion = 2; | 46 const int kContextualSearchRequestVersion = 2; |
46 const char kContextualSearchResolverUrl[] = | 47 const char kContextualSearchResolverUrl[] = |
47 "contextual-search-resolver-url"; | 48 "contextual-search-resolver-url"; |
48 // The default size of the content surrounding the selection to gather, allowing | 49 // The default size of the content surrounding the selection to gather, allowing |
49 // room for other parameters. | 50 // room for other parameters. |
50 const int kContextualSearchDefaultContentSize = 1536; | 51 const int kContextualSearchDefaultContentSize = 1536; |
51 const int kContextualSearchDefaultIcingSurroundingSize = 400; | 52 const int kContextualSearchDefaultIcingSurroundingSize = 400; |
53 const int kContextualSearchMaxSelection = 100; | |
52 // The maximum length of a URL to build. | 54 // The maximum length of a URL to build. |
53 const int kMaxURLSize = 2048; | 55 const int kMaxURLSize = 2048; |
54 const char kXssiEscape[] = ")]}'\n"; | 56 const char kXssiEscape[] = ")]}'\n"; |
55 const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: "; | 57 const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: "; |
56 const char kDoPreventPreloadValue[] = "1"; | 58 const char kDoPreventPreloadValue[] = "1"; |
57 | 59 |
58 // The number of characters that should be shown on each side of the selected | 60 // The number of characters that should be shown on each side of the selected |
59 // expression. | 61 // expression. |
60 const int kSurroundingSizeForUI = 30; | 62 const int kSurroundingSizeForUI = 30; |
61 | 63 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 } | 137 } |
136 | 138 |
137 void ContextualSearchDelegate::OnURLFetchComplete( | 139 void ContextualSearchDelegate::OnURLFetchComplete( |
138 const net::URLFetcher* source) { | 140 const net::URLFetcher* source) { |
139 DCHECK(source == search_term_fetcher_.get()); | 141 DCHECK(source == search_term_fetcher_.get()); |
140 int response_code = source->GetResponseCode(); | 142 int response_code = source->GetResponseCode(); |
141 std::string search_term; | 143 std::string search_term; |
142 std::string display_text; | 144 std::string display_text; |
143 std::string alternate_term; | 145 std::string alternate_term; |
144 std::string prevent_preload; | 146 std::string prevent_preload; |
147 size_t mention_start = 0; | |
148 size_t mention_end = 0; | |
149 int start_adjust = 0; | |
150 int end_adjust = 0; | |
145 | 151 |
146 if (source->GetStatus().is_success() && response_code == 200) { | 152 if (source->GetStatus().is_success() && response_code == 200) { |
147 std::string response; | 153 std::string response; |
148 bool has_string_response = source->GetResponseAsString(&response); | 154 bool has_string_response = source->GetResponseAsString(&response); |
149 DCHECK(has_string_response); | 155 DCHECK(has_string_response); |
150 if (has_string_response) { | 156 if (has_string_response) { |
151 DecodeSearchTermsFromJsonResponse(response, &search_term, &display_text, | 157 DecodeSearchTermsFromJsonResponse(response, &search_term, &display_text, |
152 &alternate_term, &prevent_preload); | 158 &alternate_term, &prevent_preload, |
159 &mention_start, &mention_end); | |
160 if (mention_start != 0 || mention_end != 0) { | |
161 // Sanity check that our selection is non-zero and it is less than | |
162 // 100 characters as that would make contextual search bar hide. | |
163 if (mention_start >= mention_end | |
164 || (mention_end - mention_start) > kContextualSearchMaxSelection) { | |
165 start_adjust = 0; | |
166 end_adjust = 0; | |
167 } else { | |
168 start_adjust = mention_start - context_->start_offset; | |
169 end_adjust = mention_end - context_->end_offset; | |
palmer
2015/07/09 21:15:16
Do you also need to check if |start_adjust| and |e
aurimas (slooooooooow)
2015/07/10 01:46:49
Great catch. We discussed it and we decided that t
| |
170 } | |
171 } | |
153 } | 172 } |
154 } | 173 } |
155 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID; | 174 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID; |
156 search_term_callback_.Run( | 175 search_term_callback_.Run( |
157 is_invalid, response_code, search_term, display_text, alternate_term, | 176 is_invalid, response_code, search_term, display_text, alternate_term, |
158 prevent_preload == kDoPreventPreloadValue); | 177 prevent_preload == kDoPreventPreloadValue, start_adjust, end_adjust); |
159 | 178 |
160 // The ContextualSearchContext is consumed once the request has completed. | 179 // The ContextualSearchContext is consumed once the request has completed. |
161 context_.reset(); | 180 context_.reset(); |
162 } | 181 } |
163 | 182 |
164 // TODO(jeremycho): Remove selected_text and base_page_url CGI parameters. | 183 // TODO(jeremycho): Remove selected_text and base_page_url CGI parameters. |
165 GURL ContextualSearchDelegate::BuildRequestUrl() { | 184 GURL ContextualSearchDelegate::BuildRequestUrl() { |
166 // TODO(jeremycho): Confirm this is the right way to handle TemplateURL fails. | 185 // TODO(jeremycho): Confirm this is the right way to handle TemplateURL fails. |
167 if (!template_url_service_ || | 186 if (!template_url_service_ || |
168 !template_url_service_->GetDefaultSearchProvider()) { | 187 !template_url_service_->GetDefaultSearchProvider()) { |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 return true; | 411 return true; |
393 } | 412 } |
394 | 413 |
395 // Decodes the given response from the search term resolution request and sets | 414 // Decodes the given response from the search term resolution request and sets |
396 // the value of the given parameters. | 415 // the value of the given parameters. |
397 void ContextualSearchDelegate::DecodeSearchTermsFromJsonResponse( | 416 void ContextualSearchDelegate::DecodeSearchTermsFromJsonResponse( |
398 const std::string& response, | 417 const std::string& response, |
399 std::string* search_term, | 418 std::string* search_term, |
400 std::string* display_text, | 419 std::string* display_text, |
401 std::string* alternate_term, | 420 std::string* alternate_term, |
402 std::string* prevent_preload) { | 421 std::string* prevent_preload, |
422 size_t* mention_start, | |
423 size_t* mention_end) { | |
403 bool contains_xssi_escape = response.find(kXssiEscape) == 0; | 424 bool contains_xssi_escape = response.find(kXssiEscape) == 0; |
404 const std::string& proper_json = | 425 const std::string& proper_json = |
405 contains_xssi_escape ? response.substr(strlen(kXssiEscape)) : response; | 426 contains_xssi_escape ? response.substr(strlen(kXssiEscape)) : response; |
406 JSONStringValueDeserializer deserializer(proper_json); | 427 JSONStringValueDeserializer deserializer(proper_json); |
407 scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, NULL)); | 428 scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, NULL)); |
408 | 429 |
409 if (root.get() != NULL && root->IsType(base::Value::TYPE_DICTIONARY)) { | 430 if (root.get() != NULL && root->IsType(base::Value::TYPE_DICTIONARY)) { |
410 base::DictionaryValue* dict = | 431 base::DictionaryValue* dict = |
411 static_cast<base::DictionaryValue*>(root.get()); | 432 static_cast<base::DictionaryValue*>(root.get()); |
412 dict->GetString(kContextualSearchPreventPreload, prevent_preload); | 433 dict->GetString(kContextualSearchPreventPreload, prevent_preload); |
413 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); | 434 dict->GetString(kContextualSearchResponseSearchTermParam, search_term); |
414 // For the display_text, if not present fall back to the "search_term". | 435 // For the display_text, if not present fall back to the "search_term". |
415 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, | 436 if (!dict->GetString(kContextualSearchResponseDisplayTextParam, |
416 display_text)) { | 437 display_text)) { |
417 *display_text = *search_term; | 438 *display_text = *search_term; |
418 } | 439 } |
440 // Extract mentions for selection expansion. | |
441 base::ListValue* mentions_list; | |
442 dict->GetList(kContextualSearchMentions, &mentions_list); | |
443 if (mentions_list != NULL && mentions_list->GetSize() >= 2) | |
444 ExtractMentionsStartEnd(*mentions_list, mention_start, mention_end); | |
419 // If either the selected text or the resolved term is not the search term, | 445 // If either the selected text or the resolved term is not the search term, |
420 // use it as the alternate term. | 446 // use it as the alternate term. |
421 std::string selected_text; | 447 std::string selected_text; |
422 dict->GetString(kContextualSearchResponseSelectedTextParam, &selected_text); | 448 dict->GetString(kContextualSearchResponseSelectedTextParam, &selected_text); |
423 if (selected_text != *search_term) { | 449 if (selected_text != *search_term) { |
424 *alternate_term = selected_text; | 450 *alternate_term = selected_text; |
425 } else { | 451 } else { |
426 std::string resolved_term; | 452 std::string resolved_term; |
427 dict->GetString(kContextualSearchResponseResolvedTermParam, | 453 dict->GetString(kContextualSearchResponseResolvedTermParam, |
428 &resolved_term); | 454 &resolved_term); |
429 if (resolved_term != *search_term) { | 455 if (resolved_term != *search_term) { |
430 *alternate_term = resolved_term; | 456 *alternate_term = resolved_term; |
431 } | 457 } |
432 } | 458 } |
433 } | 459 } |
434 } | 460 } |
435 | 461 |
436 // Returns the size of the surroundings to be sent to the server for search term | 462 // Returns the size of the surroundings to be sent to the server for search term |
437 // resolution. | 463 // resolution. |
438 int ContextualSearchDelegate::GetSearchTermSurroundingSize() { | 464 int ContextualSearchDelegate::GetSearchTermSurroundingSize() { |
439 const std::string param_value = variations::GetVariationParamValue( | 465 const std::string param_value = variations::GetVariationParamValue( |
440 kContextualSearchFieldTrialName, | 466 kContextualSearchFieldTrialName, |
441 kContextualSearchSurroundingSizeParamName); | 467 kContextualSearchSurroundingSizeParamName); |
442 int param_length; | 468 int param_length; |
443 if (!param_value.empty() && base::StringToInt(param_value, ¶m_length)) | 469 if (!param_value.empty() && base::StringToInt(param_value, ¶m_length)) |
444 return param_length; | 470 return param_length; |
445 return kContextualSearchDefaultContentSize; | 471 return kContextualSearchDefaultContentSize; |
446 } | 472 } |
447 | 473 |
474 // Extract the Start/End of the mentions in the surrounding text | |
475 // for selection-expansion. | |
476 void ContextualSearchDelegate::ExtractMentionsStartEnd( | |
477 const base::ListValue& mentions_list, | |
478 size_t* startResult, | |
479 size_t* endResult) { | |
480 int int_value; | |
481 if (mentions_list.GetInteger(0, &int_value)) | |
482 *startResult = std::max(0, int_value); | |
483 if (mentions_list.GetInteger(1, &int_value)) | |
484 *endResult = std::max(0, int_value); | |
485 } | |
486 | |
448 // Returns the size of the surroundings to be sent to Icing. | 487 // Returns the size of the surroundings to be sent to Icing. |
449 int ContextualSearchDelegate::GetIcingSurroundingSize() { | 488 int ContextualSearchDelegate::GetIcingSurroundingSize() { |
450 std::string param_string = variations::GetVariationParamValue( | 489 std::string param_string = variations::GetVariationParamValue( |
451 kContextualSearchFieldTrialName, | 490 kContextualSearchFieldTrialName, |
452 kContextualSearchIcingSurroundingSizeParamName); | 491 kContextualSearchIcingSurroundingSizeParamName); |
453 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 492 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
454 kContextualSearchIcingSurroundingSizeParamName)) { | 493 kContextualSearchIcingSurroundingSizeParamName)) { |
455 param_string = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 494 param_string = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
456 kContextualSearchIcingSurroundingSizeParamName); | 495 kContextualSearchIcingSurroundingSizeParamName); |
457 } | 496 } |
(...skipping 23 matching lines...) Expand all Loading... | |
481 end_offset -= trim; | 520 end_offset -= trim; |
482 } | 521 } |
483 if (result_text.length() > end_offset + padding_each_side_pinned) { | 522 if (result_text.length() > end_offset + padding_each_side_pinned) { |
484 // Trim the end. | 523 // Trim the end. |
485 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); | 524 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); |
486 } | 525 } |
487 *start = start_offset; | 526 *start = start_offset; |
488 *end = end_offset; | 527 *end = end_offset; |
489 return result_text; | 528 return result_text; |
490 } | 529 } |
OLD | NEW |