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

Unified Diff: chrome/browser/android/contextualsearch/search_action.cc

Issue 2211353002: [TTS] Gather surrounding text on Tap before any UX. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Split usage of the Tapped text from the SearchAction into a separate CL. Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/contextualsearch/search_action.cc
diff --git a/chrome/browser/android/contextualsearch/search_action.cc b/chrome/browser/android/contextualsearch/search_action.cc
new file mode 100644
index 0000000000000000000000000000000000000000..67db3a7f6f58c5d794e875b36965b9b29bcf5125
--- /dev/null
+++ b/chrome/browser/android/contextualsearch/search_action.cc
@@ -0,0 +1,205 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/contextualsearch/search_action.h"
+
+#include <set>
+
+#include "base/android/jni_string.h"
+#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/android/contextualsearch/contextual_search_context.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/SearchAction_jni.h"
+#include "url/gurl.h"
+
+using base::android::JavaParamRef;
+
+namespace {
+
+const int kSurroundingTextSize = 1536;
+const int kSurroundingTextSampleSize = 200;
+}
+
+SearchAction::SearchAction(JNIEnv* env, jobject obj) {
+ java_object_.Reset(env, obj);
+}
+
+SearchAction::~SearchAction() {
+ LOG(ERROR) << "ctxs ===== native SearchAction::~SearchAction";
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_SearchAction_clearNativePointer(env, java_object_.obj());
+}
+
+void SearchAction::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
+ LOG(ERROR) << "ctxs ===== native SearchAction::Destroy";
+ delete this;
+}
+
+void SearchAction::RequestSurroundingText(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& j_web_contents) {
+ content::WebContents* web_contents =
+ content::WebContents::FromJavaWebContents(j_web_contents.obj());
+ DCHECK(web_contents);
+
+ GURL url(web_contents->GetURL());
+ std::string encoding(web_contents->GetEncoding());
+ search_context_.reset(new ContextualSearchContext(true, url, encoding));
+
+ content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
+ if (!focused_frame) {
+ OnSurroundingTextResponse(base::string16(), 0, 0);
+ } else {
+ focused_frame->RequestTextSurroundingSelection(
+ base::Bind(&SearchAction::OnSurroundingTextResponse, AsWeakPtr()),
+ kSurroundingTextSize);
+ }
+}
+
+void SearchAction::OnSurroundingTextResponse(
+ const base::string16& surrounding_text,
+ int focus_start,
+ int focus_end) {
+ search_context_->surrounding_text = surrounding_text;
+
+ // Find the focused word.
+ std::pair<int, int> focus =
+ FindFocusedWord(surrounding_text, focus_start, focus_end);
+ std::string selected_text = base::UTF16ToUTF8(
+ surrounding_text.substr(focus.first, focus.second - focus.first));
+
+ // Trim surroundings to a sample small enough to be suitable to send to Java.
+ std::pair<base::string16, int> sample = SampleSurroundings(
+ surrounding_text, focus_start, focus_end, kSurroundingTextSampleSize);
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ LOG(ERROR) << "ctxs --- surroundings";
+ LOG(ERROR) << "ctxs --- '" << sample.first << "'";
+
+ base::android::ScopedJavaLocalRef<jstring> j_surrounding_text_sample =
+ base::android::ConvertUTF16ToJavaString(env, sample.first);
+
+ LOG(ERROR) << "ctxs --- WORD [" << selected_text << "] focus " << focus_start
+ << ", " << focus_end << " focused word [" << focus.first << ", "
+ << focus.second << ") substring '" << sample.first << "' offset "
+ << sample.second;
+
+ // Notify Java.
+ Java_SearchAction_onSurroundingTextResponse(
+ env, java_object_.obj(), j_surrounding_text_sample.obj(), sample.second,
+ focus_start, focus_end, focus.first, focus.second);
+}
+
+// static
+std::pair<int, int> SearchAction::FindFocusedWord(
+ const base::string16& surrounding_text,
+ int focus_start,
+ int focus_end) {
+ int surrounding_text_length = surrounding_text.length();
+
+ // First, we need to find the focused word boundaries.
+ int focused_word_start = focus_start;
+ int focused_word_end = focus_end;
+
+ if (surrounding_text_length > 0 &&
+ IsValidCharacter(surrounding_text[focused_word_start])) {
+ // Find focused word start (inclusive)
+ for (int i = focus_start; i >= 0; i--) {
+ focused_word_start = i;
+
+ wchar_t character;
+ if (i > 0) {
+ character = surrounding_text[i - 1];
+
+ if (!IsValidCharacter(character))
+ break;
+ }
+ }
+
+ // Find focused word end (non inclusive)
+ for (int i = focus_end; i < surrounding_text_length; i++) {
+ wchar_t character = surrounding_text[i];
+
+ if (IsValidCharacter(character)) {
+ focused_word_end = i + 1;
+ } else {
+ focused_word_end = i;
+ break;
+ }
+ }
+ }
+
+ return std::pair<int, int>(focused_word_start, focused_word_end);
+}
+
+// static
+std::pair<base::string16, int> SearchAction::SampleSurroundings(
+ const base::string16& surrounding_text,
+ int focus_start,
+ int focus_end,
+ int surrounding_text_sample_limit) {
+ int surrounding_text_length = surrounding_text.length();
+
+ //---------------------------------------------------------------------------
+ // Cut the surrounding size so it can be sent to the Java side.
+
+ // Start equally distributing the size around the focal point.
+ int focal_point_size = focus_end - focus_start;
+ int sample_margin = (surrounding_text_sample_limit - focal_point_size) / 2;
+ int sample_start = focus_start - sample_margin;
+ int sample_end = focus_end + sample_margin;
+
+ // If the the start is out of bounds, compensate the end side.
+ if (sample_start < 0) {
+ sample_end -= sample_start;
+ sample_start = 0;
+ }
+
+ // If the the end is out of bounds, compensate the start side.
+ if (sample_end > surrounding_text_length) {
+ int diff = sample_end - surrounding_text_length;
+ sample_end = surrounding_text_length;
+ sample_start -= diff;
+ }
+
+ // Trim the start and end to make sure they are within bounds.
+ sample_start = std::max(0, sample_start);
+ sample_end = std::min(surrounding_text_length, sample_end);
+ base::string16 sample_string(
+ surrounding_text.substr(sample_start, sample_end - sample_start));
+ std::pair<base::string16, int> sample(sample_string, sample_start);
+ return sample;
+}
+
+// static
+bool SearchAction::IsValidCharacter(int char_code) {
+ // See http://www.unicode.org/Public/UCD/latest/ucd/NamesList.txt
+ // See http://jrgraphix.net/research/unicode_blocks.php
+
+ // TODO(pedrosimonetti): should not include CJK characters!
Theresa 2016/08/16 15:41:49 Let's be sure to get some manual test coverage on
Donn Denman 2016/08/17 04:35:22 Acknowledged.
Donn Denman 2016/08/17 04:35:22 Pedro, why shouldn't CJK characters be included he
pedro (no code reviews) 2016/08/22 20:54:17 If we include all CJK charactes, as we are doing,
Donn Denman 2016/08/23 23:21:46 Acknowledged.
+
+ if ((char_code >= 11264 && char_code <= 55295) ||
Theresa 2016/08/16 15:41:49 Can we comment on whta these are as well?
Donn Denman 2016/08/17 04:35:22 Done.
+ (char_code >= 192 && char_code <= 8191) ||
+ (char_code >= 97 && char_code <= 122) || // Lowercase letters
+ (char_code >= 65 && char_code <= 90) || // Uppercase letters
+ (char_code >= 48 && char_code <= 57)) { // Numbers
+ return true;
+ }
+
+ return false;
+}
+
+bool RegisterSearchAction(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
+ SearchAction* content = new SearchAction(env, obj);
+ return reinterpret_cast<intptr_t>(content);
+}

Powered by Google App Engine
This is Rietveld 408576698