Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: chrome/browser/android/contextualsearch/contextual_search_delegate.cc

Issue 2706333002: [TTS] Add a Java Context linked to existing native (Closed)
Patch Set: Minor change only. Previous patch also rebased. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include <utility> 8 #include <utility>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 template_url_service_(template_url_service), 91 template_url_service_(template_url_service),
92 search_term_callback_(search_term_callback), 92 search_term_callback_(search_term_callback),
93 surrounding_callback_(surrounding_callback), 93 surrounding_callback_(surrounding_callback),
94 icing_callback_(icing_callback) { 94 icing_callback_(icing_callback) {
95 field_trial_.reset(new ContextualSearchFieldTrial()); 95 field_trial_.reset(new ContextualSearchFieldTrial());
96 } 96 }
97 97
98 ContextualSearchDelegate::~ContextualSearchDelegate() { 98 ContextualSearchDelegate::~ContextualSearchDelegate() {
99 } 99 }
100 100
101 void ContextualSearchDelegate::StartSearchTermResolutionRequest( 101 void ContextualSearchDelegate::GatherAndSaveSurroundingText(
102 const std::string& selection, 102 ContextualSearchContext* contextual_search_context,
103 const std::string& home_country, 103 content::WebContents* web_contents) {
104 content::WebContents* web_contents, 104 DCHECK(web_contents);
105 bool may_send_base_page_url) { 105 RenderFrameHost::TextSurroundingSelectionCallback callback =
106 GatherSurroundingTextWithCallback( 106 base::Bind(&ContextualSearchDelegate::OnTextSurroundingSelectionAvailable,
107 selection, home_country, web_contents, may_send_base_page_url, 107 AsWeakPtr());
108 base::Bind(&ContextualSearchDelegate::StartSearchTermRequestFromSelection, 108 context_ = contextual_search_context;
109 AsWeakPtr())); 109 context_->SetBasePageEncoding(web_contents->GetEncoding());
110 int surroundingTextSize = context_->CanResolve()
111 ? field_trial_->GetSurroundingSize()
Theresa 2017/03/09 22:46:37 Not in this CL, but in a follow up one, it seems t
Donn Denman 2017/03/10 01:29:43 Acknowledged.
112 : field_trial_->GetIcingSurroundingSize();
113 RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
114 if (focused_frame) {
115 focused_frame->RequestTextSurroundingSelection(callback,
116 surroundingTextSize);
117 } else {
118 callback.Run(base::string16(), 0, 0);
119 }
110 } 120 }
111 121
112 void ContextualSearchDelegate::GatherAndSaveSurroundingText( 122 void ContextualSearchDelegate::StartSearchTermResolutionRequest(
113 const std::string& selection, 123 ContextualSearchContext* contextual_search_context,
114 const std::string& home_country, 124 content::WebContents* web_contents) {
115 content::WebContents* web_contents, 125 DCHECK(web_contents);
116 bool may_send_base_page_url) { 126 DCHECK(context_ == contextual_search_context);
117 GatherSurroundingTextWithCallback( 127 DCHECK(context_->CanResolve());
118 selection, home_country, web_contents, may_send_base_page_url, 128
119 base::Bind(&ContextualSearchDelegate::SaveSurroundingText, AsWeakPtr())); 129 // Immediately cancel any request that's in flight, since we're building a new
120 // TODO(donnd): clear the context here, since we're done with it (but risky). 130 // context (and the response disposes of any existing context).
131 search_term_fetcher_.reset();
132
133 // Decide if the URL should be sent with the context.
134 GURL page_url(web_contents->GetURL());
135 if (context_->CanSendBasePageUrl() &&
136 CanSendPageURL(page_url, ProfileManager::GetActiveUserProfile(),
137 template_url_service_)) {
138 context_->SetBasePageUrl(page_url);
139 }
140 ResolveSearchTermFromContext();
121 } 141 }
122 142
123 void ContextualSearchDelegate::ContinueSearchTermResolutionRequest() { 143 void ContextualSearchDelegate::ResolveSearchTermFromContext() {
124 DCHECK(context_.get()); 144 DCHECK(context_);
125 if (!context_.get()) 145 if (!context_)
126 return; 146 return;
127 GURL request_url(BuildRequestUrl(context_->home_country)); 147 GURL request_url(BuildRequestUrl(context_->GetHomeCountry()));
128 DCHECK(request_url.is_valid()); 148 DCHECK(request_url.is_valid());
129 149
130 // Reset will delete any previous fetcher, and we won't get any callback. 150 // Reset will delete any previous fetcher, and we won't get any callback.
131 search_term_fetcher_.reset( 151 search_term_fetcher_.reset(
132 net::URLFetcher::Create(kContextualSearchURLFetcherID, request_url, 152 net::URLFetcher::Create(kContextualSearchURLFetcherID, request_url,
133 net::URLFetcher::GET, this).release()); 153 net::URLFetcher::GET, this).release());
134 search_term_fetcher_->SetRequestContext(url_request_context_); 154 search_term_fetcher_->SetRequestContext(url_request_context_);
135 155
136 // Add Chrome experiment state to the request headers. 156 // Add Chrome experiment state to the request headers.
137 net::HttpRequestHeaders headers; 157 net::HttpRequestHeaders headers;
(...skipping 21 matching lines...) Expand all
159 if (source->GetStatus().is_success() && response_code == net::HTTP_OK) { 179 if (source->GetStatus().is_success() && response_code == net::HTTP_OK) {
160 std::string response; 180 std::string response;
161 bool has_string_response = source->GetResponseAsString(&response); 181 bool has_string_response = source->GetResponseAsString(&response);
162 DCHECK(has_string_response); 182 DCHECK(has_string_response);
163 if (has_string_response) { 183 if (has_string_response) {
164 resolved_search_term = 184 resolved_search_term =
165 GetResolvedSearchTermFromJson(response_code, response); 185 GetResolvedSearchTermFromJson(response_code, response);
166 } 186 }
167 } 187 }
168 search_term_callback_.Run(*resolved_search_term); 188 search_term_callback_.Run(*resolved_search_term);
169
170 // The ContextualSearchContext is consumed once the request has completed.
171 context_.reset();
172 } 189 }
173 190
174 std::unique_ptr<ResolvedSearchTerm> 191 std::unique_ptr<ResolvedSearchTerm>
175 ContextualSearchDelegate::GetResolvedSearchTermFromJson( 192 ContextualSearchDelegate::GetResolvedSearchTermFromJson(
176 int response_code, 193 int response_code,
177 const std::string& json_string) { 194 const std::string& json_string) {
178 std::string search_term; 195 std::string search_term;
179 std::string display_text; 196 std::string display_text;
180 std::string alternate_term; 197 std::string alternate_term;
181 std::string mid; 198 std::string mid;
(...skipping 12 matching lines...) Expand all
194 json_string, &search_term, &display_text, &alternate_term, &mid, 211 json_string, &search_term, &display_text, &alternate_term, &mid,
195 &prevent_preload, &mention_start, &mention_end, &context_language, 212 &prevent_preload, &mention_start, &mention_end, &context_language,
196 &thumbnail_url, &caption, &quick_action_uri, &quick_action_category); 213 &thumbnail_url, &caption, &quick_action_uri, &quick_action_category);
197 if (mention_start != 0 || mention_end != 0) { 214 if (mention_start != 0 || mention_end != 0) {
198 // Sanity check that our selection is non-zero and it is less than 215 // Sanity check that our selection is non-zero and it is less than
199 // 100 characters as that would make contextual search bar hide. 216 // 100 characters as that would make contextual search bar hide.
200 // We also check that there is at least one character overlap between 217 // We also check that there is at least one character overlap between
201 // the new and old selection. 218 // the new and old selection.
202 if (mention_start >= mention_end || 219 if (mention_start >= mention_end ||
203 (mention_end - mention_start) > kContextualSearchMaxSelection || 220 (mention_end - mention_start) > kContextualSearchMaxSelection ||
204 mention_end <= context_->start_offset || 221 mention_end <= context_->GetStartOffset() ||
205 mention_start >= context_->end_offset) { 222 mention_start >= context_->GetEndOffset()) {
206 start_adjust = 0; 223 start_adjust = 0;
207 end_adjust = 0; 224 end_adjust = 0;
208 } else { 225 } else {
209 start_adjust = mention_start - context_->start_offset; 226 start_adjust = mention_start - context_->GetStartOffset();
210 end_adjust = mention_end - context_->end_offset; 227 end_adjust = mention_end - context_->GetEndOffset();
211 } 228 }
212 } 229 }
213 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID; 230 bool is_invalid = response_code == net::URLFetcher::RESPONSE_CODE_INVALID;
214 return std::unique_ptr<ResolvedSearchTerm>(new ResolvedSearchTerm( 231 return std::unique_ptr<ResolvedSearchTerm>(new ResolvedSearchTerm(
215 is_invalid, response_code, search_term, display_text, alternate_term, mid, 232 is_invalid, response_code, search_term, display_text, alternate_term, mid,
216 prevent_preload == kDoPreventPreloadValue, start_adjust, end_adjust, 233 prevent_preload == kDoPreventPreloadValue, start_adjust, end_adjust,
217 context_language, thumbnail_url, caption, quick_action_uri, 234 context_language, thumbnail_url, caption, quick_action_uri,
218 quick_action_category)); 235 quick_action_category));
219 } 236 }
220 237
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 if (!replacement_url.empty()) { 280 if (!replacement_url.empty()) {
264 size_t pos = request.find(kContextualSearchServerEndpoint); 281 size_t pos = request.find(kContextualSearchServerEndpoint);
265 if (pos != std::string::npos) { 282 if (pos != std::string::npos) {
266 request.replace(0, pos + strlen(kContextualSearchServerEndpoint), 283 request.replace(0, pos + strlen(kContextualSearchServerEndpoint),
267 replacement_url); 284 replacement_url);
268 } 285 }
269 } 286 }
270 return request; 287 return request;
271 } 288 }
272 289
273 void ContextualSearchDelegate::GatherSurroundingTextWithCallback( 290 void ContextualSearchDelegate::OnTextSurroundingSelectionAvailable(
274 const std::string& selection,
275 const std::string& home_country,
276 content::WebContents* web_contents,
277 bool may_send_base_page_url,
278 HandleSurroundingsCallback callback) {
279 // Immediately cancel any request that's in flight, since we're building a new
280 // context (and the response disposes of any existing context).
281 search_term_fetcher_.reset();
282 BuildContext(selection, home_country, web_contents, may_send_base_page_url);
283 DCHECK(web_contents);
284 RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
285 if (focused_frame) {
286 focused_frame->RequestTextSurroundingSelection(
287 callback, field_trial_->GetSurroundingSize());
288 } else {
289 callback.Run(base::string16(), 0, 0);
290 }
291 }
292
293 void ContextualSearchDelegate::BuildContext(const std::string& selection,
294 const std::string& home_country,
295 content::WebContents* web_contents,
296 bool may_send_base_page_url) {
297 // Decide if the URL should be sent with the context.
298 GURL page_url(web_contents->GetURL());
299 GURL url_to_send;
300 if (may_send_base_page_url &&
301 CanSendPageURL(page_url, ProfileManager::GetActiveUserProfile(),
302 template_url_service_)) {
303 url_to_send = page_url;
304 }
305 std::string encoding(web_contents->GetEncoding());
306 context_.reset(new ContextualSearchContext(selection, home_country,
307 url_to_send, encoding));
308 }
309
310 void ContextualSearchDelegate::StartSearchTermRequestFromSelection(
311 const base::string16& surrounding_text, 291 const base::string16& surrounding_text,
312 int start_offset, 292 int start_offset,
313 int end_offset) { 293 int end_offset) {
314 // TODO(donnd): figure out how to gather text surrounding the selection 294 SaveSurroundingText(surrounding_text, start_offset, end_offset);
315 // for other purposes too: e.g. to determine if we should select the 295 if (context_->CanResolve())
316 // word where the user tapped.
317 if (context_.get()) {
318 SaveSurroundingText(surrounding_text, start_offset, end_offset);
319 SendSurroundingText(kSurroundingSizeForUI); 296 SendSurroundingText(kSurroundingSizeForUI);
320 ContinueSearchTermResolutionRequest();
321 } else {
322 DVLOG(1) << "ctxs: Null context, ignored!";
323 }
324 } 297 }
325 298
326 void ContextualSearchDelegate::SaveSurroundingText( 299 void ContextualSearchDelegate::SaveSurroundingText(
327 const base::string16& surrounding_text, 300 const base::string16& surrounding_text,
328 int start_offset, 301 int start_offset,
329 int end_offset) { 302 int end_offset) {
330 DCHECK(context_.get()); 303 DCHECK(context_);
331 // Sometimes the surroundings are 0, 0, '', so fall back on the selection. 304 // Sometimes the surroundings are 0, 0, '', so fall back on the selection.
332 // See crbug.com/393100. 305 // See crbug.com/393100.
306 bool use_selection = false;
333 if (start_offset == 0 && end_offset == 0 && surrounding_text.length() == 0) { 307 if (start_offset == 0 && end_offset == 0 && surrounding_text.length() == 0) {
334 context_->surrounding_text = base::UTF8ToUTF16(context_->selected_text); 308 use_selection = true;
335 context_->start_offset = 0; 309 end_offset = context_->GetOriginalSelectedText().length();
336 context_->end_offset = context_->selected_text.length();
337 } else {
338 context_->surrounding_text = surrounding_text;
339 context_->start_offset = start_offset;
340 context_->end_offset = end_offset;
341 } 310 }
311 const base::string16& surrounding_text_or_selection(
312 use_selection ? base::UTF8ToUTF16(context_->GetOriginalSelectedText())
313 : surrounding_text);
342 314
343 // Pin the start and end offsets to ensure they point within the string. 315 // Pin the start and end offsets to ensure they point within the string.
344 int surrounding_length = context_->surrounding_text.length(); 316 int surrounding_length = surrounding_text_or_selection.length();
345 context_->start_offset = 317 start_offset = std::min(surrounding_length, std::max(0, start_offset));
346 std::min(surrounding_length, std::max(0, context_->start_offset)); 318 end_offset = std::min(surrounding_length, std::max(0, end_offset));
347 context_->end_offset = 319
348 std::min(surrounding_length, std::max(0, context_->end_offset)); 320 context_->SetSelectionSurroundings(start_offset, end_offset,
321 surrounding_text_or_selection);
349 322
350 // Call the Icing callback with a shortened copy of the surroundings. 323 // Call the Icing callback with a shortened copy of the surroundings.
351 int icing_surrounding_size = field_trial_->GetIcingSurroundingSize(); 324 int icing_surrounding_size = field_trial_->GetIcingSurroundingSize();
352 size_t selection_start = context_->start_offset; 325 size_t selection_start = start_offset;
353 size_t selection_end = context_->end_offset; 326 size_t selection_end = end_offset;
354 if (icing_surrounding_size >= 0 && selection_start < selection_end) { 327 if (icing_surrounding_size >= 0 && selection_start <= selection_end) {
355 int icing_padding_each_side = icing_surrounding_size / 2; 328 int icing_padding_each_side = icing_surrounding_size / 2;
356 base::string16 icing_surrounding_text = SurroundingTextForIcing( 329 base::string16 icing_surrounding_text = SurroundingTextForIcing(
357 context_->surrounding_text, icing_padding_each_side, &selection_start, 330 surrounding_text_or_selection, icing_padding_each_side,
358 &selection_end); 331 &selection_start, &selection_end);
359 if (selection_start < selection_end) 332 if (selection_start <= selection_end)
360 icing_callback_.Run(context_->encoding, icing_surrounding_text, 333 icing_callback_.Run(context_->GetBasePageEncoding(),
361 selection_start, selection_end); 334 icing_surrounding_text, selection_start,
335 selection_end);
362 } 336 }
363 } 337 }
364 338
365 void ContextualSearchDelegate::SendSurroundingText(int max_surrounding_chars) { 339 void ContextualSearchDelegate::SendSurroundingText(int max_surrounding_chars) {
366 const base::string16& surrounding = context_->surrounding_text; 340 const base::string16& surrounding = context_->GetSurroundingText();
367 341
368 // Determine the text after the selection. 342 // Determine the text after the selection.
369 int surrounding_length = surrounding.length(); // Cast to int. 343 int surrounding_length = surrounding.length(); // Cast to int.
370 int num_after_characters = std::min( 344 int num_after_characters = std::min(
371 surrounding_length - context_->end_offset, max_surrounding_chars); 345 surrounding_length - context_->GetEndOffset(), max_surrounding_chars);
372 base::string16 after_text = surrounding.substr( 346 base::string16 after_text =
373 context_->end_offset, num_after_characters); 347 surrounding.substr(context_->GetEndOffset(), num_after_characters);
374 348
375 base::TrimWhitespace(after_text, base::TRIM_ALL, &after_text); 349 base::TrimWhitespace(after_text, base::TRIM_ALL, &after_text);
376 surrounding_callback_.Run(UTF16ToUTF8(after_text)); 350 surrounding_callback_.Run(UTF16ToUTF8(after_text));
377 } 351 }
378 352
379 void ContextualSearchDelegate::SetDiscourseContextAndAddToHeader( 353 void ContextualSearchDelegate::SetDiscourseContextAndAddToHeader(
380 const ContextualSearchContext& context) { 354 const ContextualSearchContext& context) {
381 search_term_fetcher_->AddExtraRequestHeader(GetDiscourseContext(context)); 355 search_term_fetcher_->AddExtraRequestHeader(GetDiscourseContext(context));
382 } 356 }
383 357
384 std::string ContextualSearchDelegate::GetDiscourseContext( 358 std::string ContextualSearchDelegate::GetDiscourseContext(
385 const ContextualSearchContext& context) { 359 const ContextualSearchContext& context) {
386 discourse_context::ClientDiscourseContext proto; 360 discourse_context::ClientDiscourseContext proto;
387 discourse_context::Display* display = proto.add_display(); 361 discourse_context::Display* display = proto.add_display();
388 display->set_uri(context.page_url.spec()); 362 display->set_uri(context.GetBasePageUrl().spec());
389 363
390 discourse_context::Media* media = display->mutable_media(); 364 discourse_context::Media* media = display->mutable_media();
391 media->set_mime_type(context.encoding); 365 media->set_mime_type(context.GetBasePageEncoding());
392 366
393 discourse_context::Selection* selection = display->mutable_selection(); 367 discourse_context::Selection* selection = display->mutable_selection();
394 selection->set_content(UTF16ToUTF8(context.surrounding_text)); 368 selection->set_content(UTF16ToUTF8(context.GetSurroundingText()));
395 selection->set_start(context.start_offset); 369 selection->set_start(context.GetStartOffset());
396 selection->set_end(context.end_offset); 370 selection->set_end(context.GetEndOffset());
397 selection->set_is_uri_encoded(false); 371 selection->set_is_uri_encoded(false);
398 372
399 std::string serialized; 373 std::string serialized;
400 proto.SerializeToString(&serialized); 374 proto.SerializeToString(&serialized);
401 375
402 std::string encoded_context; 376 std::string encoded_context;
403 base::Base64Encode(serialized, &encoded_context); 377 base::Base64Encode(serialized, &encoded_context);
404 // The server memoizer expects a web-safe encoding. 378 // The server memoizer expects a web-safe encoding.
405 std::replace(encoded_context.begin(), encoded_context.end(), '+', '-'); 379 std::replace(encoded_context.begin(), encoded_context.end(), '+', '-');
406 std::replace(encoded_context.begin(), encoded_context.end(), '/', '_'); 380 std::replace(encoded_context.begin(), encoded_context.end(), '/', '_');
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 end_offset -= trim; 573 end_offset -= trim;
600 } 574 }
601 if (result_text.length() > end_offset + padding_each_side_pinned) { 575 if (result_text.length() > end_offset + padding_each_side_pinned) {
602 // Trim the end. 576 // Trim the end.
603 result_text = result_text.substr(0, end_offset + padding_each_side_pinned); 577 result_text = result_text.substr(0, end_offset + padding_each_side_pinned);
604 } 578 }
605 *start = start_offset; 579 *start = start_offset;
606 *end = end_offset; 580 *end = end_offset;
607 return result_text; 581 return result_text;
608 } 582 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698