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

Side by Side Diff: ui/base/ime/remote_input_method_win_unittest.cc

Issue 67503004: Introduce RemoteInputMethodWin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 1 month 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 2013 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 "ui/base/ime/remote_input_method_win.h"
6
7 #include <InputScope.h>
8
9 #include <vector>
10
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string16.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/base/ime/dummy_text_input_client.h"
15 #include "ui/base/ime/input_method.h"
16 #include "ui/base/ime/input_method_delegate.h"
17 #include "ui/base/ime/remote_input_method_delegate_win.h"
18 #include "ui/events/event.h"
19
20 namespace ui {
21 namespace {
22
23 class MockTextInputClient : public DummyTextInputClient {
24 public:
25 MockTextInputClient()
26 : text_input_type_(TEXT_INPUT_TYPE_NONE),
27 text_input_mode_(TEXT_INPUT_MODE_DEFAULT) {
28 }
29
30 const base::string16& inserted_text() const {
31 return inserted_text_;
32 }
33 void Reset() {
34 inserted_text_.clear();
35 text_input_type_ = TEXT_INPUT_TYPE_NONE;
36 text_input_mode_ = TEXT_INPUT_MODE_DEFAULT;
37 caret_bounds_ = gfx::Rect();
38 composition_character_bounds_.clear();
39 }
40 void set_text_input_type(ui::TextInputType type) {
41 text_input_type_ = type;
42 }
43 void set_text_input_mode(ui::TextInputMode mode) {
44 text_input_mode_ = mode;
45 }
46 void set_caret_bounds(const gfx::Rect& caret_bounds) {
47 caret_bounds_ = caret_bounds;
48 }
49 void set_composition_character_bounds(
50 const std::vector<gfx::Rect>& composition_character_bounds) {
51 composition_character_bounds_ = composition_character_bounds;
52 }
53
54 private:
55 virtual void InsertChar(char16 ch, int flags) OVERRIDE{
56 inserted_text_.append(1, ch);
57 }
58 virtual void InsertText(const string16& text) OVERRIDE{
59 EXPECT_TRUE(false) << "RemoteInputMethodWin does not use this method";
60 }
61 virtual ui::TextInputType GetTextInputType() const OVERRIDE {
62 return text_input_type_;
63 }
64 virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
65 return text_input_mode_;
66 }
67 virtual gfx::Rect GetCaretBounds() const {
68 return caret_bounds_;
69 }
70 virtual bool GetCompositionCharacterBounds(uint32 index,
71 gfx::Rect* rect) const OVERRIDE {
72 if (!rect || composition_character_bounds_.size() <= index)
73 return false;
74 *rect = composition_character_bounds_[index];
75 return true;
76 }
77 virtual bool HasCompositionText() const OVERRIDE {
78 return !composition_character_bounds_.empty();
79 }
80
81 ui::TextInputType text_input_type_;
82 ui::TextInputMode text_input_mode_;
83 gfx::Rect caret_bounds_;
84 std::vector<gfx::Rect> composition_character_bounds_;
85 base::string16 inserted_text_;
86 DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
87 };
88
89 class MockInputMethodDelegate : public internal::InputMethodDelegate {
90 public:
91 MockInputMethodDelegate() {}
92
93 const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
94 return fabricated_key_events_;
95 }
96 void Reset() {
97 fabricated_key_events_.clear();
98 }
99
100 private:
101 virtual bool DispatchKeyEventPostIME(
102 const base::NativeEvent& native_key_event) OVERRIDE {
103 EXPECT_TRUE(false);
104 return false;
105 }
106 virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type,
107 ui::KeyboardCode key_code,
108 int flags) OVERRIDE {
109 fabricated_key_events_.push_back(key_code);
110 return false;
111 }
112
113 std::vector<ui::KeyboardCode> fabricated_key_events_;
114 DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
115 };
116
117 class MockRemoteInputMethodDelegateWin
118 : public internal::RemoteInputMethodDelegateWin {
119 public:
120 MockRemoteInputMethodDelegateWin()
121 : cancel_composition_called_(false),
122 text_input_client_updated_called_(false) {
123 }
124
125 bool cancel_composition_called() const {
126 return cancel_composition_called_;
127 }
128 bool text_input_client_updated_called() const {
129 return text_input_client_updated_called_;
130 }
131 const std::vector<int32>& input_scopes() const {
132 return input_scopes_;
133 }
134 const std::vector<gfx::Rect>& composition_character_bounds() const {
135 return composition_character_bounds_;
136 }
137 void Reset() {
138 cancel_composition_called_ = false;
139 text_input_client_updated_called_ = false;
140 input_scopes_.clear();
141 composition_character_bounds_.clear();
142 }
143
144 private:
145 virtual void CancelComposition() OVERRIDE {
146 cancel_composition_called_ = true;
147 }
148
149 virtual void OnTextInputClientUpdated(
150 const std::vector<int32>& input_scopes,
151 const std::vector<gfx::Rect>& composition_character_bounds) OVERRIDE {
152 text_input_client_updated_called_ = true;
153 input_scopes_ = input_scopes;
154 composition_character_bounds_ = composition_character_bounds;
155 }
156
157 bool cancel_composition_called_;
158 bool text_input_client_updated_called_;
159 std::vector<int32> input_scopes_;
160 std::vector<gfx::Rect> composition_character_bounds_;
161 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
162 };
163
164 TEST(RemoteInputMethodTest, Get) {
165 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
166
167 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
168 RemoteInputMethodPrivateWin* kNull =
169 static_cast<RemoteInputMethodPrivateWin*>(NULL);
170 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
171
172 MockInputMethodDelegate delegate_;
173 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
174 EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
175
176 InputMethod* dangling_ptr = input_method.get();
177 input_method.reset(NULL);
178 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
179 }
180
181 TEST(RemoteInputMethodTest, OnLanguageChanged) {
182 MockInputMethodDelegate delegate_;
183 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
184 RemoteInputMethodPrivateWin* private_ptr =
185 RemoteInputMethodPrivateWin::Get(input_method.get());
186 ASSERT_TRUE(private_ptr != NULL);
187
188 private_ptr->OnLanguageChanged(
189 MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
190 EXPECT_EQ("ja-JP", input_method->GetInputLocale());
191 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT,
192 input_method->GetInputTextDirection());
193
194 private_ptr->OnLanguageChanged(
195 MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
196 EXPECT_EQ("ar-QA", input_method->GetInputLocale());
197 EXPECT_EQ(base::i18n::RIGHT_TO_LEFT,
198 input_method->GetInputTextDirection());
199 }
200
201 TEST(RemoteInputMethodTest, OnCandidatePopupChanged) {
202 MockInputMethodDelegate delegate_;
203 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
204 RemoteInputMethodPrivateWin* private_ptr =
205 RemoteInputMethodPrivateWin::Get(input_method.get());
206 ASSERT_TRUE(private_ptr != NULL);
207
208 // Initial value
209 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
210
211 private_ptr->OnCandidatePopupChanged(true);
212 EXPECT_TRUE(input_method->IsCandidatePopupOpen());
213
214 private_ptr->OnCandidatePopupChanged(false);
215 EXPECT_FALSE(input_method->IsCandidatePopupOpen());
216 }
217
218 TEST(RemoteInputMethodTest, CancelComposition) {
219 MockInputMethodDelegate delegate_;
220 MockTextInputClient mock_text_input_client;
221 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
222
223 // This must not cause a crash.
224 input_method->CancelComposition(&mock_text_input_client);
225
226 RemoteInputMethodPrivateWin* private_ptr =
227 RemoteInputMethodPrivateWin::Get(input_method.get());
228 ASSERT_TRUE(private_ptr != NULL);
229 MockRemoteInputMethodDelegateWin mock_remote_delegate;
230 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
231
232 input_method->CancelComposition(&mock_text_input_client);
233 EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
234
235 input_method->SetFocusedTextInputClient(&mock_text_input_client);
236 input_method->CancelComposition(&mock_text_input_client);
237 EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
238 }
239
240 TEST(RemoteInputMethodTest, OnCaretBoundsChanged) {
241 MockInputMethodDelegate delegate_;
242 MockTextInputClient mock_text_input_client;
243 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
244
245 // This must not cause a crash.
246 input_method->OnCaretBoundsChanged(&mock_text_input_client);
247
248 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
249 input_method->SetFocusedTextInputClient(&mock_text_input_client);
250
251 RemoteInputMethodPrivateWin* private_ptr =
252 RemoteInputMethodPrivateWin::Get(input_method.get());
253 ASSERT_TRUE(private_ptr != NULL);
254 MockRemoteInputMethodDelegateWin mock_remote_delegate;
255 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
256
257 // Initial state must be synced.
258 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
259 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
260 EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
261 mock_remote_delegate.composition_character_bounds()[0]);
262
263 // Redundant OnCaretBoundsChanged must be ignored.
264 mock_remote_delegate.Reset();
265 input_method->OnCaretBoundsChanged(&mock_text_input_client);
266 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
267
268 // Check OnCaretBoundsChanged is handled. (w/o composition)
269 mock_remote_delegate.Reset();
270 mock_text_input_client.Reset();
271 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
272 input_method->OnCaretBoundsChanged(&mock_text_input_client);
273 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
274 ASSERT_EQ(1, mock_remote_delegate.composition_character_bounds().size());
275 EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
276 mock_remote_delegate.composition_character_bounds()[0]);
277
278 // Check OnCaretBoundsChanged is handled. (w/ composition)
279 {
280 mock_remote_delegate.Reset();
281 mock_text_input_client.Reset();
282
283 std::vector<gfx::Rect> bounds;
284 bounds.push_back(gfx::Rect(10, 20, 30, 40));
285 bounds.push_back(gfx::Rect(40, 30, 20, 10));
286 mock_text_input_client.set_composition_character_bounds(bounds);
287 input_method->OnCaretBoundsChanged(&mock_text_input_client);
288 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
289 EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
290 }
291 }
292
293 TEST(RemoteInputMethodTest, OnTextInputTypeChanged) {
294 MockInputMethodDelegate delegate_;
295 MockTextInputClient mock_text_input_client;
296 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
297
298 // This must not cause a crash.
299 input_method->OnCaretBoundsChanged(&mock_text_input_client);
300
301 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
302 input_method->SetFocusedTextInputClient(&mock_text_input_client);
303
304 RemoteInputMethodPrivateWin* private_ptr =
305 RemoteInputMethodPrivateWin::Get(input_method.get());
306 ASSERT_TRUE(private_ptr != NULL);
307 MockRemoteInputMethodDelegateWin mock_remote_delegate;
308 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
309
310 // Initial state must be synced.
311 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
312 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size());
313 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
314
315 // Check TEXT_INPUT_TYPE_NONE is handled.
316 mock_remote_delegate.Reset();
317 mock_text_input_client.Reset();
318 mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
319 mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
320 input_method->OnTextInputTypeChanged(&mock_text_input_client);
321 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
322 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
323
324 // Redundant OnTextInputTypeChanged must be ignored.
325 mock_remote_delegate.Reset();
326 input_method->OnTextInputTypeChanged(&mock_text_input_client);
327 EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
328
329 mock_remote_delegate.Reset();
330 mock_text_input_client.Reset();
331 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
332 input_method->OnCaretBoundsChanged(&mock_text_input_client);
333 }
334
335 TEST(RemoteInputMethodTest, DispatchKeyEvent) {
336 MockInputMethodDelegate delegate_;
337 MockTextInputClient mock_text_input_client;
338 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
339
340 MSG msg = { NULL, WM_KEYDOWN, ui::VKEY_A };
341 ui::KeyEvent fabricated_key_events(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
342 fabricated_key_events.set_character(L'A');
343 ui::KeyEvent native_key_event(msg, false);
344
345 // This must not cause a crash.
346 input_method->DispatchKeyEvent(native_key_event);
347 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
348 input_method->DispatchKeyEvent(fabricated_key_events);
349 EXPECT_EQ(ui::VKEY_A, delegate_.fabricated_key_events()[0]);
350 delegate_.Reset();
351 ASSERT_TRUE(delegate_.fabricated_key_events().empty());
352
353 RemoteInputMethodPrivateWin* private_ptr =
354 RemoteInputMethodPrivateWin::Get(input_method.get());
355 ASSERT_TRUE(private_ptr != NULL);
356 MockRemoteInputMethodDelegateWin mock_remote_delegate;
357 private_ptr->SetRemoteDelegate(&mock_remote_delegate);
358
359 input_method->DispatchKeyEvent(native_key_event);
360 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
361 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
362
363 delegate_.Reset();
364
365 input_method->DispatchKeyEvent(fabricated_key_events);
366 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
367 EXPECT_EQ(ui::VKEY_A, delegate_.fabricated_key_events()[0]);
368
369 delegate_.Reset();
370
371 input_method->SetFocusedTextInputClient(&mock_text_input_client);
372
373 input_method->DispatchKeyEvent(native_key_event);
374 EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
375 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
376
377 mock_text_input_client.Reset();
378
379 input_method->DispatchKeyEvent(fabricated_key_events);
380 EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
381 EXPECT_TRUE(delegate_.fabricated_key_events().empty());
382 }
383
384 } // namespace
385 } // namespace ui
OLDNEW
« ui/base/ime/remote_input_method_win.cc ('K') | « ui/base/ime/remote_input_method_win.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698