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

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

Issue 2931443003: Add support for Android spellcheck menu in Chrome/WebViews (Closed)
Patch Set: Respond to latest comments Created 3 years, 5 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 2017 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 "content/browser/android/text_suggestion_host_android.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "content/browser/android/text_suggestion_host_mojo_impl_android.h"
11 #include "content/browser/renderer_host/render_widget_host_impl.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/render_frame_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "jni/TextSuggestionHost_jni.h"
16 #include "services/service_manager/public/cpp/interface_provider.h"
17 #include "ui/gfx/android/view_configuration.h"
18
19 using base::android::AttachCurrentThread;
20 using base::android::ConvertUTF8ToJavaString;
21 using base::android::JavaParamRef;
22 using base::android::ScopedJavaLocalRef;
23 using base::android::ToJavaArrayOfStrings;
24
25 namespace content {
26
27 bool RegisterTextSuggestionHost(JNIEnv* env) {
28 return RegisterNativesImpl(env);
29 }
30
31 jlong Init(JNIEnv* env,
32 const JavaParamRef<jobject>& obj,
33 const JavaParamRef<jobject>& jweb_contents) {
34 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
35 DCHECK(web_contents);
36 auto* text_suggestion_host =
37 new TextSuggestionHostAndroid(env, obj, web_contents);
38 text_suggestion_host->Initialize();
39 return reinterpret_cast<intptr_t>(text_suggestion_host);
40 }
41
42 TextSuggestionHostAndroid::TextSuggestionHostAndroid(
43 JNIEnv* env,
44 const JavaParamRef<jobject>& obj,
45 WebContents* web_contents)
46 : RenderWidgetHostConnector(web_contents),
47 rwhva_(nullptr),
48 java_text_suggestion_host_(JavaObjectWeakGlobalRef(env, obj)),
49 spellcheck_menu_timeout_(
50 base::Bind(&TextSuggestionHostAndroid::OnSpellCheckMenuTimeout,
51 base::Unretained(this))) {
52 FocusedNodeChanged();
53 }
54
55 TextSuggestionHostAndroid::~TextSuggestionHostAndroid() {
56 JNIEnv* env = AttachCurrentThread();
57 ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
58 if (!obj.is_null())
59 Java_TextSuggestionHost_destroy(env, obj);
60 }
61
62 void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
63 RenderWidgetHostViewAndroid* old_rwhva,
64 RenderWidgetHostViewAndroid* new_rwhva) {
65 text_suggestion_backend_ = nullptr;
66 if (old_rwhva)
67 old_rwhva->set_text_suggestion_host(nullptr);
68 if (new_rwhva)
69 new_rwhva->set_text_suggestion_host(this);
70 rwhva_ = new_rwhva;
71 }
72
73 void TextSuggestionHostAndroid::ApplySpellCheckSuggestion(
74 JNIEnv* env,
75 const JavaParamRef<jobject>&,
76 const base::android::JavaParamRef<jstring>& replacement) {
77 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
78 GetTextSuggestionBackend();
79 if (!text_suggestion_backend)
80 return;
81 text_suggestion_backend->ApplySpellCheckSuggestion(
82 ConvertJavaStringToUTF8(env, replacement));
83 }
84
85 void TextSuggestionHostAndroid::DeleteActiveSuggestionRange(
86 JNIEnv*,
87 const JavaParamRef<jobject>&) {
88 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
89 GetTextSuggestionBackend();
90 if (!text_suggestion_backend)
91 return;
92 text_suggestion_backend->DeleteActiveSuggestionRange();
93 }
94
95 void TextSuggestionHostAndroid::NewWordAddedToDictionary(
96 JNIEnv* env,
97 const JavaParamRef<jobject>&,
98 const base::android::JavaParamRef<jstring>& word) {
99 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
100 GetTextSuggestionBackend();
101 if (!text_suggestion_backend)
102 return;
103 text_suggestion_backend->NewWordAddedToDictionary(
104 ConvertJavaStringToUTF8(env, word));
105 }
106
107 void TextSuggestionHostAndroid::SuggestionMenuClosed(
108 JNIEnv*,
109 const JavaParamRef<jobject>&) {
110 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
111 GetTextSuggestionBackend();
112 if (!text_suggestion_backend)
113 return;
114 text_suggestion_backend->SuggestionMenuClosed();
115 }
116
117 void TextSuggestionHostAndroid::ShowSpellCheckSuggestionMenu(
118 double caret_x,
119 double caret_y,
120 const std::string& marked_text,
121 const std::vector<blink::mojom::SpellCheckSuggestionPtr>& suggestions) {
122 std::vector<std::string> suggestion_strings;
123 for (const auto& suggestion_ptr : suggestions)
124 suggestion_strings.push_back(suggestion_ptr->suggestion);
125 JNIEnv* env = AttachCurrentThread();
126 ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
127 if (obj.is_null())
128 return;
129
130 Java_TextSuggestionHost_showSpellCheckSuggestionMenu(
131 env, obj, caret_x, caret_y, ConvertUTF8ToJavaString(env, marked_text),
132 ToJavaArrayOfStrings(env, suggestion_strings));
133 }
134
135 void TextSuggestionHostAndroid::FocusedNodeChanged() {
136 RenderFrameHost* rfh = GetFocusedFrame();
137 if (!rfh)
138 return;
139
140 rfh->GetInterfaceRegistry()->AddInterface(base::Bind(
141 &TextSuggestionHostMojoImplAndroid::Create, base::Unretained(this)));
142 }
143
144 void TextSuggestionHostAndroid::StartSpellCheckMenuTimer() {
145 spellcheck_menu_timeout_.Stop();
146 spellcheck_menu_timeout_.Start(base::TimeDelta::FromMilliseconds(
147 gfx::ViewConfiguration::GetDoubleTapTimeoutInMs()));
148 }
149
150 void TextSuggestionHostAndroid::OnKeyEvent() {
151 spellcheck_menu_timeout_.Stop();
152
153 JNIEnv* env = AttachCurrentThread();
154 ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
155 if (obj.is_null())
156 return;
157
158 Java_TextSuggestionHost_hidePopups(env, obj);
159 }
160
161 void TextSuggestionHostAndroid::StopSpellCheckMenuTimer() {
162 spellcheck_menu_timeout_.Stop();
163 }
164
165 RenderFrameHost* TextSuggestionHostAndroid::GetFocusedFrame() {
166 DCHECK_CURRENTLY_ON(BrowserThread::UI);
167 // We get the focused frame from the WebContents of the page. Although
168 // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way
169 // to get a RenderFrameHost from its RWH.
170 if (!rwhva_)
171 return nullptr;
172 RenderWidgetHostImpl* rwh =
173 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
174 if (!rwh || !rwh->delegate())
175 return nullptr;
176
177 if (auto* contents = rwh->delegate()->GetAsWebContents())
178 return contents->GetFocusedFrame();
179
180 return nullptr;
181 }
182
183 const blink::mojom::TextSuggestionBackendPtr&
184 TextSuggestionHostAndroid::GetTextSuggestionBackend() {
185 if (!text_suggestion_backend_) {
186 if (RenderFrameHost* rfh = GetFocusedFrame()) {
187 rfh->GetRemoteInterfaces()->GetInterface(
188 mojo::MakeRequest(&text_suggestion_backend_));
189 }
190 }
191 return text_suggestion_backend_;
192 }
193
194 void TextSuggestionHostAndroid::OnSpellCheckMenuTimeout() {
195 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
196 GetTextSuggestionBackend();
197 if (!text_suggestion_backend)
198 return;
199 text_suggestion_backend->SpellCheckMenuTimeoutCallback();
200 }
201
202 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698