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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/contextualsearch/search_action.h"
6
7 #include <set>
8
9 #include "base/android/jni_string.h"
10 #include "base/bind.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/android/contextualsearch/contextual_search_context.h"
14 #include "chrome/browser/profiles/profile_manager.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/web_contents.h"
17 #include "jni/SearchAction_jni.h"
18 #include "url/gurl.h"
19
20 using base::android::JavaParamRef;
21
22 namespace {
23
24 const int kSurroundingTextSize = 1536;
25 const int kSurroundingTextSampleSize = 200;
26 }
27
28 SearchAction::SearchAction(JNIEnv* env, jobject obj) {
29 java_object_.Reset(env, obj);
30 }
31
32 SearchAction::~SearchAction() {
33 LOG(ERROR) << "ctxs ===== native SearchAction::~SearchAction";
34 JNIEnv* env = base::android::AttachCurrentThread();
35 Java_SearchAction_clearNativePointer(env, java_object_.obj());
36 }
37
38 void SearchAction::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
39 LOG(ERROR) << "ctxs ===== native SearchAction::Destroy";
40 delete this;
41 }
42
43 void SearchAction::RequestSurroundingText(
44 JNIEnv* env,
45 const JavaParamRef<jobject>& obj,
46 const JavaParamRef<jobject>& j_web_contents) {
47 content::WebContents* web_contents =
48 content::WebContents::FromJavaWebContents(j_web_contents.obj());
49 DCHECK(web_contents);
50
51 GURL url(web_contents->GetURL());
52 std::string encoding(web_contents->GetEncoding());
53 search_context_.reset(new ContextualSearchContext(true, url, encoding));
54
55 content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
56 if (!focused_frame) {
57 OnSurroundingTextResponse(base::string16(), 0, 0);
58 } else {
59 focused_frame->RequestTextSurroundingSelection(
60 base::Bind(&SearchAction::OnSurroundingTextResponse, AsWeakPtr()),
61 kSurroundingTextSize);
62 }
63 }
64
65 void SearchAction::OnSurroundingTextResponse(
66 const base::string16& surrounding_text,
67 int focus_start,
68 int focus_end) {
69 search_context_->surrounding_text = surrounding_text;
70
71 // Find the focused word.
72 std::pair<int, int> focus =
73 FindFocusedWord(surrounding_text, focus_start, focus_end);
74 std::string selected_text = base::UTF16ToUTF8(
75 surrounding_text.substr(focus.first, focus.second - focus.first));
76
77 // Trim surroundings to a sample small enough to be suitable to send to Java.
78 std::pair<base::string16, int> sample = SampleSurroundings(
79 surrounding_text, focus_start, focus_end, kSurroundingTextSampleSize);
80 JNIEnv* env = base::android::AttachCurrentThread();
81
82 LOG(ERROR) << "ctxs --- surroundings";
83 LOG(ERROR) << "ctxs --- '" << sample.first << "'";
84
85 base::android::ScopedJavaLocalRef<jstring> j_surrounding_text_sample =
86 base::android::ConvertUTF16ToJavaString(env, sample.first);
87
88 LOG(ERROR) << "ctxs --- WORD [" << selected_text << "] focus " << focus_start
89 << ", " << focus_end << " focused word [" << focus.first << ", "
90 << focus.second << ") substring '" << sample.first << "' offset "
91 << sample.second;
92
93 // Notify Java.
94 Java_SearchAction_onSurroundingTextResponse(
95 env, java_object_.obj(), j_surrounding_text_sample.obj(), sample.second,
96 focus_start, focus_end, focus.first, focus.second);
97 }
98
99 // static
100 std::pair<int, int> SearchAction::FindFocusedWord(
101 const base::string16& surrounding_text,
102 int focus_start,
103 int focus_end) {
104 int surrounding_text_length = surrounding_text.length();
105
106 // First, we need to find the focused word boundaries.
107 int focused_word_start = focus_start;
108 int focused_word_end = focus_end;
109
110 if (surrounding_text_length > 0 &&
111 IsValidCharacter(surrounding_text[focused_word_start])) {
112 // Find focused word start (inclusive)
113 for (int i = focus_start; i >= 0; i--) {
114 focused_word_start = i;
115
116 wchar_t character;
117 if (i > 0) {
118 character = surrounding_text[i - 1];
119
120 if (!IsValidCharacter(character))
121 break;
122 }
123 }
124
125 // Find focused word end (non inclusive)
126 for (int i = focus_end; i < surrounding_text_length; i++) {
127 wchar_t character = surrounding_text[i];
128
129 if (IsValidCharacter(character)) {
130 focused_word_end = i + 1;
131 } else {
132 focused_word_end = i;
133 break;
134 }
135 }
136 }
137
138 return std::pair<int, int>(focused_word_start, focused_word_end);
139 }
140
141 // static
142 std::pair<base::string16, int> SearchAction::SampleSurroundings(
143 const base::string16& surrounding_text,
144 int focus_start,
145 int focus_end,
146 int surrounding_text_sample_limit) {
147 int surrounding_text_length = surrounding_text.length();
148
149 //---------------------------------------------------------------------------
150 // Cut the surrounding size so it can be sent to the Java side.
151
152 // Start equally distributing the size around the focal point.
153 int focal_point_size = focus_end - focus_start;
154 int sample_margin = (surrounding_text_sample_limit - focal_point_size) / 2;
155 int sample_start = focus_start - sample_margin;
156 int sample_end = focus_end + sample_margin;
157
158 // If the the start is out of bounds, compensate the end side.
159 if (sample_start < 0) {
160 sample_end -= sample_start;
161 sample_start = 0;
162 }
163
164 // If the the end is out of bounds, compensate the start side.
165 if (sample_end > surrounding_text_length) {
166 int diff = sample_end - surrounding_text_length;
167 sample_end = surrounding_text_length;
168 sample_start -= diff;
169 }
170
171 // Trim the start and end to make sure they are within bounds.
172 sample_start = std::max(0, sample_start);
173 sample_end = std::min(surrounding_text_length, sample_end);
174 base::string16 sample_string(
175 surrounding_text.substr(sample_start, sample_end - sample_start));
176 std::pair<base::string16, int> sample(sample_string, sample_start);
177 return sample;
178 }
179
180 // static
181 bool SearchAction::IsValidCharacter(int char_code) {
182 // See http://www.unicode.org/Public/UCD/latest/ucd/NamesList.txt
183 // See http://jrgraphix.net/research/unicode_blocks.php
184
185 // 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.
186
187 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.
188 (char_code >= 192 && char_code <= 8191) ||
189 (char_code >= 97 && char_code <= 122) || // Lowercase letters
190 (char_code >= 65 && char_code <= 90) || // Uppercase letters
191 (char_code >= 48 && char_code <= 57)) { // Numbers
192 return true;
193 }
194
195 return false;
196 }
197
198 bool RegisterSearchAction(JNIEnv* env) {
199 return RegisterNativesImpl(env);
200 }
201
202 jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
203 SearchAction* content = new SearchAction(env, obj);
204 return reinterpret_cast<intptr_t>(content);
205 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698