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

Side by Side Diff: content/browser/android/ime_adapter_android.cc

Issue 2752113005: Let ImeAdapterAndroid have the same lifecycle as its Java peer (Closed)
Patch Set: WebContentsObserver 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/renderer_host/ime_adapter_android.h" 5 #include "content/browser/android/ime_adapter_android.h"
6 6
7 #include <android/input.h>
boliu 2017/03/27 17:18:12 that's not alphabetical order?
Jinsuk Kim 2017/03/27 22:38:19 Thought so too but |git cl format| insists this is
boliu 2017/03/27 22:49:29 Oh, keep it if clang-format did it..
Jinsuk Kim 2017/03/27 23:01:49 Done. I was kind of curious what you would said :)
7 #include <algorithm> 8 #include <algorithm>
8 #include <android/input.h>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/android/jni_android.h" 11 #include "base/android/jni_android.h"
12 #include "base/android/jni_array.h" 12 #include "base/android/jni_array.h"
13 #include "base/android/jni_string.h" 13 #include "base/android/jni_string.h"
14 #include "base/android/scoped_java_ref.h" 14 #include "base/android/scoped_java_ref.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "content/browser/frame_host/interstitial_page_impl.h"
17 #include "content/browser/frame_host/render_frame_host_impl.h" 18 #include "content/browser/frame_host/render_frame_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_delegate.h" 19 #include "content/browser/renderer_host/render_view_host_delegate.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h" 20 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_android.h" 21 #include "content/browser/renderer_host/render_widget_host_view_android.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
21 #include "content/common/input_messages.h" 23 #include "content/common/input_messages.h"
22 #include "content/common/view_messages.h" 24 #include "content/common/view_messages.h"
23 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/native_web_keyboard_event.h" 26 #include "content/public/browser/native_web_keyboard_event.h"
25 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
26 #include "jni/ImeAdapter_jni.h" 28 #include "jni/ImeAdapter_jni.h"
27 #include "third_party/WebKit/public/platform/WebInputEvent.h" 29 #include "third_party/WebKit/public/platform/WebInputEvent.h"
28 #include "third_party/WebKit/public/platform/WebTextInputType.h" 30 #include "third_party/WebKit/public/platform/WebTextInputType.h"
29 #include "third_party/WebKit/public/web/WebCompositionUnderline.h" 31 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
30 32
31 using base::android::AttachCurrentThread; 33 using base::android::AttachCurrentThread;
32 using base::android::ConvertJavaStringToUTF16; 34 using base::android::ConvertJavaStringToUTF16;
33 using base::android::JavaParamRef; 35 using base::android::JavaParamRef;
36 using base::android::ScopedJavaLocalRef;
34 37
35 namespace content { 38 namespace content {
36 namespace { 39 namespace {
37 40
38 // Maps a java KeyEvent into a NativeWebKeyboardEvent. 41 // Maps a java KeyEvent into a NativeWebKeyboardEvent.
39 // |java_key_event| is used to maintain a globalref for KeyEvent. 42 // |java_key_event| is used to maintain a globalref for KeyEvent.
40 // |type| will determine the WebInputEvent type. 43 // |type| will determine the WebInputEvent type.
41 // type, |modifiers|, |time_ms|, |key_code|, |unicode_char| is used to create 44 // type, |modifiers|, |time_ms|, |key_code|, |unicode_char| is used to create
42 // WebKeyboardEvent. |key_code| is also needed ad need to treat the enter key 45 // WebKeyboardEvent. |key_code| is also needed ad need to treat the enter key
43 // as a key press of character \r. 46 // as a key press of character \r.
(...skipping 12 matching lines...) Expand all
56 modifiers, time_ms / 1000.0, key_code, 59 modifiers, time_ms / 1000.0, key_code,
57 scan_code, unicode_char, is_system_key); 60 scan_code, unicode_char, is_system_key);
58 } 61 }
59 62
60 } // anonymous namespace 63 } // anonymous namespace
61 64
62 bool RegisterImeAdapter(JNIEnv* env) { 65 bool RegisterImeAdapter(JNIEnv* env) {
63 return RegisterNativesImpl(env); 66 return RegisterNativesImpl(env);
64 } 67 }
65 68
69 jlong Init(JNIEnv* env,
70 const JavaParamRef<jobject>& obj,
71 const JavaParamRef<jobject>& jweb_contents) {
72 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
73 DCHECK(web_contents);
74 return reinterpret_cast<intptr_t>(
75 new ImeAdapterAndroid(env, obj, web_contents));
76 }
77
66 // Callback from Java to convert BackgroundColorSpan data to a 78 // Callback from Java to convert BackgroundColorSpan data to a
67 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|. 79 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
68 void AppendBackgroundColorSpan(JNIEnv*, 80 void AppendBackgroundColorSpan(JNIEnv*,
69 const JavaParamRef<jclass>&, 81 const JavaParamRef<jclass>&,
70 jlong underlines_ptr, 82 jlong underlines_ptr,
71 jint start, 83 jint start,
72 jint end, 84 jint end,
73 jint background_color) { 85 jint background_color) {
74 DCHECK_GE(start, 0); 86 DCHECK_GE(start, 0);
75 DCHECK_GE(end, 0); 87 DCHECK_GE(end, 0);
76 // Do not check |background_color|. 88 // Do not check |background_color|.
77 std::vector<blink::WebCompositionUnderline>* underlines = 89 std::vector<blink::WebCompositionUnderline>* underlines =
78 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>( 90 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
79 underlines_ptr); 91 underlines_ptr);
80 underlines->push_back( 92 underlines->push_back(blink::WebCompositionUnderline(
81 blink::WebCompositionUnderline(static_cast<unsigned>(start), 93 static_cast<unsigned>(start), static_cast<unsigned>(end),
82 static_cast<unsigned>(end), 94 SK_ColorTRANSPARENT, false, static_cast<unsigned>(background_color)));
83 SK_ColorTRANSPARENT,
84 false,
85 static_cast<unsigned>(background_color)));
86 } 95 }
87 96
88 // Callback from Java to convert UnderlineSpan data to a 97 // Callback from Java to convert UnderlineSpan data to a
89 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|. 98 // blink::WebCompositionUnderline instance, and append it to |underlines_ptr|.
90 void AppendUnderlineSpan(JNIEnv*, 99 void AppendUnderlineSpan(JNIEnv*,
91 const JavaParamRef<jclass>&, 100 const JavaParamRef<jclass>&,
92 jlong underlines_ptr, 101 jlong underlines_ptr,
93 jint start, 102 jint start,
94 jint end) { 103 jint end) {
95 DCHECK_GE(start, 0); 104 DCHECK_GE(start, 0);
96 DCHECK_GE(end, 0); 105 DCHECK_GE(end, 0);
97 std::vector<blink::WebCompositionUnderline>* underlines = 106 std::vector<blink::WebCompositionUnderline>* underlines =
98 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>( 107 reinterpret_cast<std::vector<blink::WebCompositionUnderline>*>(
99 underlines_ptr); 108 underlines_ptr);
100 underlines->push_back( 109 underlines->push_back(blink::WebCompositionUnderline(
101 blink::WebCompositionUnderline(static_cast<unsigned>(start), 110 static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorBLACK,
102 static_cast<unsigned>(end), 111 false, SK_ColorTRANSPARENT));
103 SK_ColorBLACK,
104 false,
105 SK_ColorTRANSPARENT));
106 } 112 }
107 113
108 ImeAdapterAndroid::ImeAdapterAndroid(RenderWidgetHostViewAndroid* rwhva) 114 ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env,
109 : rwhva_(rwhva) { 115 const JavaParamRef<jobject>& obj,
110 DCHECK(rwhva_); 116 WebContents* web_contents)
117 : WebContentsObserver(web_contents),
118 web_contents_(static_cast<WebContentsImpl*>(web_contents)),
119 rwhva_(nullptr) {
120 java_ime_adapter_ = JavaObjectWeakGlobalRef(env, obj);
111 } 121 }
112 122
113 ImeAdapterAndroid::~ImeAdapterAndroid() { 123 ImeAdapterAndroid::~ImeAdapterAndroid() {
114 JNIEnv* env = AttachCurrentThread(); 124 JNIEnv* env = AttachCurrentThread();
115 base::android::ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env); 125 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
116 if (!obj.is_null()) 126 if (!obj.is_null())
117 Java_ImeAdapter_detach(env, obj); 127 Java_ImeAdapter_destroy(env, obj);
128
129 UpdateRenderProcessConnection(nullptr);
130 }
131
132 RenderWidgetHostViewAndroid* ImeAdapterAndroid::GetRenderWidgetHostViewAndroid()
133 const {
134 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
135 if (web_contents_->ShowingInterstitialPage()) {
136 rwhv = web_contents_->GetInterstitialPage()
137 ->GetMainFrame()
138 ->GetRenderViewHost()
139 ->GetWidget()
140 ->GetView();
141 }
142 return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
143 }
144
145 void ImeAdapterAndroid::RenderViewReady() {
146 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
147
148 JNIEnv* env = AttachCurrentThread();
149 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
150 if (!obj.is_null())
151 Java_ImeAdapter_onConnectedToRenderProcess(env, obj);
152 }
153
154 void ImeAdapterAndroid::RenderViewHostChanged(RenderViewHost* old_host,
155 RenderViewHost* new_host) {
156 if (new_host) {
boliu 2017/03/27 17:18:12 should set to null in the else case?
Jinsuk Kim 2017/03/27 22:38:19 Not checking new_host does the trick. Done.
157 UpdateRenderProcessConnection(static_cast<RenderWidgetHostViewAndroid*>(
158 new_host->GetWidget()->GetView()));
159 }
160 }
161
162 void ImeAdapterAndroid::DidAttachInterstitialPage() {
163 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
164 }
165
166 void ImeAdapterAndroid::DidDetachInterstitialPage() {
167 UpdateRenderProcessConnection(GetRenderWidgetHostViewAndroid());
168 }
169
170 void ImeAdapterAndroid::WebContentsDestroyed() {
171 delete this;
172 }
173
174 void ImeAdapterAndroid::UpdateRenderProcessConnection(
175 RenderWidgetHostViewAndroid* new_rwhva) {
176 if (rwhva_ == new_rwhva)
177 return;
178 if (rwhva_)
179 rwhva_->set_ime_adapter(nullptr);
180 if (new_rwhva)
181 new_rwhva->set_ime_adapter(this);
182 rwhva_ = new_rwhva;
118 } 183 }
119 184
120 bool ImeAdapterAndroid::SendKeyEvent( 185 bool ImeAdapterAndroid::SendKeyEvent(
121 JNIEnv* env, 186 JNIEnv* env,
122 const JavaParamRef<jobject>&, 187 const JavaParamRef<jobject>&,
123 const JavaParamRef<jobject>& original_key_event, 188 const JavaParamRef<jobject>& original_key_event,
124 int type, 189 int type,
125 int modifiers, 190 int modifiers,
126 jlong time_ms, 191 jlong time_ms,
127 int key_code, 192 int key_code,
128 int scan_code, 193 int scan_code,
129 bool is_system_key, 194 bool is_system_key,
130 int unicode_char) { 195 int unicode_char) {
196 if (!rwhva_)
197 return false;
131 NativeWebKeyboardEvent event = NativeWebKeyboardEventFromKeyEvent( 198 NativeWebKeyboardEvent event = NativeWebKeyboardEventFromKeyEvent(
132 env, original_key_event, type, modifiers, time_ms, key_code, scan_code, 199 env, original_key_event, type, modifiers, time_ms, key_code, scan_code,
133 is_system_key, unicode_char); 200 is_system_key, unicode_char);
134 rwhva_->SendKeyEvent(event); 201 rwhva_->SendKeyEvent(event);
135 return true; 202 return true;
136 } 203 }
137 204
138 void ImeAdapterAndroid::SetComposingText(JNIEnv* env, 205 void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
139 const JavaParamRef<jobject>& obj, 206 const JavaParamRef<jobject>& obj,
140 const JavaParamRef<jobject>& text, 207 const JavaParamRef<jobject>& text,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 260
194 void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, 261 void ImeAdapterAndroid::FinishComposingText(JNIEnv* env,
195 const JavaParamRef<jobject>&) { 262 const JavaParamRef<jobject>&) {
196 RenderWidgetHostImpl* rwhi = GetFocusedWidget(); 263 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
197 if (!rwhi) 264 if (!rwhi)
198 return; 265 return;
199 266
200 rwhi->ImeFinishComposingText(true); 267 rwhi->ImeFinishComposingText(true);
201 } 268 }
202 269
203 void ImeAdapterAndroid::AttachImeAdapter(
204 JNIEnv* env,
205 const JavaParamRef<jobject>& java_object) {
206 java_ime_adapter_ = JavaObjectWeakGlobalRef(env, java_object);
207 }
208
209 void ImeAdapterAndroid::CancelComposition() { 270 void ImeAdapterAndroid::CancelComposition() {
210 base::android::ScopedJavaLocalRef<jobject> obj = 271 JNIEnv* env = AttachCurrentThread();
211 java_ime_adapter_.get(AttachCurrentThread()); 272 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
212 if (!obj.is_null()) 273 if (!obj.is_null())
213 Java_ImeAdapter_cancelComposition(AttachCurrentThread(), obj); 274 Java_ImeAdapter_cancelComposition(env, obj);
214 } 275 }
215 276
216 void ImeAdapterAndroid::FocusedNodeChanged(bool is_editable_node) { 277 void ImeAdapterAndroid::FocusedNodeChanged(bool is_editable_node) {
217 base::android::ScopedJavaLocalRef<jobject> obj = 278 JNIEnv* env = AttachCurrentThread();
218 java_ime_adapter_.get(AttachCurrentThread()); 279 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
219 if (!obj.is_null()) { 280 if (!obj.is_null()) {
220 Java_ImeAdapter_focusedNodeChanged(AttachCurrentThread(), obj, 281 Java_ImeAdapter_focusedNodeChanged(env, obj, is_editable_node);
221 is_editable_node);
222 } 282 }
223 } 283 }
224 284
225 void ImeAdapterAndroid::SetEditableSelectionOffsets( 285 void ImeAdapterAndroid::SetEditableSelectionOffsets(
226 JNIEnv*, 286 JNIEnv*,
227 const JavaParamRef<jobject>&, 287 const JavaParamRef<jobject>&,
228 int start, 288 int start,
229 int end) { 289 int end) {
230 RenderFrameHost* rfh = GetFocusedFrame(); 290 RenderFrameHost* rfh = GetFocusedFrame();
231 if (!rfh) 291 if (!rfh)
232 return; 292 return;
233 293
234 rfh->Send(new InputMsg_SetEditableSelectionOffsets(rfh->GetRoutingID(), start, 294 rfh->Send(new InputMsg_SetEditableSelectionOffsets(rfh->GetRoutingID(), start,
235 end)); 295 end));
236 } 296 }
237 297
238 void ImeAdapterAndroid::SetCharacterBounds( 298 void ImeAdapterAndroid::SetCharacterBounds(
239 const std::vector<gfx::RectF>& character_bounds) { 299 const std::vector<gfx::RectF>& character_bounds) {
240 JNIEnv* env = AttachCurrentThread(); 300 JNIEnv* env = AttachCurrentThread();
241 base::android::ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env); 301 ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
242 if (obj.is_null()) 302 if (obj.is_null())
243 return; 303 return;
244 304
245 const size_t coordinates_array_size = character_bounds.size() * 4; 305 const size_t coordinates_array_size = character_bounds.size() * 4;
246 std::unique_ptr<float[]> coordinates_array(new float[coordinates_array_size]); 306 std::unique_ptr<float[]> coordinates_array(new float[coordinates_array_size]);
247 for (size_t i = 0; i < character_bounds.size(); ++i) { 307 for (size_t i = 0; i < character_bounds.size(); ++i) {
248 const gfx::RectF& rect = character_bounds[i]; 308 const gfx::RectF& rect = character_bounds[i];
249 const size_t coordinates_array_index = i * 4; 309 const size_t coordinates_array_index = i * 4;
250 coordinates_array[coordinates_array_index + 0] = rect.x(); 310 coordinates_array[coordinates_array_index + 0] = rect.x();
251 coordinates_array[coordinates_array_index + 1] = rect.y(); 311 coordinates_array[coordinates_array_index + 1] = rect.y();
252 coordinates_array[coordinates_array_index + 2] = rect.right(); 312 coordinates_array[coordinates_array_index + 2] = rect.right();
253 coordinates_array[coordinates_array_index + 3] = rect.bottom(); 313 coordinates_array[coordinates_array_index + 3] = rect.bottom();
254 } 314 }
255 Java_ImeAdapter_setCharacterBounds( 315 Java_ImeAdapter_setCharacterBounds(
256 env, obj, base::android::ToJavaFloatArray(env, coordinates_array.get(), 316 env, obj,
257 coordinates_array_size)); 317 base::android::ToJavaFloatArray(env, coordinates_array.get(),
318 coordinates_array_size));
258 } 319 }
259 320
260 void ImeAdapterAndroid::SetComposingRegion(JNIEnv*, 321 void ImeAdapterAndroid::SetComposingRegion(JNIEnv*,
261 const JavaParamRef<jobject>&, 322 const JavaParamRef<jobject>&,
262 int start, 323 int start,
263 int end) { 324 int end) {
264 RenderFrameHost* rfh = GetFocusedFrame(); 325 RenderFrameHost* rfh = GetFocusedFrame();
265 if (!rfh) 326 if (!rfh)
266 return; 327 return;
267 328
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 const base::android::JavaParamRef<jobject>& obj, 370 const base::android::JavaParamRef<jobject>& obj,
310 bool immediate_request, 371 bool immediate_request,
311 bool monitor_request) { 372 bool monitor_request) {
312 RenderWidgetHostImpl* rwhi = GetFocusedWidget(); 373 RenderWidgetHostImpl* rwhi = GetFocusedWidget();
313 if (!rwhi) 374 if (!rwhi)
314 return; 375 return;
315 rwhi->Send(new InputMsg_RequestCompositionUpdate( 376 rwhi->Send(new InputMsg_RequestCompositionUpdate(
316 rwhi->GetRoutingID(), immediate_request, monitor_request)); 377 rwhi->GetRoutingID(), immediate_request, monitor_request));
317 } 378 }
318 379
319 void ImeAdapterAndroid::ResetImeAdapter(JNIEnv* env,
320 const JavaParamRef<jobject>&) {
321 java_ime_adapter_.reset();
322 }
323
324 RenderWidgetHostImpl* ImeAdapterAndroid::GetFocusedWidget() { 380 RenderWidgetHostImpl* ImeAdapterAndroid::GetFocusedWidget() {
325 DCHECK_CURRENTLY_ON(BrowserThread::UI); 381 DCHECK_CURRENTLY_ON(BrowserThread::UI);
326 return rwhva_->GetFocusedWidget(); 382 return rwhva_ ? rwhva_->GetFocusedWidget() : nullptr;
327 } 383 }
328 384
329 RenderFrameHost* ImeAdapterAndroid::GetFocusedFrame() { 385 RenderFrameHost* ImeAdapterAndroid::GetFocusedFrame() {
330 DCHECK_CURRENTLY_ON(BrowserThread::UI); 386 DCHECK_CURRENTLY_ON(BrowserThread::UI);
331 // We get the focused frame from the WebContents of the page. Although 387 // We get the focused frame from the WebContents of the page. Although
332 // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way 388 // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way
333 // to get a RenderFrameHost from its RWH. 389 // to get a RenderFrameHost from its RWH.
390 if (!rwhva_)
391 return nullptr;
334 RenderWidgetHostImpl* rwh = 392 RenderWidgetHostImpl* rwh =
335 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost()); 393 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
336 if (!rwh || !rwh->delegate()) 394 if (!rwh || !rwh->delegate())
337 return nullptr; 395 return nullptr;
338 396
339 if (auto* contents = rwh->delegate()->GetAsWebContents()) 397 if (auto* contents = rwh->delegate()->GetAsWebContents())
340 return contents->GetFocusedFrame(); 398 return contents->GetFocusedFrame();
341 399
342 return nullptr; 400 return nullptr;
343 } 401 }
(...skipping 11 matching lines...) Expand all
355 Java_ImeAdapter_populateUnderlinesFromSpans( 413 Java_ImeAdapter_populateUnderlinesFromSpans(
356 env, obj, text, reinterpret_cast<jlong>(&underlines)); 414 env, obj, text, reinterpret_cast<jlong>(&underlines));
357 415
358 // Sort spans by |.startOffset|. 416 // Sort spans by |.startOffset|.
359 std::sort(underlines.begin(), underlines.end()); 417 std::sort(underlines.begin(), underlines.end());
360 418
361 return underlines; 419 return underlines;
362 } 420 }
363 421
364 } // namespace content 422 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698