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

Side by Side Diff: ui/views/controls/textfield/textfield_unittest.cc

Issue 1177503003: Remove the 2-level input method system & InputMethodBridge. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: makes trybots green. Created 5 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "ui/views/controls/textfield/textfield.h" 5 #include "ui/views/controls/textfield/textfield.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/pickle.h" 12 #include "base/pickle.h"
13 #include "base/strings/string16.h" 13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "ui/accessibility/ax_view_state.h" 15 #include "ui/accessibility/ax_view_state.h"
16 #include "ui/aura/window.h"
17 #include "ui/aura/window_tree_host.h"
16 #include "ui/base/clipboard/clipboard.h" 18 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/clipboard/scoped_clipboard_writer.h" 19 #include "ui/base/clipboard/scoped_clipboard_writer.h"
18 #include "ui/base/dragdrop/drag_drop_types.h" 20 #include "ui/base/dragdrop/drag_drop_types.h"
21 #include "ui/base/ime/input_method_base.h"
22 #include "ui/base/ime/input_method_delegate.h"
23 #include "ui/base/ime/input_method_factory.h"
19 #include "ui/base/ime/text_input_client.h" 24 #include "ui/base/ime/text_input_client.h"
20 #include "ui/base/l10n/l10n_util.h" 25 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/ui_base_switches.h" 26 #include "ui/base/ui_base_switches.h"
22 #include "ui/base/ui_base_switches_util.h" 27 #include "ui/base/ui_base_switches_util.h"
23 #include "ui/events/event.h" 28 #include "ui/events/event.h"
29 #include "ui/events/event_processor.h"
24 #include "ui/events/event_utils.h" 30 #include "ui/events/event_utils.h"
25 #include "ui/events/keycodes/keyboard_codes.h" 31 #include "ui/events/keycodes/keyboard_codes.h"
26 #include "ui/events/test/event_generator.h" 32 #include "ui/events/test/event_generator.h"
27 #include "ui/gfx/render_text.h" 33 #include "ui/gfx/render_text.h"
28 #include "ui/strings/grit/ui_strings.h" 34 #include "ui/strings/grit/ui_strings.h"
29 #include "ui/views/controls/textfield/textfield_controller.h" 35 #include "ui/views/controls/textfield/textfield_controller.h"
30 #include "ui/views/controls/textfield/textfield_model.h" 36 #include "ui/views/controls/textfield/textfield_model.h"
31 #include "ui/views/controls/textfield/textfield_test_api.h" 37 #include "ui/views/controls/textfield/textfield_test_api.h"
32 #include "ui/views/focus/focus_manager.h" 38 #include "ui/views/focus/focus_manager.h"
33 #include "ui/views/ime/mock_input_method.h"
34 #include "ui/views/test/test_views_delegate.h" 39 #include "ui/views/test/test_views_delegate.h"
35 #include "ui/views/test/views_test_base.h" 40 #include "ui/views/test/views_test_base.h"
36 #include "ui/views/test/widget_test.h" 41 #include "ui/views/test/widget_test.h"
37 #include "ui/views/widget/widget.h" 42 #include "ui/views/widget/widget.h"
38 #include "url/gurl.h" 43 #include "url/gurl.h"
39 44
40 #if defined(OS_WIN) 45 #if defined(OS_WIN)
41 #include "base/win/windows_version.h" 46 #include "base/win/windows_version.h"
42 #endif 47 #endif
43 48
44 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 49 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
45 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h" 50 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
46 #endif 51 #endif
47 52
48 #if defined(USE_X11) 53 #if defined(USE_X11)
49 #include "ui/events/event_utils.h" 54 #include "ui/events/event_utils.h"
50 #endif 55 #endif
51 56
52 using base::ASCIIToUTF16; 57 using base::ASCIIToUTF16;
53 using base::UTF8ToUTF16; 58 using base::UTF8ToUTF16;
54 using base::WideToUTF16; 59 using base::WideToUTF16;
55 60
56 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) 61 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
57 62
58 namespace { 63 namespace {
59 64
60 const base::char16 kHebrewLetterSamekh = 0x05E1; 65 const base::char16 kHebrewLetterSamekh = 0x05E1;
61 66
67 class MockInputMethod : public ui::InputMethodBase {
68 public:
69 MockInputMethod();
70 ~MockInputMethod() override;
71
72 // Overridden from InputMethod:
73 bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
74 NativeEventResult* result) override;
75 bool DispatchKeyEvent(const ui::KeyEvent& key) override;
76 void OnTextInputTypeChanged(const ui::TextInputClient* client) override;
77 void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
78 void CancelComposition(const ui::TextInputClient* client) override;
79 void OnInputLocaleChanged() override {}
80 std::string GetInputLocale() override;
81 bool IsActive() override;
82 bool IsCandidatePopupOpen() const override;
83 void ShowImeIfNeeded() override {}
84
85 bool untranslated_ime_message_called() const {
86 return untranslated_ime_message_called_;
87 }
88 bool text_input_type_changed() const { return text_input_type_changed_; }
89 bool cancel_composition_called() const { return cancel_composition_called_; }
90
91 // Clears all internal states and result.
92 void Clear();
93
94 void SetCompositionTextForNextKey(const ui::CompositionText& composition);
95 void SetResultTextForNextKey(const base::string16& result);
96
97 private:
98 // Overridden from InputMethodBase.
99 void OnWillChangeFocusedClient(ui::TextInputClient* focused_before,
100 ui::TextInputClient* focused) override;
101
102 // Clears boolean states defined below.
103 void ClearStates();
104
105 // Whether a mock composition or result is scheduled for the next key event.
106 bool HasComposition();
107
108 // Clears only composition information and result text.
109 void ClearComposition();
110
111 // Composition information for the next key event. It'll be cleared
112 // automatically after dispatching the next key event.
113 ui::CompositionText composition_;
114
115 // Result text for the next key event. It'll be cleared automatically after
116 // dispatching the next key event.
117 base::string16 result_text_;
118
119 // Record call state of corresponding methods. They will be set to false
120 // automatically before dispatching a key event.
121 bool untranslated_ime_message_called_;
122 bool text_input_type_changed_;
123 bool cancel_composition_called_;
124
125 DISALLOW_COPY_AND_ASSIGN(MockInputMethod);
126 };
127
128 MockInputMethod::MockInputMethod()
129 : untranslated_ime_message_called_(false),
130 text_input_type_changed_(false),
131 cancel_composition_called_(false) {
132 }
133
134 MockInputMethod::~MockInputMethod() {
135 }
136
137 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
138 NativeEventResult* result) {
139 if (result)
140 *result = NativeEventResult();
141 return false;
142 }
143
144 bool MockInputMethod::DispatchKeyEvent(const ui::KeyEvent& key) {
145 // Checks whether the key event is from EventGenerator on Windows which will
146 // generate key event for WM_CHAR.
147 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here.
148 if (key.is_char() && key.HasNativeEvent())
149 return true;
150
151 bool handled = !IsTextInputTypeNone() && HasComposition();
152 ClearStates();
153 if (handled) {
154 DCHECK(!key.is_char());
155 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, key.flags());
156 DispatchKeyEventPostIME(mock_key);
157 } else {
158 DispatchKeyEventPostIME(key);
159 }
160
161 ui::TextInputClient* client = GetTextInputClient();
162 if (client) {
163 if (handled) {
164 if (result_text_.length())
165 client->InsertText(result_text_);
166 if (composition_.text.length())
167 client->SetCompositionText(composition_);
168 else
169 client->ClearCompositionText();
170 } else if (key.type() == ui::ET_KEY_PRESSED) {
171 base::char16 ch = key.GetCharacter();
172 if (ch)
173 client->InsertChar(ch, key.flags());
174 }
175 }
176
177 ClearComposition();
178 return true;
179 }
180
181 void MockInputMethod::OnTextInputTypeChanged(
182 const ui::TextInputClient* client) {
183 if (IsTextInputClientFocused(client))
184 text_input_type_changed_ = true;
185 InputMethodBase::OnTextInputTypeChanged(client);
186 }
187
188 void MockInputMethod::CancelComposition(const ui::TextInputClient* client) {
189 if (IsTextInputClientFocused(client)) {
190 cancel_composition_called_ = true;
191 ClearComposition();
192 }
193 }
194
195 std::string MockInputMethod::GetInputLocale() {
196 return "en-US";
197 }
198
199 bool MockInputMethod::IsActive() {
200 return true;
201 }
202
203 bool MockInputMethod::IsCandidatePopupOpen() const {
204 return false;
205 }
206
207 void MockInputMethod::OnWillChangeFocusedClient(
208 ui::TextInputClient* focused_before,
209 ui::TextInputClient* focused) {
210 ui::TextInputClient* client = GetTextInputClient();
211 if (client && client->HasCompositionText())
212 client->ConfirmCompositionText();
213 ClearComposition();
214 }
215
216 void MockInputMethod::Clear() {
217 ClearStates();
218 ClearComposition();
219 }
220
221 void MockInputMethod::SetCompositionTextForNextKey(
222 const ui::CompositionText& composition) {
223 composition_ = composition;
224 }
225
226 void MockInputMethod::SetResultTextForNextKey(const base::string16& result) {
227 result_text_ = result;
228 }
229
230 void MockInputMethod::ClearStates() {
231 untranslated_ime_message_called_ = false;
232 text_input_type_changed_ = false;
233 cancel_composition_called_ = false;
234 }
235
236 bool MockInputMethod::HasComposition() {
237 return composition_.text.length() || result_text_.length();
238 }
239
240 void MockInputMethod::ClearComposition() {
241 composition_.Clear();
242 result_text_.clear();
243 }
244
62 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults. 245 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
63 class TestTextfield : public views::Textfield { 246 class TestTextfield : public views::Textfield {
64 public: 247 public:
65 TestTextfield() 248 TestTextfield()
66 : Textfield(), 249 : Textfield(),
67 key_handled_(false), 250 key_handled_(false),
68 key_received_(false), 251 key_received_(false),
69 weak_ptr_factory_(this) {} 252 weak_ptr_factory_(this) {}
70 253
71 bool OnKeyPressed(const ui::KeyEvent& e) override { 254 bool OnKeyPressed(const ui::KeyEvent& e) override {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 class TextfieldTest : public ViewsTestBase, public TextfieldController { 347 class TextfieldTest : public ViewsTestBase, public TextfieldController {
165 public: 348 public:
166 TextfieldTest() 349 TextfieldTest()
167 : widget_(NULL), 350 : widget_(NULL),
168 textfield_(NULL), 351 textfield_(NULL),
169 model_(NULL), 352 model_(NULL),
170 input_method_(NULL), 353 input_method_(NULL),
171 on_before_user_action_(0), 354 on_before_user_action_(0),
172 on_after_user_action_(0), 355 on_after_user_action_(0),
173 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) { 356 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
357 input_method_ = new MockInputMethod();
358 ui::SetUpInputMethodForTesting(input_method_);
174 } 359 }
175 360
176 // ::testing::Test: 361 // ::testing::Test:
177 void TearDown() override { 362 void TearDown() override {
178 if (widget_) 363 if (widget_)
179 widget_->Close(); 364 widget_->Close();
180 ViewsTestBase::TearDown(); 365 ViewsTestBase::TearDown();
181 } 366 }
182 367
183 ui::ClipboardType GetAndResetCopiedToClipboard() { 368 ui::ClipboardType GetAndResetCopiedToClipboard() {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 textfield_->set_controller(this); 402 textfield_->set_controller(this);
218 widget_ = new Widget(); 403 widget_ = new Widget();
219 404
220 // The widget type must be an activatable type, and we don't want to worry 405 // The widget type must be an activatable type, and we don't want to worry
221 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS. 406 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
222 Widget::InitParams params = 407 Widget::InitParams params =
223 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); 408 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
224 409
225 params.bounds = gfx::Rect(100, 100, 100, 100); 410 params.bounds = gfx::Rect(100, 100, 100, 100);
226 widget_->Init(params); 411 widget_->Init(params);
412 input_method_->SetDelegate(static_cast<ui::internal::InputMethodDelegate*>(
413 widget_->GetNativeWindow()->GetRootWindow()->GetHost()));
227 View* container = new View(); 414 View* container = new View();
228 widget_->SetContentsView(container); 415 widget_->SetContentsView(container);
229 container->AddChildView(textfield_); 416 container->AddChildView(textfield_);
230 textfield_->SetBoundsRect(params.bounds); 417 textfield_->SetBoundsRect(params.bounds);
231 textfield_->set_id(1); 418 textfield_->set_id(1);
232 test_api_.reset(new TextfieldTestApi(textfield_)); 419 test_api_.reset(new TextfieldTestApi(textfield_));
233 420
234 for (int i = 1; i < count; i++) { 421 for (int i = 1; i < count; i++) {
235 Textfield* textfield = new Textfield(); 422 Textfield* textfield = new Textfield();
236 container->AddChildView(textfield); 423 container->AddChildView(textfield);
237 textfield->set_id(i + 1); 424 textfield->set_id(i + 1);
238 } 425 }
239 426
240 model_ = test_api_->model(); 427 model_ = test_api_->model();
241 model_->ClearEditHistory(); 428 model_->ClearEditHistory();
242 429
243 input_method_ = new MockInputMethod();
244 widget_->ReplaceInputMethod(input_method_);
245
246 // Since the window type is activatable, showing the widget will also 430 // Since the window type is activatable, showing the widget will also
247 // activate it. Calling Activate directly is insufficient, since that does 431 // activate it. Calling Activate directly is insufficient, since that does
248 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the 432 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
249 // widget and the textfield must have focus to properly handle input. 433 // widget and the textfield must have focus to properly handle input.
250 widget_->Show(); 434 widget_->Show();
251 textfield_->RequestFocus(); 435 textfield_->RequestFocus();
252 436
253 // On Mac, activation is asynchronous since desktop widgets are used. We 437 // On Mac, activation is asynchronous since desktop widgets are used. We
254 // don't want parallel tests to steal active status either, so fake it. 438 // don't want parallel tests to steal active status either, so fake it.
255 #if defined(OS_MACOSX) && !defined(USE_AURA) 439 #if defined(OS_MACOSX) && !defined(USE_AURA)
(...skipping 2102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2358 2542
2359 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); 2543 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
2360 ui::AXViewState state_protected; 2544 ui::AXViewState state_protected;
2361 textfield_->GetAccessibleState(&state_protected); 2545 textfield_->GetAccessibleState(&state_protected);
2362 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role); 2546 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role);
2363 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value); 2547 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value);
2364 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED)); 2548 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED));
2365 } 2549 }
2366 2550
2367 } // namespace views 2551 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698