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

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: Actually split off LayoutTheme changes Created 3 years, 6 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
18 using base::android::AttachCurrentThread;
19 using base::android::ConvertUTF8ToJavaString;
20 using base::android::JavaParamRef;
21 using base::android::ScopedJavaLocalRef;
22 using base::android::ToJavaArrayOfStrings;
23
24 namespace content {
25 namespace {
26
27 const int kDoubleTapTimeoutInMilliseconds = 300;
Ted C 2017/06/21 17:59:21 Is this supposed to match https://developer.androi
rlanday 2017/06/28 01:35:33 Ok, I'll do that
28
29 } // namespace
30
31 bool RegisterTextSuggestionHost(JNIEnv* env) {
32 return RegisterNativesImpl(env);
33 }
34
35 jlong Init(JNIEnv* env,
36 const JavaParamRef<jobject>& obj,
37 const JavaParamRef<jobject>& jweb_contents) {
38 WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
39 DCHECK(web_contents);
40 auto* text_suggestion_host =
41 new TextSuggestionHostAndroid(env, obj, web_contents);
42 text_suggestion_host->Initialize();
43 return reinterpret_cast<intptr_t>(text_suggestion_host);
44 }
45
46 TextSuggestionHostAndroid::TextSuggestionHostAndroid(
47 JNIEnv* env,
48 const JavaParamRef<jobject>& obj,
49 WebContents* web_contents)
50 : RenderWidgetHostConnector(web_contents),
51 rwhva_(nullptr),
52 spellcheck_menu_timeout_(
53 base::Bind(&TextSuggestionHostAndroid::OnSpellCheckMenuTimeout,
54 base::Unretained(this))) {
55 java_text_suggestion_host_ = JavaObjectWeakGlobalRef(env, obj);
rlanday 2017/06/28 01:35:33 This can go in the initializer list
56
57 RenderFrameHost* rfh = GetFocusedFrame();
Ted C 2017/06/21 17:59:21 should we call FocusedNodeChanged() here instead o
rlanday 2017/06/28 01:35:33 I guess it avoids some code duplication, I'll do t
rlanday 2017/06/28 01:35:33 I guess it avoids some code duplication, I'll do t
58 if (!rfh)
59 return;
60
61 rfh->GetInterfaceRegistry()->AddInterface(base::Bind(
62 &TextSuggestionHostMojoImplAndroid::Create, base::Unretained(this)));
63 }
64
65 TextSuggestionHostAndroid::~TextSuggestionHostAndroid() {
66 JNIEnv* env = AttachCurrentThread();
67 ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
68 if (!obj.is_null())
69 Java_TextSuggestionHost_destroy(env, obj);
70 }
71
72 void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
73 RenderWidgetHostViewAndroid* old_rwhva,
74 RenderWidgetHostViewAndroid* new_rwhva) {
75 text_suggestion_backend_ = nullptr;
76 if (old_rwhva)
77 old_rwhva->set_text_suggestion_host(nullptr);
78 if (new_rwhva)
79 new_rwhva->set_text_suggestion_host(this);
80 rwhva_ = new_rwhva;
81 }
82
83 void TextSuggestionHostAndroid::ApplySpellCheckSuggestion(
84 JNIEnv* env,
85 const JavaParamRef<jobject>&,
86 const base::android::JavaParamRef<jstring>& replacement) {
87 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
88 GetTextSuggestionBackend();
89 if (!text_suggestion_backend)
90 return;
91 text_suggestion_backend->ApplySpellCheckSuggestion(
92 ConvertJavaStringToUTF8(env, replacement));
93 }
94
95 void TextSuggestionHostAndroid::DeleteActiveSuggestionRange(
96 JNIEnv*,
97 const JavaParamRef<jobject>&) {
98 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
99 GetTextSuggestionBackend();
100 if (!text_suggestion_backend)
101 return;
102 text_suggestion_backend->DeleteActiveSuggestionRange();
103 }
104
105 void TextSuggestionHostAndroid::NewWordAddedToDictionary(
106 JNIEnv* env,
107 const JavaParamRef<jobject>&,
108 const base::android::JavaParamRef<jstring>& word) {
109 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
110 GetTextSuggestionBackend();
111 if (!text_suggestion_backend)
112 return;
113 text_suggestion_backend->NewWordAddedToDictionary(
114 ConvertJavaStringToUTF8(env, word));
115 }
116 void TextSuggestionHostAndroid::SuggestionMenuClosed(
Ted C 2017/06/21 17:59:21 add blank line above this
117 JNIEnv*,
118 const JavaParamRef<jobject>&) {
119 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
120 GetTextSuggestionBackend();
121 if (!text_suggestion_backend)
122 return;
123 text_suggestion_backend->SuggestionMenuClosed();
124 }
125
126 void TextSuggestionHostAndroid::ShowSpellCheckSuggestionMenu(
127 double caret_x,
128 double caret_y,
129 const std::string& marked_text,
130 const std::vector<blink::mojom::SpellCheckSuggestionPtr>& suggestions) {
131 std::vector<std::string> suggestion_strings;
132 for (const auto& suggestion_ptr : suggestions)
133 suggestion_strings.push_back(suggestion_ptr->suggestion);
134 JNIEnv* env = AttachCurrentThread();
135 ScopedJavaLocalRef<jobject> obj = java_text_suggestion_host_.get(env);
Ted C 2017/06/21 17:59:20 should you check that obj is non-null here?
rlanday 2017/06/28 01:35:33 I think so...this class is set up pretty similarly
136 Java_TextSuggestionHost_showSpellCheckSuggestionMenu(
137 env, obj, caret_x, caret_y, ConvertUTF8ToJavaString(env, marked_text),
138 ToJavaArrayOfStrings(env, suggestion_strings));
139 }
140
141 void TextSuggestionHostAndroid::FocusedNodeChanged() {
142 RenderFrameHost* rfh = GetFocusedFrame();
143 if (!rfh)
144 return;
145
146 rfh->GetInterfaceRegistry()->AddInterface(base::Bind(
Ted C 2017/06/21 17:59:21 does there need to be a corresponding RemoveInterf
rlanday 2017/06/28 01:35:33 I don't think so, I think this object is shared be
147 &TextSuggestionHostMojoImplAndroid::Create, base::Unretained(this)));
148 }
149
150 void TextSuggestionHostAndroid::StartSpellCheckMenuTimer() {
151 spellcheck_menu_timeout_.Stop();
152 spellcheck_menu_timeout_.Start(
153 base::TimeDelta::FromMilliseconds(kDoubleTapTimeoutInMilliseconds));
154 }
155
156 void TextSuggestionHostAndroid::StopSpellCheckMenuTimer() {
157 spellcheck_menu_timeout_.Stop();
158 }
159
160 RenderFrameHost* TextSuggestionHostAndroid::GetFocusedFrame() {
161 DCHECK_CURRENTLY_ON(BrowserThread::UI);
162 // We get the focused frame from the WebContents of the page. Although
163 // |rwhva_->GetFocusedWidget()| does a similar thing, there is no direct way
164 // to get a RenderFrameHost from its RWH.
165 if (!rwhva_)
166 return nullptr;
167 RenderWidgetHostImpl* rwh =
168 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
169 if (!rwh || !rwh->delegate())
170 return nullptr;
171
172 if (auto* contents = rwh->delegate()->GetAsWebContents())
173 return contents->GetFocusedFrame();
174
175 return nullptr;
176 }
177
178 const blink::mojom::TextSuggestionBackendPtr&
179 TextSuggestionHostAndroid::GetTextSuggestionBackend() {
180 if (!text_suggestion_backend_) {
181 if (RenderFrameHost* rfh = GetFocusedFrame()) {
182 rfh->GetRemoteInterfaces()->GetInterface(
183 mojo::MakeRequest(&text_suggestion_backend_));
184 }
185 }
186 return text_suggestion_backend_;
187 }
188
189 void TextSuggestionHostAndroid::OnSpellCheckMenuTimeout() {
190 const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
191 GetTextSuggestionBackend();
192 if (!text_suggestion_backend)
193 return;
194 text_suggestion_backend->SpellCheckMenuTimeoutCallback();
195 }
196
197 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698