Add ICU message format support
[chromium-blink-merge.git] / ui / views / controls / textfield / textfield_unittest.cc
blob056a4c569b441b5e3b9c6772b8ef5c3e6976ebca
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
3 // found in the LICENSE file.
5 #include "ui/views/controls/textfield/textfield.h"
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/command_line.h"
12 #include "base/pickle.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "ui/accessibility/ax_view_state.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/clipboard/scoped_clipboard_writer.h"
18 #include "ui/base/dragdrop/drag_drop_types.h"
19 #include "ui/base/ime/input_method_base.h"
20 #include "ui/base/ime/input_method_delegate.h"
21 #include "ui/base/ime/input_method_factory.h"
22 #include "ui/base/ime/text_input_client.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/base/ui_base_switches_util.h"
26 #include "ui/events/event.h"
27 #include "ui/events/event_processor.h"
28 #include "ui/events/event_utils.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
30 #include "ui/gfx/render_text.h"
31 #include "ui/strings/grit/ui_strings.h"
32 #include "ui/views/controls/textfield/textfield_controller.h"
33 #include "ui/views/controls/textfield/textfield_model.h"
34 #include "ui/views/controls/textfield/textfield_test_api.h"
35 #include "ui/views/focus/focus_manager.h"
36 #include "ui/views/test/test_views_delegate.h"
37 #include "ui/views/test/views_test_base.h"
38 #include "ui/views/test/widget_test.h"
39 #include "ui/views/widget/widget.h"
40 #include "url/gurl.h"
42 #if defined(OS_WIN)
43 #include "base/win/windows_version.h"
44 #endif
46 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
47 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
48 #endif
50 #if defined(USE_X11)
51 #include "ui/events/event_utils.h"
52 #endif
54 #if defined(OS_MACOSX) && !defined(USE_AURA)
55 #include "ui/events/test/event_generator.h"
56 #endif
58 using base::ASCIIToUTF16;
59 using base::UTF8ToUTF16;
60 using base::WideToUTF16;
62 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
64 namespace {
66 const base::char16 kHebrewLetterSamekh = 0x05E1;
68 class MockInputMethod : public ui::InputMethodBase {
69 public:
70 MockInputMethod();
71 ~MockInputMethod() override;
73 // Overridden from InputMethod:
74 bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
75 NativeEventResult* result) override;
76 void DispatchKeyEvent(ui::KeyEvent* key) override;
77 void OnTextInputTypeChanged(const ui::TextInputClient* client) override;
78 void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
79 void CancelComposition(const ui::TextInputClient* client) override;
80 void OnInputLocaleChanged() override {}
81 std::string GetInputLocale() override;
82 bool IsCandidatePopupOpen() const override;
83 void ShowImeIfNeeded() override {}
85 bool untranslated_ime_message_called() const {
86 return untranslated_ime_message_called_;
88 bool text_input_type_changed() const { return text_input_type_changed_; }
89 bool cancel_composition_called() const { return cancel_composition_called_; }
91 // Clears all internal states and result.
92 void Clear();
94 void SetCompositionTextForNextKey(const ui::CompositionText& composition);
95 void SetResultTextForNextKey(const base::string16& result);
97 private:
98 // Overridden from InputMethodBase.
99 void OnWillChangeFocusedClient(ui::TextInputClient* focused_before,
100 ui::TextInputClient* focused) override;
102 // Clears boolean states defined below.
103 void ClearStates();
105 // Whether a mock composition or result is scheduled for the next key event.
106 bool HasComposition();
108 // Clears only composition information and result text.
109 void ClearComposition();
111 // Composition information for the next key event. It'll be cleared
112 // automatically after dispatching the next key event.
113 ui::CompositionText composition_;
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_;
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_;
125 DISALLOW_COPY_AND_ASSIGN(MockInputMethod);
128 MockInputMethod::MockInputMethod()
129 : untranslated_ime_message_called_(false),
130 text_input_type_changed_(false),
131 cancel_composition_called_(false) {
134 MockInputMethod::~MockInputMethod() {
137 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
138 NativeEventResult* result) {
139 if (result)
140 *result = NativeEventResult();
141 return false;
144 void MockInputMethod::DispatchKeyEvent(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;
151 bool handled = !IsTextInputTypeNone() && HasComposition();
152 ClearStates();
153 if (handled) {
154 DCHECK(!key->is_char());
155 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED,
156 ui::VKEY_PROCESSKEY,
157 key->flags());
158 DispatchKeyEventPostIME(&mock_key);
159 } else {
160 DispatchKeyEventPostIME(key);
163 ui::TextInputClient* client = GetTextInputClient();
164 if (client) {
165 if (handled) {
166 if (result_text_.length())
167 client->InsertText(result_text_);
168 if (composition_.text.length())
169 client->SetCompositionText(composition_);
170 else
171 client->ClearCompositionText();
172 } else if (key->type() == ui::ET_KEY_PRESSED) {
173 base::char16 ch = key->GetCharacter();
174 if (ch)
175 client->InsertChar(ch, key->flags());
179 ClearComposition();
182 void MockInputMethod::OnTextInputTypeChanged(
183 const ui::TextInputClient* client) {
184 if (IsTextInputClientFocused(client))
185 text_input_type_changed_ = true;
186 InputMethodBase::OnTextInputTypeChanged(client);
189 void MockInputMethod::CancelComposition(const ui::TextInputClient* client) {
190 if (IsTextInputClientFocused(client)) {
191 cancel_composition_called_ = true;
192 ClearComposition();
196 std::string MockInputMethod::GetInputLocale() {
197 return "en-US";
200 bool MockInputMethod::IsCandidatePopupOpen() const {
201 return false;
204 void MockInputMethod::OnWillChangeFocusedClient(
205 ui::TextInputClient* focused_before,
206 ui::TextInputClient* focused) {
207 ui::TextInputClient* client = GetTextInputClient();
208 if (client && client->HasCompositionText())
209 client->ConfirmCompositionText();
210 ClearComposition();
213 void MockInputMethod::Clear() {
214 ClearStates();
215 ClearComposition();
218 void MockInputMethod::SetCompositionTextForNextKey(
219 const ui::CompositionText& composition) {
220 composition_ = composition;
223 void MockInputMethod::SetResultTextForNextKey(const base::string16& result) {
224 result_text_ = result;
227 void MockInputMethod::ClearStates() {
228 untranslated_ime_message_called_ = false;
229 text_input_type_changed_ = false;
230 cancel_composition_called_ = false;
233 bool MockInputMethod::HasComposition() {
234 return composition_.text.length() || result_text_.length();
237 void MockInputMethod::ClearComposition() {
238 composition_.Clear();
239 result_text_.clear();
242 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
243 class TestTextfield : public views::Textfield {
244 public:
245 TestTextfield()
246 : Textfield(),
247 key_handled_(false),
248 key_received_(false),
249 weak_ptr_factory_(this) {}
251 bool OnKeyPressed(const ui::KeyEvent& e) override {
252 key_received_ = true;
254 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
255 // verify it isn't null before writing the bool value to key_handled_.
256 base::WeakPtr<TestTextfield> textfield(weak_ptr_factory_.GetWeakPtr());
257 bool key = views::Textfield::OnKeyPressed(e);
259 if (!textfield)
260 return key;
262 key_handled_ = key;
264 return key_handled_;
267 bool OnKeyReleased(const ui::KeyEvent& e) override {
268 key_received_ = true;
269 key_handled_ = views::Textfield::OnKeyReleased(e);
270 EXPECT_FALSE(key_handled_); // Textfield doesn't override OnKeyReleased.
271 return key_handled_;
274 // ui::TextInputClient overrides:
275 void InsertChar(base::char16 ch, int flags) override {
276 views::Textfield::InsertChar(ch, flags);
277 #if defined(OS_MACOSX)
278 // On Mac, characters are inserted directly rather than attempting to get a
279 // unicode character from the ui::KeyEvent (which isn't always possible).
280 key_received_ = true;
281 #endif
284 bool key_handled() const { return key_handled_; }
285 bool key_received() const { return key_received_; }
287 void clear() { key_received_ = key_handled_ = false; }
289 private:
290 bool key_handled_;
291 bool key_received_;
293 base::WeakPtrFactory<TestTextfield> weak_ptr_factory_;
295 DISALLOW_COPY_AND_ASSIGN(TestTextfield);
298 // Convenience to make constructing a GestureEvent simpler.
299 class GestureEventForTest : public ui::GestureEvent {
300 public:
301 GestureEventForTest(int x, int y, ui::GestureEventDetails details)
302 : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
304 private:
305 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
308 // This controller will happily destroy the target textfield passed on
309 // construction when a key event is triggered.
310 class TextfieldDestroyerController : public views::TextfieldController {
311 public:
312 explicit TextfieldDestroyerController(views::Textfield* target)
313 : target_(target) {
314 target_->set_controller(this);
317 views::Textfield* target() { return target_.get(); }
319 // views::TextfieldController:
320 bool HandleKeyEvent(views::Textfield* sender,
321 const ui::KeyEvent& key_event) override {
322 target_->OnBlur();
323 target_.reset();
324 return false;
327 private:
328 scoped_ptr<views::Textfield> target_;
331 base::string16 GetClipboardText(ui::ClipboardType type) {
332 base::string16 text;
333 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
334 return text;
337 void SetClipboardText(ui::ClipboardType type, const std::string& text) {
338 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text));
341 } // namespace
343 namespace views {
345 class TextfieldTest : public ViewsTestBase, public TextfieldController {
346 public:
347 TextfieldTest()
348 : widget_(NULL),
349 textfield_(NULL),
350 model_(NULL),
351 input_method_(NULL),
352 on_before_user_action_(0),
353 on_after_user_action_(0),
354 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
355 input_method_ = new MockInputMethod();
356 ui::SetUpInputMethodForTesting(input_method_);
359 // ::testing::Test:
360 void TearDown() override {
361 if (widget_)
362 widget_->Close();
363 ViewsTestBase::TearDown();
366 ui::ClipboardType GetAndResetCopiedToClipboard() {
367 ui::ClipboardType clipboard_type = copied_to_clipboard_;
368 copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
369 return clipboard_type;
372 // TextfieldController:
373 void ContentsChanged(Textfield* sender,
374 const base::string16& new_contents) override {
375 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
376 // paste action did not change the content. So |new_contents| may match
377 // |last_contents_|. For more info, see http://crbug.com/79002
378 last_contents_ = new_contents;
381 void OnBeforeUserAction(Textfield* sender) override {
382 ++on_before_user_action_;
385 void OnAfterUserAction(Textfield* sender) override {
386 ++on_after_user_action_;
389 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) override {
390 copied_to_clipboard_ = clipboard_type;
393 void InitTextfield() {
394 InitTextfields(1);
397 void InitTextfields(int count) {
398 ASSERT_FALSE(textfield_);
399 textfield_ = new TestTextfield();
400 textfield_->set_controller(this);
401 widget_ = new Widget();
403 // The widget type must be an activatable type, and we don't want to worry
404 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
405 Widget::InitParams params =
406 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
408 params.bounds = gfx::Rect(100, 100, 100, 100);
409 widget_->Init(params);
410 input_method_->SetDelegate(
411 test::WidgetTest::GetInputMethodDelegateForWidget(widget_));
412 View* container = new View();
413 widget_->SetContentsView(container);
414 container->AddChildView(textfield_);
415 textfield_->SetBoundsRect(params.bounds);
416 textfield_->set_id(1);
417 test_api_.reset(new TextfieldTestApi(textfield_));
419 for (int i = 1; i < count; i++) {
420 Textfield* textfield = new Textfield();
421 container->AddChildView(textfield);
422 textfield->set_id(i + 1);
425 model_ = test_api_->model();
426 model_->ClearEditHistory();
428 // Since the window type is activatable, showing the widget will also
429 // activate it. Calling Activate directly is insufficient, since that does
430 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
431 // widget and the textfield must have focus to properly handle input.
432 widget_->Show();
433 textfield_->RequestFocus();
435 // On Mac, activation is asynchronous since desktop widgets are used. We
436 // don't want parallel tests to steal active status either, so fake it.
437 #if defined(OS_MACOSX) && !defined(USE_AURA)
438 fake_activation_ = test::WidgetTest::FakeWidgetIsActiveAlways();
440 // This is only used on Mac. See comment regarding |event_generator_| below.
441 event_generator_.reset(
442 new ui::test::EventGenerator(GetContext(), widget_->GetNativeWindow()));
443 #endif
446 ui::MenuModel* GetContextMenuModel() {
447 test_api_->UpdateContextMenu();
448 return test_api_->context_menu_contents();
451 // True if native Mac keystrokes should be used (to avoid ifdef litter).
452 bool TestingNativeMac() {
453 #if defined(OS_MACOSX)
454 return true;
455 #else
456 return false;
457 #endif
460 protected:
461 void SendKeyEvent(ui::KeyboardCode key_code,
462 bool alt,
463 bool shift,
464 bool control_or_command,
465 bool caps_lock) {
466 bool control = control_or_command;
467 bool command = false;
469 // By default, swap control and command for native events on Mac. This
470 // handles most cases.
471 if (TestingNativeMac())
472 std::swap(control, command);
474 int flags = (alt ? ui::EF_ALT_DOWN : 0) | (shift ? ui::EF_SHIFT_DOWN : 0) |
475 (control ? ui::EF_CONTROL_DOWN : 0) |
476 (command ? ui::EF_COMMAND_DOWN : 0) |
477 (caps_lock ? ui::EF_CAPS_LOCK_DOWN : 0);
479 #if defined(OS_MACOSX) && !defined(USE_AURA)
480 // The Mac EventGenerator hooks in before IME. It sends events first to an
481 // NSResponder, which is necessary to interpret keyboard events into
482 // appropriate editing commands.
483 event_generator_->PressKey(key_code, flags);
484 #else
485 // TODO(shuchen): making EventGenerator support input method and using
486 // EventGenerator here. crbug.com/512315.
487 ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags);
488 input_method_->DispatchKeyEvent(&event);
489 #endif
492 void SendKeyEvent(ui::KeyboardCode key_code,
493 bool shift,
494 bool control_or_command) {
495 SendKeyEvent(key_code, false, shift, control_or_command, false);
498 void SendKeyEvent(ui::KeyboardCode key_code) {
499 SendKeyEvent(key_code, false, false);
502 void SendKeyEvent(base::char16 ch) {
503 if (ch < 0x80) {
504 ui::KeyboardCode code =
505 ch == ' ' ? ui::VKEY_SPACE :
506 static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a');
507 SendKeyEvent(code);
508 } else {
509 // For unicode characters, assume they come from IME rather than the
510 // keyboard. So they are dispatched directly to the input method.
511 ui::KeyEvent event(ch, ui::VKEY_UNKNOWN, ui::EF_NONE);
512 input_method_->DispatchKeyEvent(&event);
516 // Sends a platform-specific move (and select) to start of line.
517 void SendHomeEvent(bool shift) {
518 if (TestingNativeMac()) {
519 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
520 // default key-binding on Mac.
521 SendKeyEvent(ui::VKEY_LEFT, shift /* shift */, true /* command */);
522 return;
524 SendKeyEvent(ui::VKEY_HOME, shift /* shift */, false /* control */);
527 // Sends a platform-specific move (and select) to end of line.
528 void SendEndEvent(bool shift) {
529 if (TestingNativeMac()) {
530 SendKeyEvent(ui::VKEY_RIGHT, shift, true); // Cmd+Right.
531 return;
533 SendKeyEvent(ui::VKEY_END, shift, false);
536 // Sends {delete, move, select} word {forward, backward}.
537 void SendWordEvent(ui::KeyboardCode key, bool shift) {
538 bool alt = false;
539 bool control = true;
540 bool caps = false;
541 if (TestingNativeMac()) {
542 // Use Alt+Left/Right/Backspace on native Mac.
543 alt = true;
544 control = false;
546 SendKeyEvent(key, alt, shift, control, caps);
549 // Sends Shift+Delete if supported, otherwise Cmd+X again.
550 void SendAlternateCut() {
551 if (TestingNativeMac())
552 SendKeyEvent(ui::VKEY_X, false, true);
553 else
554 SendKeyEvent(ui::VKEY_DELETE, true, false);
557 // Sends Ctrl+Insert if supported, otherwise Cmd+C again.
558 void SendAlternateCopy() {
559 if (TestingNativeMac())
560 SendKeyEvent(ui::VKEY_C, false, true);
561 else
562 SendKeyEvent(ui::VKEY_INSERT, false, true);
565 // Sends Shift+Insert if supported, otherwise Cmd+V again.
566 void SendAlternatePaste() {
567 if (TestingNativeMac())
568 SendKeyEvent(ui::VKEY_V, false, true);
569 else
570 SendKeyEvent(ui::VKEY_INSERT, true, false);
573 View* GetFocusedView() {
574 return widget_->GetFocusManager()->GetFocusedView();
577 int GetCursorPositionX(int cursor_pos) {
578 return test_api_->GetRenderText()->GetCursorBounds(
579 gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), false).x();
582 // Get the current cursor bounds.
583 gfx::Rect GetCursorBounds() {
584 return test_api_->GetRenderText()->GetUpdatedCursorBounds();
587 // Get the cursor bounds of |sel|.
588 gfx::Rect GetCursorBounds(const gfx::SelectionModel& sel) {
589 return test_api_->GetRenderText()->GetCursorBounds(sel, true);
592 gfx::Rect GetDisplayRect() {
593 return test_api_->GetRenderText()->display_rect();
596 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
597 // y-axis is in the middle of |bound|'s vertical range.
598 void MouseClick(const gfx::Rect bound, int x_offset) {
599 gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
600 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
601 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
602 ui::EF_LEFT_MOUSE_BUTTON);
603 textfield_->OnMousePressed(click);
604 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point,
605 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
606 ui::EF_LEFT_MOUSE_BUTTON);
607 textfield_->OnMouseReleased(release);
610 // This is to avoid double/triple click.
611 void NonClientMouseClick() {
612 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
613 ui::EventTimeForNow(),
614 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
615 ui::EF_LEFT_MOUSE_BUTTON);
616 textfield_->OnMousePressed(click);
617 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
618 ui::EventTimeForNow(),
619 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
620 ui::EF_LEFT_MOUSE_BUTTON);
621 textfield_->OnMouseReleased(release);
624 void VerifyTextfieldContextMenuContents(bool textfield_has_selection,
625 bool can_undo,
626 ui::MenuModel* menu) {
627 EXPECT_EQ(can_undo, menu->IsEnabledAt(0 /* UNDO */));
628 EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */));
629 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */));
630 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */));
631 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
632 menu->IsEnabledAt(4 /* PASTE */));
633 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */));
634 EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */));
635 EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */));
638 // We need widget to populate wrapper class.
639 Widget* widget_;
641 TestTextfield* textfield_;
642 scoped_ptr<TextfieldTestApi> test_api_;
643 TextfieldModel* model_;
645 // The string from Controller::ContentsChanged callback.
646 base::string16 last_contents_;
648 // For testing input method related behaviors.
649 MockInputMethod* input_method_;
651 // Indicates how many times OnBeforeUserAction() is called.
652 int on_before_user_action_;
654 // Indicates how many times OnAfterUserAction() is called.
655 int on_after_user_action_;
657 private:
658 ui::ClipboardType copied_to_clipboard_;
659 scoped_ptr<test::WidgetTest::FakeActivation> fake_activation_;
661 #if defined(OS_MACOSX) && !defined(USE_AURA)
662 scoped_ptr<ui::test::EventGenerator> event_generator_;
663 #endif
665 DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
668 TEST_F(TextfieldTest, ModelChangesTest) {
669 InitTextfield();
671 // TextfieldController::ContentsChanged() shouldn't be called when changing
672 // text programmatically.
673 last_contents_.clear();
674 textfield_->SetText(ASCIIToUTF16("this is"));
676 EXPECT_STR_EQ("this is", model_->text());
677 EXPECT_STR_EQ("this is", textfield_->text());
678 EXPECT_TRUE(last_contents_.empty());
680 textfield_->AppendText(ASCIIToUTF16(" a test"));
681 EXPECT_STR_EQ("this is a test", model_->text());
682 EXPECT_STR_EQ("this is a test", textfield_->text());
683 EXPECT_TRUE(last_contents_.empty());
685 EXPECT_EQ(base::string16(), textfield_->GetSelectedText());
686 textfield_->SelectAll(false);
687 EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText());
688 EXPECT_TRUE(last_contents_.empty());
691 TEST_F(TextfieldTest, KeyTest) {
692 InitTextfield();
693 // Event flags: key, alt, shift, ctrl, caps-lock.
694 SendKeyEvent(ui::VKEY_T, false, true, false, false);
695 SendKeyEvent(ui::VKEY_E, false, false, false, false);
696 SendKeyEvent(ui::VKEY_X, false, true, false, true);
697 SendKeyEvent(ui::VKEY_T, false, false, false, true);
698 SendKeyEvent(ui::VKEY_1, false, true, false, false);
699 SendKeyEvent(ui::VKEY_1, false, false, false, false);
700 SendKeyEvent(ui::VKEY_1, false, true, false, true);
701 SendKeyEvent(ui::VKEY_1, false, false, false, true);
703 // On Mac, Caps+Shift remains uppercase.
704 if (TestingNativeMac())
705 EXPECT_STR_EQ("TeXT!1!1", textfield_->text());
706 else
707 EXPECT_STR_EQ("TexT!1!1", textfield_->text());
710 TEST_F(TextfieldTest, ControlAndSelectTest) {
711 // Insert a test string in a textfield.
712 InitTextfield();
713 textfield_->SetText(ASCIIToUTF16("one two three"));
714 SendHomeEvent(false);
715 SendKeyEvent(ui::VKEY_RIGHT, true, false);
716 SendKeyEvent(ui::VKEY_RIGHT, true, false);
717 SendKeyEvent(ui::VKEY_RIGHT, true, false);
719 EXPECT_STR_EQ("one", textfield_->GetSelectedText());
721 // Test word select.
722 SendWordEvent(ui::VKEY_RIGHT, true);
723 EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
724 SendWordEvent(ui::VKEY_RIGHT, true);
725 EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
726 SendWordEvent(ui::VKEY_LEFT, true);
727 EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
728 SendWordEvent(ui::VKEY_LEFT, true);
729 EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
731 // Replace the selected text.
732 SendKeyEvent(ui::VKEY_Z, true, false);
733 SendKeyEvent(ui::VKEY_E, true, false);
734 SendKeyEvent(ui::VKEY_R, true, false);
735 SendKeyEvent(ui::VKEY_O, true, false);
736 SendKeyEvent(ui::VKEY_SPACE, false, false);
737 EXPECT_STR_EQ("ZERO two three", textfield_->text());
739 SendEndEvent(true);
740 EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
741 SendHomeEvent(true);
742 EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
745 TEST_F(TextfieldTest, InsertionDeletionTest) {
746 // Insert a test string in a textfield.
747 InitTextfield();
748 for (size_t i = 0; i < 10; i++)
749 SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
750 EXPECT_STR_EQ("abcdefghij", textfield_->text());
752 // Test the delete and backspace keys.
753 textfield_->SelectRange(gfx::Range(5));
754 for (int i = 0; i < 3; i++)
755 SendKeyEvent(ui::VKEY_BACK);
756 EXPECT_STR_EQ("abfghij", textfield_->text());
757 for (int i = 0; i < 3; i++)
758 SendKeyEvent(ui::VKEY_DELETE);
759 EXPECT_STR_EQ("abij", textfield_->text());
761 // Select all and replace with "k".
762 textfield_->SelectAll(false);
763 SendKeyEvent(ui::VKEY_K);
764 EXPECT_STR_EQ("k", textfield_->text());
766 // Delete the previous word from cursor.
767 bool shift = false;
768 textfield_->SetText(ASCIIToUTF16("one two three four"));
769 SendEndEvent(shift);
770 SendWordEvent(ui::VKEY_BACK, shift);
771 EXPECT_STR_EQ("one two three ", textfield_->text());
773 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
774 // and Mac.
775 SendWordEvent(ui::VKEY_LEFT, shift);
776 shift = true;
777 SendWordEvent(ui::VKEY_BACK, shift);
778 #if defined(OS_LINUX)
779 EXPECT_STR_EQ("three ", textfield_->text());
780 #else
781 EXPECT_STR_EQ("one three ", textfield_->text());
782 #endif
784 // Delete the next word from cursor.
785 textfield_->SetText(ASCIIToUTF16("one two three four"));
786 shift = false;
787 SendHomeEvent(shift);
788 SendWordEvent(ui::VKEY_DELETE, shift);
789 EXPECT_STR_EQ(" two three four", textfield_->text());
791 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
792 // and Mac.
793 SendWordEvent(ui::VKEY_RIGHT, shift);
794 shift = true;
795 SendWordEvent(ui::VKEY_DELETE, shift);
796 #if defined(OS_LINUX)
797 EXPECT_STR_EQ(" two", textfield_->text());
798 #else
799 EXPECT_STR_EQ(" two four", textfield_->text());
800 #endif
803 TEST_F(TextfieldTest, PasswordTest) {
804 InitTextfield();
805 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
806 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
807 EXPECT_TRUE(textfield_->enabled());
808 EXPECT_TRUE(textfield_->IsFocusable());
810 last_contents_.clear();
811 textfield_->SetText(ASCIIToUTF16("password"));
812 // Ensure text() and the callback returns the actual text instead of "*".
813 EXPECT_STR_EQ("password", textfield_->text());
814 EXPECT_TRUE(last_contents_.empty());
815 model_->SelectAll(false);
816 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
818 // Cut and copy should be disabled.
819 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
820 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
821 SendKeyEvent(ui::VKEY_X, false, true);
822 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
823 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
824 SendKeyEvent(ui::VKEY_C, false, true);
825 SendAlternateCopy();
826 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
827 EXPECT_STR_EQ("password", textfield_->text());
828 // [Shift]+[Delete] should just delete without copying text to the clipboard.
829 textfield_->SelectAll(false);
830 SendKeyEvent(ui::VKEY_DELETE, true, false);
832 // Paste should work normally.
833 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
834 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
835 SendKeyEvent(ui::VKEY_V, false, true);
836 SendAlternatePaste();
837 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
838 EXPECT_STR_EQ("foofoofoo", textfield_->text());
841 TEST_F(TextfieldTest, TextInputType) {
842 InitTextfield();
844 // Defaults to TEXT
845 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
847 // And can be set.
848 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
849 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
850 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
851 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
853 // Readonly textfields have type NONE
854 textfield_->SetReadOnly(true);
855 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
857 textfield_->SetReadOnly(false);
858 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
860 // As do disabled textfields
861 textfield_->SetEnabled(false);
862 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
864 textfield_->SetEnabled(true);
865 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
868 TEST_F(TextfieldTest, OnKeyPress) {
869 InitTextfield();
871 // Character keys are handled by the input method.
872 SendKeyEvent(ui::VKEY_A);
873 EXPECT_TRUE(textfield_->key_received());
874 EXPECT_FALSE(textfield_->key_handled());
875 textfield_->clear();
877 // Arrow keys and home/end are handled by the textfield.
878 SendKeyEvent(ui::VKEY_LEFT);
879 EXPECT_TRUE(textfield_->key_received());
880 EXPECT_TRUE(textfield_->key_handled());
881 textfield_->clear();
883 SendKeyEvent(ui::VKEY_RIGHT);
884 EXPECT_TRUE(textfield_->key_received());
885 EXPECT_TRUE(textfield_->key_handled());
886 textfield_->clear();
888 const bool shift = false;
889 SendHomeEvent(shift);
890 EXPECT_TRUE(textfield_->key_received());
891 EXPECT_TRUE(textfield_->key_handled());
892 textfield_->clear();
894 SendEndEvent(shift);
895 EXPECT_TRUE(textfield_->key_received());
896 EXPECT_TRUE(textfield_->key_handled());
897 textfield_->clear();
899 // F20, up/down key won't be handled.
900 SendKeyEvent(ui::VKEY_F20);
901 #if defined(OS_MACOSX)
902 // On Mac, key combinations that don't map to editing commands are forwarded
903 // on to the next responder, usually ending up at the window, which will beep.
904 EXPECT_FALSE(textfield_->key_received());
905 #else
906 EXPECT_TRUE(textfield_->key_received());
907 #endif
908 EXPECT_FALSE(textfield_->key_handled());
909 textfield_->clear();
911 SendKeyEvent(ui::VKEY_UP);
912 EXPECT_TRUE(textfield_->key_received());
913 EXPECT_FALSE(textfield_->key_handled());
914 textfield_->clear();
916 SendKeyEvent(ui::VKEY_DOWN);
917 EXPECT_TRUE(textfield_->key_received());
918 EXPECT_FALSE(textfield_->key_handled());
919 textfield_->clear();
922 // Tests that default key bindings are handled even with a delegate installed.
923 TEST_F(TextfieldTest, OnKeyPressBinding) {
924 InitTextfield();
926 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
927 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
928 class TestDelegate : public ui::TextEditKeyBindingsDelegateAuraLinux {
929 public:
930 TestDelegate() {}
931 ~TestDelegate() override {}
933 bool MatchEvent(
934 const ui::Event& event,
935 std::vector<ui::TextEditCommandAuraLinux>* commands) override {
936 return false;
939 private:
940 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
943 TestDelegate delegate;
944 ui::SetTextEditKeyBindingsDelegate(&delegate);
945 #endif
947 SendKeyEvent(ui::VKEY_A, false, false);
948 EXPECT_STR_EQ("a", textfield_->text());
949 textfield_->clear();
951 // Undo/Redo command keys are handled by the textfield.
952 SendKeyEvent(ui::VKEY_Z, false, true);
953 EXPECT_TRUE(textfield_->key_received());
954 EXPECT_TRUE(textfield_->key_handled());
955 EXPECT_TRUE(textfield_->text().empty());
956 textfield_->clear();
958 SendKeyEvent(ui::VKEY_Z, true, true);
959 EXPECT_TRUE(textfield_->key_received());
960 EXPECT_TRUE(textfield_->key_handled());
961 EXPECT_STR_EQ("a", textfield_->text());
962 textfield_->clear();
964 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
965 ui::SetTextEditKeyBindingsDelegate(NULL);
966 #endif
969 TEST_F(TextfieldTest, CursorMovement) {
970 InitTextfield();
972 // Test with trailing whitespace.
973 textfield_->SetText(ASCIIToUTF16("one two hre "));
975 // Send the cursor at the end.
976 SendKeyEvent(ui::VKEY_END);
978 // Ctrl+Left should move the cursor just before the last word.
979 const bool shift = false;
980 SendWordEvent(ui::VKEY_LEFT, shift);
981 SendKeyEvent(ui::VKEY_T);
982 EXPECT_STR_EQ("one two thre ", textfield_->text());
983 EXPECT_STR_EQ("one two thre ", last_contents_);
985 // Ctrl+Right should move the cursor to the end of the last word.
986 SendWordEvent(ui::VKEY_RIGHT, shift);
987 SendKeyEvent(ui::VKEY_E);
988 EXPECT_STR_EQ("one two three ", textfield_->text());
989 EXPECT_STR_EQ("one two three ", last_contents_);
991 // Ctrl+Right again should move the cursor to the end.
992 SendWordEvent(ui::VKEY_RIGHT, shift);
993 SendKeyEvent(ui::VKEY_BACK);
994 EXPECT_STR_EQ("one two three", textfield_->text());
995 EXPECT_STR_EQ("one two three", last_contents_);
997 // Test with leading whitespace.
998 textfield_->SetText(ASCIIToUTF16(" ne two"));
1000 // Send the cursor at the beginning.
1001 SendHomeEvent(shift);
1003 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
1004 // first word.
1005 SendWordEvent(ui::VKEY_RIGHT, shift);
1006 SendWordEvent(ui::VKEY_LEFT, shift);
1007 SendKeyEvent(ui::VKEY_O);
1008 EXPECT_STR_EQ(" one two", textfield_->text());
1009 EXPECT_STR_EQ(" one two", last_contents_);
1011 // Ctrl+Left to move the cursor to the beginning of the first word.
1012 SendWordEvent(ui::VKEY_LEFT, shift);
1013 // Ctrl+Left again should move the cursor back to the very beginning.
1014 SendWordEvent(ui::VKEY_LEFT, shift);
1015 SendKeyEvent(ui::VKEY_DELETE);
1016 EXPECT_STR_EQ("one two", textfield_->text());
1017 EXPECT_STR_EQ("one two", last_contents_);
1020 TEST_F(TextfieldTest, FocusTraversalTest) {
1021 InitTextfields(3);
1022 textfield_->RequestFocus();
1024 EXPECT_EQ(1, GetFocusedView()->id());
1025 widget_->GetFocusManager()->AdvanceFocus(false);
1026 EXPECT_EQ(2, GetFocusedView()->id());
1027 widget_->GetFocusManager()->AdvanceFocus(false);
1028 EXPECT_EQ(3, GetFocusedView()->id());
1029 // Cycle back to the first textfield.
1030 widget_->GetFocusManager()->AdvanceFocus(false);
1031 EXPECT_EQ(1, GetFocusedView()->id());
1033 widget_->GetFocusManager()->AdvanceFocus(true);
1034 EXPECT_EQ(3, GetFocusedView()->id());
1035 widget_->GetFocusManager()->AdvanceFocus(true);
1036 EXPECT_EQ(2, GetFocusedView()->id());
1037 widget_->GetFocusManager()->AdvanceFocus(true);
1038 EXPECT_EQ(1, GetFocusedView()->id());
1039 // Cycle back to the last textfield.
1040 widget_->GetFocusManager()->AdvanceFocus(true);
1041 EXPECT_EQ(3, GetFocusedView()->id());
1043 // Request focus should still work.
1044 textfield_->RequestFocus();
1045 EXPECT_EQ(1, GetFocusedView()->id());
1047 // Test if clicking on textfield view sets the focus.
1048 widget_->GetFocusManager()->AdvanceFocus(true);
1049 EXPECT_EQ(3, GetFocusedView()->id());
1050 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1051 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1052 ui::EF_LEFT_MOUSE_BUTTON);
1053 textfield_->OnMousePressed(click);
1054 EXPECT_EQ(1, GetFocusedView()->id());
1056 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
1057 SendKeyEvent(ui::VKEY_TAB, false, false);
1058 EXPECT_EQ(2, GetFocusedView()->id());
1059 SendKeyEvent(ui::VKEY_TAB, false, false);
1060 EXPECT_EQ(3, GetFocusedView()->id());
1061 // Cycle back to the first textfield.
1062 SendKeyEvent(ui::VKEY_TAB, false, false);
1063 EXPECT_EQ(1, GetFocusedView()->id());
1065 SendKeyEvent(ui::VKEY_TAB, true, false);
1066 EXPECT_EQ(3, GetFocusedView()->id());
1067 SendKeyEvent(ui::VKEY_TAB, true, false);
1068 EXPECT_EQ(2, GetFocusedView()->id());
1069 SendKeyEvent(ui::VKEY_TAB, true, false);
1070 EXPECT_EQ(1, GetFocusedView()->id());
1071 // Cycle back to the last textfield.
1072 SendKeyEvent(ui::VKEY_TAB, true, false);
1073 EXPECT_EQ(3, GetFocusedView()->id());
1076 TEST_F(TextfieldTest, ContextMenuDisplayTest) {
1077 InitTextfield();
1078 EXPECT_TRUE(textfield_->context_menu_controller());
1079 textfield_->SetText(ASCIIToUTF16("hello world"));
1080 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1081 textfield_->ClearEditHistory();
1082 EXPECT_TRUE(GetContextMenuModel());
1083 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
1085 textfield_->SelectAll(false);
1086 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
1088 SendKeyEvent(ui::VKEY_T);
1089 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
1091 textfield_->SelectAll(false);
1092 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1094 // Exercise the "paste enabled?" check in the verifier.
1095 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1096 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1099 TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
1100 InitTextfield();
1101 textfield_->SetText(ASCIIToUTF16("hello world"));
1102 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1103 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1104 ui::EF_LEFT_MOUSE_BUTTON);
1105 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
1106 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1107 ui::EF_LEFT_MOUSE_BUTTON);
1108 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1109 ui::EventTimeForNow(),
1110 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
1111 ui::EF_LEFT_MOUSE_BUTTON);
1113 // Test for double click.
1114 textfield_->OnMousePressed(click);
1115 textfield_->OnMouseReleased(release);
1116 EXPECT_TRUE(textfield_->GetSelectedText().empty());
1117 textfield_->OnMousePressed(double_click);
1118 textfield_->OnMouseReleased(release);
1119 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1121 // Test for triple click.
1122 textfield_->OnMousePressed(click);
1123 textfield_->OnMouseReleased(release);
1124 EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
1126 // Another click should reset back to double click.
1127 textfield_->OnMousePressed(click);
1128 textfield_->OnMouseReleased(release);
1129 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1132 TEST_F(TextfieldTest, DragToSelect) {
1133 InitTextfield();
1134 textfield_->SetText(ASCIIToUTF16("hello world"));
1135 const int kStart = GetCursorPositionX(5);
1136 const int kEnd = 500;
1137 gfx::Point start_point(kStart, 0);
1138 gfx::Point end_point(kEnd, 0);
1139 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point,
1140 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1141 ui::EF_LEFT_MOUSE_BUTTON);
1142 ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point,
1143 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1144 ui::EF_LEFT_MOUSE_BUTTON);
1145 ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(),
1146 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1147 ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point,
1148 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1149 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point,
1150 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1151 ui::EF_LEFT_MOUSE_BUTTON);
1152 textfield_->OnMousePressed(click_a);
1153 EXPECT_TRUE(textfield_->GetSelectedText().empty());
1154 // Check that dragging left selects the beginning of the string.
1155 textfield_->OnMouseDragged(drag_left);
1156 base::string16 text_left = textfield_->GetSelectedText();
1157 EXPECT_STR_EQ("hello", text_left);
1158 // Check that dragging right selects the rest of the string.
1159 textfield_->OnMouseDragged(drag_right);
1160 base::string16 text_right = textfield_->GetSelectedText();
1161 EXPECT_STR_EQ(" world", text_right);
1162 // Check that releasing in the same location does not alter the selection.
1163 textfield_->OnMouseReleased(release);
1164 EXPECT_EQ(text_right, textfield_->GetSelectedText());
1165 // Check that dragging from beyond the text length works too.
1166 textfield_->OnMousePressed(click_b);
1167 textfield_->OnMouseDragged(drag_left);
1168 textfield_->OnMouseReleased(release);
1169 EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText());
1172 #if defined(OS_WIN)
1173 TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
1174 InitTextfield();
1175 textfield_->SetText(ASCIIToUTF16("hello world"));
1177 ui::OSExchangeData data;
1178 base::string16 string(ASCIIToUTF16("string "));
1179 data.SetString(string);
1180 int formats = 0;
1181 std::set<OSExchangeData::CustomFormat> custom_formats;
1183 // Ensure that disabled textfields do not accept drops.
1184 textfield_->SetEnabled(false);
1185 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
1186 EXPECT_EQ(0, formats);
1187 EXPECT_TRUE(custom_formats.empty());
1188 EXPECT_FALSE(textfield_->CanDrop(data));
1189 textfield_->SetEnabled(true);
1191 // Ensure that read-only textfields do not accept drops.
1192 textfield_->SetReadOnly(true);
1193 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
1194 EXPECT_EQ(0, formats);
1195 EXPECT_TRUE(custom_formats.empty());
1196 EXPECT_FALSE(textfield_->CanDrop(data));
1197 textfield_->SetReadOnly(false);
1199 // Ensure that enabled and editable textfields do accept drops.
1200 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1201 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1202 EXPECT_TRUE(custom_formats.empty());
1203 EXPECT_TRUE(textfield_->CanDrop(data));
1204 gfx::Point drop_point(GetCursorPositionX(6), 0);
1205 ui::DropTargetEvent drop(data, drop_point, drop_point,
1206 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE);
1207 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
1208 textfield_->OnDragUpdated(drop));
1209 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_->OnPerformDrop(drop));
1210 EXPECT_STR_EQ("hello string world", textfield_->text());
1212 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1213 ui::OSExchangeData bad_data;
1214 bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1215 ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType();
1216 bad_data.SetPickledData(fmt, base::Pickle());
1217 bad_data.SetFileContents(base::FilePath(L"x"), "x");
1218 bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1219 ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL);
1220 bad_data.SetDownloadFileInfo(download);
1221 EXPECT_FALSE(textfield_->CanDrop(bad_data));
1223 #endif
1225 TEST_F(TextfieldTest, DragAndDrop_InitiateDrag) {
1226 InitTextfield();
1227 textfield_->SetText(ASCIIToUTF16("hello string world"));
1229 // Ensure the textfield will provide selected text for drag data.
1230 base::string16 string;
1231 ui::OSExchangeData data;
1232 const gfx::Range kStringRange(6, 12);
1233 textfield_->SelectRange(kStringRange);
1234 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
1235 textfield_->WriteDragDataForView(NULL, kStringPoint, &data);
1236 EXPECT_TRUE(data.GetString(&string));
1237 EXPECT_EQ(textfield_->GetSelectedText(), string);
1239 // Ensure that disabled textfields do not support drag operations.
1240 textfield_->SetEnabled(false);
1241 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1242 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1243 textfield_->SetEnabled(true);
1244 // Ensure that textfields without selections do not support drag operations.
1245 textfield_->ClearSelection();
1246 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1247 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1248 textfield_->SelectRange(kStringRange);
1249 // Ensure that password textfields do not support drag operations.
1250 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1251 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1252 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1253 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
1254 // Ensure that textfields only initiate drag operations inside the selection.
1255 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint,
1256 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1257 ui::EF_LEFT_MOUSE_BUTTON);
1258 textfield_->OnMousePressed(press_event);
1259 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1260 textfield_->GetDragOperationsForView(NULL, gfx::Point()));
1261 EXPECT_FALSE(textfield_->CanStartDragForView(NULL, gfx::Point(),
1262 gfx::Point()));
1263 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY,
1264 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1265 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
1266 gfx::Point()));
1267 // Ensure that textfields support local moves.
1268 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1269 textfield_->GetDragOperationsForView(textfield_, kStringPoint));
1272 TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
1273 InitTextfield();
1274 textfield_->SetText(ASCIIToUTF16("hello world"));
1276 base::string16 string;
1277 ui::OSExchangeData data;
1278 int formats = 0;
1279 int operations = 0;
1280 std::set<OSExchangeData::CustomFormat> custom_formats;
1282 // Start dragging "ello".
1283 textfield_->SelectRange(gfx::Range(1, 5));
1284 gfx::Point point(GetCursorPositionX(3), 0);
1285 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1286 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1287 ui::EF_LEFT_MOUSE_BUTTON);
1288 textfield_->OnMousePressed(click_a);
1289 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1290 gfx::Point()));
1291 operations = textfield_->GetDragOperationsForView(textfield_,
1292 click_a.location());
1293 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1294 operations);
1295 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1296 EXPECT_TRUE(data.GetString(&string));
1297 EXPECT_EQ(textfield_->GetSelectedText(), string);
1298 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1299 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1300 EXPECT_TRUE(custom_formats.empty());
1302 // Drop "ello" after "w".
1303 const gfx::Point kDropPoint(GetCursorPositionX(7), 0);
1304 EXPECT_TRUE(textfield_->CanDrop(data));
1305 ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
1306 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1307 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1308 EXPECT_STR_EQ("h welloorld", textfield_->text());
1309 textfield_->OnDragDone();
1311 // Undo/Redo the drag&drop change.
1312 SendKeyEvent(ui::VKEY_Z, false, true);
1313 EXPECT_STR_EQ("hello world", textfield_->text());
1314 SendKeyEvent(ui::VKEY_Z, false, true);
1315 EXPECT_STR_EQ("", textfield_->text());
1316 SendKeyEvent(ui::VKEY_Z, false, true);
1317 EXPECT_STR_EQ("", textfield_->text());
1318 SendKeyEvent(ui::VKEY_Z, true, true);
1319 EXPECT_STR_EQ("hello world", textfield_->text());
1320 SendKeyEvent(ui::VKEY_Z, true, true);
1321 EXPECT_STR_EQ("h welloorld", textfield_->text());
1322 SendKeyEvent(ui::VKEY_Z, true, true);
1323 EXPECT_STR_EQ("h welloorld", textfield_->text());
1326 TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
1327 InitTextfield();
1328 textfield_->SetText(ASCIIToUTF16("hello world"));
1330 base::string16 string;
1331 ui::OSExchangeData data;
1332 int formats = 0;
1333 int operations = 0;
1334 std::set<OSExchangeData::CustomFormat> custom_formats;
1336 // Start dragging " worl".
1337 textfield_->SelectRange(gfx::Range(5, 10));
1338 gfx::Point point(GetCursorPositionX(7), 0);
1339 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1340 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1341 ui::EF_LEFT_MOUSE_BUTTON);
1342 textfield_->OnMousePressed(click_a);
1343 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1344 gfx::Point()));
1345 operations = textfield_->GetDragOperationsForView(textfield_,
1346 click_a.location());
1347 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1348 operations);
1349 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1350 EXPECT_TRUE(data.GetString(&string));
1351 EXPECT_EQ(textfield_->GetSelectedText(), string);
1352 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1353 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1354 EXPECT_TRUE(custom_formats.empty());
1356 // Drop " worl" after "h".
1357 EXPECT_TRUE(textfield_->CanDrop(data));
1358 gfx::Point drop_point(GetCursorPositionX(1), 0);
1359 ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
1360 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1361 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1362 EXPECT_STR_EQ("h worlellod", textfield_->text());
1363 textfield_->OnDragDone();
1365 // Undo/Redo the drag&drop change.
1366 SendKeyEvent(ui::VKEY_Z, false, true);
1367 EXPECT_STR_EQ("hello world", textfield_->text());
1368 SendKeyEvent(ui::VKEY_Z, false, true);
1369 EXPECT_STR_EQ("", textfield_->text());
1370 SendKeyEvent(ui::VKEY_Z, false, true);
1371 EXPECT_STR_EQ("", textfield_->text());
1372 SendKeyEvent(ui::VKEY_Z, true, true);
1373 EXPECT_STR_EQ("hello world", textfield_->text());
1374 SendKeyEvent(ui::VKEY_Z, true, true);
1375 EXPECT_STR_EQ("h worlellod", textfield_->text());
1376 SendKeyEvent(ui::VKEY_Z, true, true);
1377 EXPECT_STR_EQ("h worlellod", textfield_->text());
1380 TEST_F(TextfieldTest, DragAndDrop_Canceled) {
1381 InitTextfield();
1382 textfield_->SetText(ASCIIToUTF16("hello world"));
1384 // Start dragging "worl".
1385 textfield_->SelectRange(gfx::Range(6, 10));
1386 gfx::Point point(GetCursorPositionX(8), 0);
1387 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
1388 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1389 ui::EF_LEFT_MOUSE_BUTTON);
1390 textfield_->OnMousePressed(click);
1391 ui::OSExchangeData data;
1392 textfield_->WriteDragDataForView(NULL, click.location(), &data);
1393 EXPECT_TRUE(textfield_->CanDrop(data));
1394 // Drag the text over somewhere valid, outside the current selection.
1395 gfx::Point drop_point(GetCursorPositionX(2), 0);
1396 ui::DropTargetEvent drop(data, drop_point, drop_point,
1397 ui::DragDropTypes::DRAG_MOVE);
1398 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop));
1399 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1400 gfx::Point drag_point(GetCursorPositionX(9), 0);
1401 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point,
1402 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1403 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point,
1404 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1405 ui::EF_LEFT_MOUSE_BUTTON);
1406 textfield_->OnMouseDragged(drag);
1407 textfield_->OnMouseReleased(release);
1408 textfield_->OnDragDone();
1409 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text());
1412 TEST_F(TextfieldTest, ReadOnlyTest) {
1413 InitTextfield();
1414 textfield_->SetText(ASCIIToUTF16("read only"));
1415 textfield_->SetReadOnly(true);
1416 EXPECT_TRUE(textfield_->enabled());
1417 EXPECT_TRUE(textfield_->IsFocusable());
1419 bool shift = false;
1420 SendHomeEvent(shift);
1421 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1422 SendEndEvent(shift);
1423 EXPECT_EQ(9U, textfield_->GetCursorPosition());
1425 SendKeyEvent(ui::VKEY_LEFT, shift, false);
1426 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1427 SendWordEvent(ui::VKEY_LEFT, shift);
1428 EXPECT_EQ(5U, textfield_->GetCursorPosition());
1429 shift = true;
1430 SendWordEvent(ui::VKEY_LEFT, shift);
1431 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1432 EXPECT_STR_EQ("read ", textfield_->GetSelectedText());
1433 textfield_->SelectAll(false);
1434 EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
1436 // Cut should be disabled.
1437 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1438 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1439 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1440 SendKeyEvent(ui::VKEY_X, false, true);
1441 SendAlternateCut();
1442 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1443 EXPECT_STR_EQ("read only", textfield_->text());
1445 // Paste should be disabled.
1446 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1447 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1448 SendKeyEvent(ui::VKEY_V, false, true);
1449 SendAlternatePaste();
1450 EXPECT_STR_EQ("read only", textfield_->text());
1452 // Copy should work normally.
1453 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1454 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1455 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1456 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1457 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1458 SendKeyEvent(ui::VKEY_C, false, true);
1459 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1460 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1461 SendAlternateCopy();
1462 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1464 // SetText should work even in read only mode.
1465 textfield_->SetText(ASCIIToUTF16(" four five six "));
1466 EXPECT_STR_EQ(" four five six ", textfield_->text());
1468 textfield_->SelectAll(false);
1469 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1471 // Text field is unmodifiable and selection shouldn't change.
1472 SendKeyEvent(ui::VKEY_DELETE);
1473 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1474 SendKeyEvent(ui::VKEY_BACK);
1475 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1476 SendKeyEvent(ui::VKEY_T);
1477 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1480 TEST_F(TextfieldTest, TextInputClientTest) {
1481 InitTextfield();
1482 ui::TextInputClient* client = textfield_;
1483 EXPECT_TRUE(client);
1484 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType());
1486 textfield_->SetText(ASCIIToUTF16("0123456789"));
1487 gfx::Range range;
1488 EXPECT_TRUE(client->GetTextRange(&range));
1489 EXPECT_EQ(0U, range.start());
1490 EXPECT_EQ(10U, range.end());
1492 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4)));
1493 EXPECT_TRUE(client->GetSelectionRange(&range));
1494 EXPECT_EQ(gfx::Range(1, 4), range);
1496 base::string16 substring;
1497 EXPECT_TRUE(client->GetTextFromRange(range, &substring));
1498 EXPECT_STR_EQ("123", substring);
1500 EXPECT_TRUE(client->DeleteRange(range));
1501 EXPECT_STR_EQ("0456789", textfield_->text());
1503 ui::CompositionText composition;
1504 composition.text = UTF8ToUTF16("321");
1505 // Set composition through input method.
1506 input_method_->Clear();
1507 input_method_->SetCompositionTextForNextKey(composition);
1508 textfield_->clear();
1510 on_before_user_action_ = on_after_user_action_ = 0;
1512 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1513 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1514 // whenever it has a test composition). However, on Mac, it can't be a letter
1515 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1516 // and don't have a meaningful ui::KeyEvent that would trigger
1517 // DispatchKeyEvent().
1518 SendKeyEvent(ui::VKEY_RETURN);
1520 EXPECT_TRUE(textfield_->key_received());
1521 EXPECT_FALSE(textfield_->key_handled());
1522 EXPECT_TRUE(client->HasCompositionText());
1523 EXPECT_TRUE(client->GetCompositionTextRange(&range));
1524 EXPECT_STR_EQ("0321456789", textfield_->text());
1525 EXPECT_EQ(gfx::Range(1, 4), range);
1526 EXPECT_EQ(1, on_before_user_action_);
1527 EXPECT_EQ(1, on_after_user_action_);
1529 input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
1530 on_before_user_action_ = on_after_user_action_ = 0;
1531 textfield_->clear();
1532 SendKeyEvent(ui::VKEY_RETURN);
1533 EXPECT_TRUE(textfield_->key_received());
1534 EXPECT_FALSE(textfield_->key_handled());
1535 EXPECT_FALSE(client->HasCompositionText());
1536 EXPECT_FALSE(input_method_->cancel_composition_called());
1537 EXPECT_STR_EQ("0123456789", textfield_->text());
1538 EXPECT_EQ(1, on_before_user_action_);
1539 EXPECT_EQ(1, on_after_user_action_);
1541 input_method_->Clear();
1542 input_method_->SetCompositionTextForNextKey(composition);
1543 textfield_->clear();
1544 SendKeyEvent(ui::VKEY_RETURN);
1545 EXPECT_TRUE(client->HasCompositionText());
1546 EXPECT_STR_EQ("0123321456789", textfield_->text());
1548 on_before_user_action_ = on_after_user_action_ = 0;
1549 textfield_->clear();
1550 SendKeyEvent(ui::VKEY_RIGHT);
1551 EXPECT_FALSE(client->HasCompositionText());
1552 EXPECT_TRUE(input_method_->cancel_composition_called());
1553 EXPECT_TRUE(textfield_->key_received());
1554 EXPECT_TRUE(textfield_->key_handled());
1555 EXPECT_STR_EQ("0123321456789", textfield_->text());
1556 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1557 EXPECT_EQ(1, on_before_user_action_);
1558 EXPECT_EQ(1, on_after_user_action_);
1560 textfield_->clear();
1561 textfield_->SetText(ASCIIToUTF16("0123456789"));
1562 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5)));
1563 client->ExtendSelectionAndDelete(4, 2);
1564 EXPECT_STR_EQ("0789", textfield_->text());
1566 // On{Before,After}UserAction should be called by whatever user action
1567 // triggers clearing or setting a selection if appropriate.
1568 on_before_user_action_ = on_after_user_action_ = 0;
1569 textfield_->clear();
1570 textfield_->ClearSelection();
1571 textfield_->SelectAll(false);
1572 EXPECT_EQ(0, on_before_user_action_);
1573 EXPECT_EQ(0, on_after_user_action_);
1575 input_method_->Clear();
1577 // Changing the Textfield to readonly shouldn't change the input client, since
1578 // it's still required for selections and clipboard copy.
1579 ui::TextInputClient* text_input_client = textfield_;
1580 EXPECT_TRUE(text_input_client);
1581 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1582 textfield_->SetReadOnly(true);
1583 EXPECT_TRUE(input_method_->text_input_type_changed());
1584 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1586 input_method_->Clear();
1587 textfield_->SetReadOnly(false);
1588 EXPECT_TRUE(input_method_->text_input_type_changed());
1589 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1591 input_method_->Clear();
1592 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1593 EXPECT_TRUE(input_method_->text_input_type_changed());
1596 TEST_F(TextfieldTest, UndoRedoTest) {
1597 InitTextfield();
1598 SendKeyEvent(ui::VKEY_A);
1599 EXPECT_STR_EQ("a", textfield_->text());
1600 SendKeyEvent(ui::VKEY_Z, false, true);
1601 EXPECT_STR_EQ("", textfield_->text());
1602 SendKeyEvent(ui::VKEY_Z, false, true);
1603 EXPECT_STR_EQ("", textfield_->text());
1604 SendKeyEvent(ui::VKEY_Z, true, true);
1605 EXPECT_STR_EQ("a", textfield_->text());
1606 SendKeyEvent(ui::VKEY_Z, true, true);
1607 EXPECT_STR_EQ("a", textfield_->text());
1609 // AppendText
1610 textfield_->AppendText(ASCIIToUTF16("b"));
1611 last_contents_.clear(); // AppendText doesn't call ContentsChanged.
1612 EXPECT_STR_EQ("ab", textfield_->text());
1613 SendKeyEvent(ui::VKEY_Z, false, true);
1614 EXPECT_STR_EQ("a", textfield_->text());
1615 SendKeyEvent(ui::VKEY_Z, true, true);
1616 EXPECT_STR_EQ("ab", textfield_->text());
1618 // SetText
1619 SendKeyEvent(ui::VKEY_C);
1620 // Undo'ing append moves the cursor to the end for now.
1621 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1622 EXPECT_STR_EQ("abc", textfield_->text());
1623 textfield_->SetText(ASCIIToUTF16("abc"));
1624 EXPECT_STR_EQ("abc", textfield_->text());
1625 SendKeyEvent(ui::VKEY_Z, false, true);
1626 EXPECT_STR_EQ("ab", textfield_->text());
1627 SendKeyEvent(ui::VKEY_Z, true, true);
1628 EXPECT_STR_EQ("abc", textfield_->text());
1629 SendKeyEvent(ui::VKEY_Z, true, true);
1630 EXPECT_STR_EQ("abc", textfield_->text());
1631 textfield_->SetText(ASCIIToUTF16("123"));
1632 textfield_->SetText(ASCIIToUTF16("123"));
1633 EXPECT_STR_EQ("123", textfield_->text());
1634 SendKeyEvent(ui::VKEY_END, false, false);
1635 SendKeyEvent(ui::VKEY_4, false, false);
1636 EXPECT_STR_EQ("1234", textfield_->text());
1637 last_contents_.clear();
1638 SendKeyEvent(ui::VKEY_Z, false, true);
1639 EXPECT_STR_EQ("123", textfield_->text());
1640 SendKeyEvent(ui::VKEY_Z, false, true);
1641 // the insert edit "c" and set edit "123" are merged to single edit,
1642 // so text becomes "ab" after undo.
1643 EXPECT_STR_EQ("ab", textfield_->text());
1644 SendKeyEvent(ui::VKEY_Z, false, true);
1645 EXPECT_STR_EQ("a", textfield_->text());
1646 SendKeyEvent(ui::VKEY_Z, true, true);
1647 EXPECT_STR_EQ("ab", textfield_->text());
1648 SendKeyEvent(ui::VKEY_Z, true, true);
1649 EXPECT_STR_EQ("123", textfield_->text());
1650 SendKeyEvent(ui::VKEY_Z, true, true);
1651 EXPECT_STR_EQ("1234", textfield_->text());
1653 // Undoing to the same text shouldn't call ContentsChanged.
1654 SendKeyEvent(ui::VKEY_A, false, true); // select all
1655 SendKeyEvent(ui::VKEY_A);
1656 EXPECT_STR_EQ("a", textfield_->text());
1657 SendKeyEvent(ui::VKEY_B);
1658 SendKeyEvent(ui::VKEY_C);
1659 EXPECT_STR_EQ("abc", textfield_->text());
1660 SendKeyEvent(ui::VKEY_Z, false, true);
1661 EXPECT_STR_EQ("1234", textfield_->text());
1662 SendKeyEvent(ui::VKEY_Z, true, true);
1663 EXPECT_STR_EQ("abc", textfield_->text());
1665 // Delete/Backspace
1666 SendKeyEvent(ui::VKEY_BACK);
1667 EXPECT_STR_EQ("ab", textfield_->text());
1668 SendHomeEvent(false);
1669 SendKeyEvent(ui::VKEY_DELETE);
1670 EXPECT_STR_EQ("b", textfield_->text());
1671 SendKeyEvent(ui::VKEY_A, false, true);
1672 SendKeyEvent(ui::VKEY_DELETE);
1673 EXPECT_STR_EQ("", textfield_->text());
1674 SendKeyEvent(ui::VKEY_Z, false, true);
1675 EXPECT_STR_EQ("b", textfield_->text());
1676 SendKeyEvent(ui::VKEY_Z, false, true);
1677 EXPECT_STR_EQ("ab", textfield_->text());
1678 SendKeyEvent(ui::VKEY_Z, false, true);
1679 EXPECT_STR_EQ("abc", textfield_->text());
1680 SendKeyEvent(ui::VKEY_Z, true, true);
1681 EXPECT_STR_EQ("ab", textfield_->text());
1682 SendKeyEvent(ui::VKEY_Z, true, true);
1683 EXPECT_STR_EQ("b", textfield_->text());
1684 SendKeyEvent(ui::VKEY_Z, true, true);
1685 EXPECT_STR_EQ("", textfield_->text());
1686 SendKeyEvent(ui::VKEY_Z, true, true);
1687 EXPECT_STR_EQ("", textfield_->text());
1690 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1691 // that is bound to "Show full history", so is not mapped as an editing
1692 // command. So, on Mac, send Cmd+Shift+Z.
1693 #if !defined(OS_MACOSX)
1695 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1696 TEST_F(TextfieldTest, RedoWithCtrlY) {
1697 InitTextfield();
1698 SendKeyEvent(ui::VKEY_A);
1699 EXPECT_STR_EQ("a", textfield_->text());
1700 SendKeyEvent(ui::VKEY_Z, false, true);
1701 EXPECT_STR_EQ("", textfield_->text());
1702 SendKeyEvent(ui::VKEY_Y, false, true);
1703 EXPECT_STR_EQ("a", textfield_->text());
1704 SendKeyEvent(ui::VKEY_Z, false, true);
1705 EXPECT_STR_EQ("", textfield_->text());
1706 SendKeyEvent(ui::VKEY_Z, true, true);
1707 EXPECT_STR_EQ("a", textfield_->text());
1710 #endif // !defined(OS_MACOSX)
1712 TEST_F(TextfieldTest, CutCopyPaste) {
1713 InitTextfield();
1715 // Ensure IDS_APP_CUT cuts.
1716 textfield_->SetText(ASCIIToUTF16("123"));
1717 textfield_->SelectAll(false);
1718 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1719 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1720 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1721 EXPECT_STR_EQ("", textfield_->text());
1722 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1724 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1725 textfield_->SetText(ASCIIToUTF16("456"));
1726 textfield_->SelectAll(false);
1727 SendKeyEvent(ui::VKEY_X, true, false, true, false);
1728 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1729 EXPECT_STR_EQ("456", textfield_->text());
1730 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1731 SendKeyEvent(ui::VKEY_X, false, true);
1732 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1733 EXPECT_STR_EQ("", textfield_->text());
1734 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1736 // Ensure [Shift]+[Delete] cuts.
1737 textfield_->SetText(ASCIIToUTF16("123"));
1738 textfield_->SelectAll(false);
1739 SendAlternateCut();
1740 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1741 EXPECT_STR_EQ("", textfield_->text());
1742 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1744 // Ensure IDS_APP_COPY copies.
1745 textfield_->SetText(ASCIIToUTF16("789"));
1746 textfield_->SelectAll(false);
1747 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1748 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1749 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1750 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1752 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1753 textfield_->SetText(ASCIIToUTF16("012"));
1754 textfield_->SelectAll(false);
1755 SendKeyEvent(ui::VKEY_C, true, false, true, false);
1756 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1757 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1758 SendKeyEvent(ui::VKEY_C, false, true);
1759 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1760 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1762 // Ensure [Ctrl]+[Insert] copies.
1763 textfield_->SetText(ASCIIToUTF16("345"));
1764 textfield_->SelectAll(false);
1765 SendAlternateCopy();
1766 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1767 EXPECT_STR_EQ("345", textfield_->text());
1768 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1770 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1771 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1772 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
1773 textfield_->SetText(base::string16());
1774 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1775 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1776 EXPECT_STR_EQ("abc", textfield_->text());
1777 SendKeyEvent(ui::VKEY_V, false, true);
1778 EXPECT_STR_EQ("abcabc", textfield_->text());
1779 SendAlternatePaste();
1780 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1781 SendKeyEvent(ui::VKEY_V, true, false, true, false);
1782 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1784 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1785 textfield_->SelectAll(false);
1786 SendKeyEvent(ui::VKEY_INSERT, true, true);
1787 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1788 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1789 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1792 TEST_F(TextfieldTest, OvertypeMode) {
1793 InitTextfield();
1794 // Overtype mode should be disabled (no-op [Insert]).
1795 textfield_->SetText(ASCIIToUTF16("2"));
1796 const bool shift = false;
1797 SendHomeEvent(shift);
1798 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1799 // since there is no overtype on toolkit-views, the behavior happens to match.
1800 // However, there's no enable-overtype equivalent key combination on OSX.
1801 SendKeyEvent(ui::VKEY_INSERT);
1802 SendKeyEvent(ui::VKEY_1, false, false);
1803 EXPECT_STR_EQ("12", textfield_->text());
1806 TEST_F(TextfieldTest, TextCursorDisplayTest) {
1807 InitTextfield();
1808 // LTR-RTL string in LTR context.
1809 SendKeyEvent('a');
1810 EXPECT_STR_EQ("a", textfield_->text());
1811 int x = GetCursorBounds().x();
1812 int prev_x = x;
1814 SendKeyEvent('b');
1815 EXPECT_STR_EQ("ab", textfield_->text());
1816 x = GetCursorBounds().x();
1817 EXPECT_LT(prev_x, x);
1818 prev_x = x;
1820 SendKeyEvent(0x05E1);
1821 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1822 x = GetCursorBounds().x();
1823 EXPECT_GE(1, std::abs(x - prev_x));
1825 SendKeyEvent(0x05E2);
1826 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1827 x = GetCursorBounds().x();
1828 EXPECT_GE(1, std::abs(x - prev_x));
1830 // Clear text.
1831 SendKeyEvent(ui::VKEY_A, false, true);
1832 SendKeyEvent(ui::VKEY_DELETE);
1834 // RTL-LTR string in LTR context.
1835 SendKeyEvent(0x05E1);
1836 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1837 x = GetCursorBounds().x();
1838 EXPECT_EQ(GetDisplayRect().x(), x);
1839 prev_x = x;
1841 SendKeyEvent(0x05E2);
1842 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1843 x = GetCursorBounds().x();
1844 EXPECT_GE(1, std::abs(x - prev_x));
1846 SendKeyEvent('a');
1847 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1848 x = GetCursorBounds().x();
1849 EXPECT_LT(prev_x, x);
1850 prev_x = x;
1852 SendKeyEvent('b');
1853 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1854 x = GetCursorBounds().x();
1855 EXPECT_LT(prev_x, x);
1858 TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
1859 std::string locale = l10n_util::GetApplicationLocale("");
1860 base::i18n::SetICUDefaultLocale("he");
1862 InitTextfield();
1863 // LTR-RTL string in RTL context.
1864 SendKeyEvent('a');
1865 EXPECT_STR_EQ("a", textfield_->text());
1866 int x = GetCursorBounds().x();
1867 EXPECT_EQ(GetDisplayRect().right() - 1, x);
1868 int prev_x = x;
1870 SendKeyEvent('b');
1871 EXPECT_STR_EQ("ab", textfield_->text());
1872 x = GetCursorBounds().x();
1873 EXPECT_GE(1, std::abs(x - prev_x));
1875 SendKeyEvent(0x05E1);
1876 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1877 x = GetCursorBounds().x();
1878 EXPECT_GT(prev_x, x);
1879 prev_x = x;
1881 SendKeyEvent(0x05E2);
1882 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1883 x = GetCursorBounds().x();
1884 EXPECT_GT(prev_x, x);
1886 // Clear text.
1887 SendKeyEvent(ui::VKEY_A, false, true);
1888 SendKeyEvent(ui::VKEY_DELETE);
1890 // RTL-LTR string in RTL context.
1891 SendKeyEvent(0x05E1);
1892 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1893 x = GetCursorBounds().x();
1894 prev_x = x;
1896 SendKeyEvent(0x05E2);
1897 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1898 x = GetCursorBounds().x();
1899 EXPECT_GT(prev_x, x);
1900 prev_x = x;
1902 SendKeyEvent('a');
1903 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1904 x = GetCursorBounds().x();
1905 EXPECT_GE(1, std::abs(x - prev_x));
1906 prev_x = x;
1908 SendKeyEvent('b');
1909 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1910 x = GetCursorBounds().x();
1911 EXPECT_GE(1, std::abs(x - prev_x));
1913 // Reset locale.
1914 base::i18n::SetICUDefaultLocale(locale);
1917 TEST_F(TextfieldTest, HitInsideTextAreaTest) {
1918 InitTextfield();
1919 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1920 std::vector<gfx::Rect> cursor_bounds;
1922 // Save each cursor bound.
1923 gfx::SelectionModel sel(0, gfx::CURSOR_FORWARD);
1924 cursor_bounds.push_back(GetCursorBounds(sel));
1926 sel = gfx::SelectionModel(1, gfx::CURSOR_BACKWARD);
1927 gfx::Rect bound = GetCursorBounds(sel);
1928 sel = gfx::SelectionModel(1, gfx::CURSOR_FORWARD);
1929 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1930 cursor_bounds.push_back(bound);
1932 // Check that a cursor at the end of the Latin portion of the text is at the
1933 // same position as a cursor placed at the end of the RTL Hebrew portion.
1934 sel = gfx::SelectionModel(2, gfx::CURSOR_BACKWARD);
1935 bound = GetCursorBounds(sel);
1936 sel = gfx::SelectionModel(4, gfx::CURSOR_BACKWARD);
1937 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1938 cursor_bounds.push_back(bound);
1940 sel = gfx::SelectionModel(3, gfx::CURSOR_BACKWARD);
1941 bound = GetCursorBounds(sel);
1942 sel = gfx::SelectionModel(3, gfx::CURSOR_FORWARD);
1943 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1944 cursor_bounds.push_back(bound);
1946 sel = gfx::SelectionModel(2, gfx::CURSOR_FORWARD);
1947 bound = GetCursorBounds(sel);
1948 sel = gfx::SelectionModel(4, gfx::CURSOR_FORWARD);
1949 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1950 cursor_bounds.push_back(bound);
1952 // Expected cursor position when clicking left and right of each character.
1953 size_t cursor_pos_expected[] = {0, 1, 1, 2, 4, 3, 3, 2};
1955 int index = 0;
1956 for (int i = 0; i < static_cast<int>(cursor_bounds.size() - 1); ++i) {
1957 int half_width = (cursor_bounds[i + 1].x() - cursor_bounds[i].x()) / 2;
1958 MouseClick(cursor_bounds[i], half_width / 2);
1959 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1961 // To avoid trigger double click. Not using sleep() since it takes longer
1962 // for the test to run if using sleep().
1963 NonClientMouseClick();
1965 MouseClick(cursor_bounds[i + 1], - (half_width / 2));
1966 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1968 NonClientMouseClick();
1972 TEST_F(TextfieldTest, HitOutsideTextAreaTest) {
1973 InitTextfield();
1975 // LTR-RTL string in LTR context.
1976 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1978 const bool shift = false;
1979 SendHomeEvent(shift);
1980 gfx::Rect bound = GetCursorBounds();
1981 MouseClick(bound, -10);
1982 EXPECT_EQ(bound, GetCursorBounds());
1984 SendEndEvent(shift);
1985 bound = GetCursorBounds();
1986 MouseClick(bound, 10);
1987 EXPECT_EQ(bound, GetCursorBounds());
1989 NonClientMouseClick();
1991 // RTL-LTR string in LTR context.
1992 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
1994 SendHomeEvent(shift);
1995 bound = GetCursorBounds();
1996 MouseClick(bound, 10);
1997 EXPECT_EQ(bound, GetCursorBounds());
1999 SendEndEvent(shift);
2000 bound = GetCursorBounds();
2001 MouseClick(bound, -10);
2002 EXPECT_EQ(bound, GetCursorBounds());
2005 TEST_F(TextfieldTest, HitOutsideTextAreaInRTLTest) {
2006 std::string locale = l10n_util::GetApplicationLocale("");
2007 base::i18n::SetICUDefaultLocale("he");
2009 InitTextfield();
2011 // RTL-LTR string in RTL context.
2012 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
2013 const bool shift = false;
2014 SendHomeEvent(shift);
2015 gfx::Rect bound = GetCursorBounds();
2016 MouseClick(bound, 10);
2017 EXPECT_EQ(bound, GetCursorBounds());
2019 SendEndEvent(shift);
2020 bound = GetCursorBounds();
2021 MouseClick(bound, -10);
2022 EXPECT_EQ(bound, GetCursorBounds());
2024 NonClientMouseClick();
2026 // LTR-RTL string in RTL context.
2027 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
2028 SendHomeEvent(shift);
2029 bound = GetCursorBounds();
2030 MouseClick(bound, -10);
2031 EXPECT_EQ(bound, GetCursorBounds());
2033 SendEndEvent(shift);
2034 bound = GetCursorBounds();
2035 MouseClick(bound, 10);
2036 EXPECT_EQ(bound, GetCursorBounds());
2038 // Reset locale.
2039 base::i18n::SetICUDefaultLocale(locale);
2042 TEST_F(TextfieldTest, OverflowTest) {
2043 InitTextfield();
2045 base::string16 str;
2046 for (int i = 0; i < 500; ++i)
2047 SendKeyEvent('a');
2048 SendKeyEvent(kHebrewLetterSamekh);
2049 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2051 // Test mouse pointing.
2052 MouseClick(GetCursorBounds(), -1);
2053 EXPECT_EQ(500U, textfield_->GetCursorPosition());
2055 // Clear text.
2056 SendKeyEvent(ui::VKEY_A, false, true);
2057 SendKeyEvent(ui::VKEY_DELETE);
2059 for (int i = 0; i < 500; ++i)
2060 SendKeyEvent(kHebrewLetterSamekh);
2061 SendKeyEvent('a');
2062 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2064 MouseClick(GetCursorBounds(), -1);
2065 EXPECT_EQ(501U, textfield_->GetCursorPosition());
2068 TEST_F(TextfieldTest, OverflowInRTLTest) {
2069 std::string locale = l10n_util::GetApplicationLocale("");
2070 base::i18n::SetICUDefaultLocale("he");
2072 InitTextfield();
2074 base::string16 str;
2075 for (int i = 0; i < 500; ++i)
2076 SendKeyEvent('a');
2077 SendKeyEvent(kHebrewLetterSamekh);
2078 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2080 MouseClick(GetCursorBounds(), 1);
2081 EXPECT_EQ(501U, textfield_->GetCursorPosition());
2083 // Clear text.
2084 SendKeyEvent(ui::VKEY_A, false, true);
2085 SendKeyEvent(ui::VKEY_DELETE);
2087 for (int i = 0; i < 500; ++i)
2088 SendKeyEvent(kHebrewLetterSamekh);
2089 SendKeyEvent('a');
2090 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2092 MouseClick(GetCursorBounds(), 1);
2093 EXPECT_EQ(500U, textfield_->GetCursorPosition());
2095 // Reset locale.
2096 base::i18n::SetICUDefaultLocale(locale);
2099 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) {
2100 InitTextfield();
2101 ui::CompositionText composition;
2102 composition.text = UTF8ToUTF16("abc123");
2103 const uint32 char_count = static_cast<uint32>(composition.text.length());
2104 ui::TextInputClient* client = textfield_;
2106 // Compare the composition character bounds with surrounding cursor bounds.
2107 for (uint32 i = 0; i < char_count; ++i) {
2108 composition.selection = gfx::Range(i);
2109 client->SetCompositionText(composition);
2110 gfx::Point cursor_origin = GetCursorBounds().origin();
2111 views::View::ConvertPointToScreen(textfield_, &cursor_origin);
2113 composition.selection = gfx::Range(i + 1);
2114 client->SetCompositionText(composition);
2115 gfx::Point next_cursor_bottom_left = GetCursorBounds().bottom_left();
2116 views::View::ConvertPointToScreen(textfield_, &next_cursor_bottom_left);
2118 gfx::Rect character;
2119 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &character));
2120 EXPECT_EQ(character.origin(), cursor_origin) << " i=" << i;
2121 EXPECT_EQ(character.bottom_right(), next_cursor_bottom_left) << " i=" << i;
2124 // Return false if the index is out of range.
2125 gfx::Rect rect;
2126 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count, &rect));
2127 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 1, &rect));
2128 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect));
2131 TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
2132 InitTextfield();
2134 const base::char16 kUtf16Chars[] = {
2135 // U+0020 SPACE
2136 0x0020,
2137 // U+1F408 (CAT) as surrogate pair
2138 0xd83d, 0xdc08,
2139 // U+5642 as Ideographic Variation Sequences
2140 0x5642, 0xDB40, 0xDD00,
2141 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
2142 0x260E, 0xFE0F,
2143 // U+0020 SPACE
2144 0x0020,
2146 const size_t kUtf16CharsCount = arraysize(kUtf16Chars);
2148 ui::CompositionText composition;
2149 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount);
2150 ui::TextInputClient* client = textfield_;
2151 client->SetCompositionText(composition);
2153 // Make sure GetCompositionCharacterBounds never fails for index.
2154 gfx::Rect rects[kUtf16CharsCount];
2155 gfx::Rect prev_cursor = GetCursorBounds();
2156 for (uint32 i = 0; i < kUtf16CharsCount; ++i)
2157 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i]));
2159 // Here we might expect the following results but it actually depends on how
2160 // Uniscribe or HarfBuzz treats them with given font.
2161 // - rects[1] == rects[2]
2162 // - rects[3] == rects[4] == rects[5]
2163 // - rects[6] == rects[7]
2166 // The word we select by double clicking should remain selected regardless of
2167 // where we drag the mouse afterwards without releasing the left button.
2168 TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
2169 InitTextfield();
2171 textfield_->SetText(ASCIIToUTF16("abc def ghi"));
2173 textfield_->SelectRange(gfx::Range(5, 5));
2174 const gfx::Rect middle_cursor = GetCursorBounds();
2175 textfield_->SelectRange(gfx::Range(0, 0));
2176 const gfx::Point beginning = GetCursorBounds().origin();
2178 // Double click, but do not release the left button.
2179 MouseClick(middle_cursor, 0);
2180 const gfx::Point middle(middle_cursor.x(),
2181 middle_cursor.y() + middle_cursor.height() / 2);
2182 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle,
2183 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2184 ui::EF_LEFT_MOUSE_BUTTON);
2185 textfield_->OnMousePressed(press_event);
2186 EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange());
2188 // Drag the mouse to the beginning of the textfield.
2189 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning,
2190 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
2191 textfield_->OnMouseDragged(drag_event);
2192 EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
2195 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2196 // flaky: http://crbug.com/396477
2197 TEST_F(TextfieldTest, DISABLED_SelectionClipboard) {
2198 InitTextfield();
2199 textfield_->SetText(ASCIIToUTF16("0123"));
2200 gfx::Point point_1(GetCursorPositionX(1), 0);
2201 gfx::Point point_2(GetCursorPositionX(2), 0);
2202 gfx::Point point_3(GetCursorPositionX(3), 0);
2203 gfx::Point point_4(GetCursorPositionX(4), 0);
2205 // Text selected by the mouse should be placed on the selection clipboard.
2206 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
2207 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2208 ui::EF_LEFT_MOUSE_BUTTON);
2209 textfield_->OnMousePressed(press);
2210 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
2211 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2212 ui::EF_LEFT_MOUSE_BUTTON);
2213 textfield_->OnMouseDragged(drag);
2214 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
2215 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2216 ui::EF_LEFT_MOUSE_BUTTON);
2217 textfield_->OnMouseReleased(release);
2218 EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
2219 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2221 // Select-all should update the selection clipboard.
2222 SendKeyEvent(ui::VKEY_A, false, true);
2223 EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
2224 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2225 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2227 // Shift-click selection modifications should update the clipboard.
2228 NonClientMouseClick();
2229 ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
2230 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2231 ui::EF_LEFT_MOUSE_BUTTON);
2232 press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
2233 #if defined(USE_X11)
2234 ui::UpdateX11EventForFlags(&press_2);
2235 #endif
2236 textfield_->OnMousePressed(press_2);
2237 ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
2238 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2239 ui::EF_LEFT_MOUSE_BUTTON);
2240 textfield_->OnMouseReleased(release_2);
2241 EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
2242 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2243 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2245 // Shift-Left/Right should update the selection clipboard.
2246 SendKeyEvent(ui::VKEY_RIGHT, true, false);
2247 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2248 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2249 SendKeyEvent(ui::VKEY_LEFT, true, false);
2250 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2251 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2252 SendKeyEvent(ui::VKEY_RIGHT, true, true);
2253 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2254 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2256 // Moving the cursor without a selection should not change the clipboard.
2257 SendKeyEvent(ui::VKEY_LEFT, false, false);
2258 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
2259 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2260 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2262 // Middle clicking should paste at the mouse (not cursor) location.
2263 // The cursor should be placed at the end of the pasted text.
2264 ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
2265 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON,
2266 ui::EF_MIDDLE_MOUSE_BUTTON);
2267 textfield_->OnMousePressed(middle);
2268 EXPECT_STR_EQ("01230123", textfield_->text());
2269 EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
2270 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2272 // Middle clicking on an unfocused textfield should focus it and paste.
2273 textfield_->GetFocusManager()->ClearFocus();
2274 EXPECT_FALSE(textfield_->HasFocus());
2275 textfield_->OnMousePressed(middle);
2276 EXPECT_TRUE(textfield_->HasFocus());
2277 EXPECT_STR_EQ("012301230123", textfield_->text());
2278 EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
2279 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2281 // Middle clicking with an empty selection clipboard should still focus.
2282 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, std::string());
2283 textfield_->GetFocusManager()->ClearFocus();
2284 EXPECT_FALSE(textfield_->HasFocus());
2285 textfield_->OnMousePressed(middle);
2286 EXPECT_TRUE(textfield_->HasFocus());
2287 EXPECT_STR_EQ("012301230123", textfield_->text());
2288 EXPECT_EQ(gfx::Range(4, 4), textfield_->GetSelectedRange());
2289 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
2291 // Middle clicking in the selection should clear the clipboard and selection.
2292 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
2293 textfield_->SelectRange(gfx::Range(2, 6));
2294 textfield_->OnMousePressed(middle);
2295 EXPECT_STR_EQ("012301230123", textfield_->text());
2296 EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
2297 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
2299 // Double and triple clicking should update the clipboard contents.
2300 textfield_->SetText(ASCIIToUTF16("ab cd ef"));
2301 gfx::Point word(GetCursorPositionX(4), 0);
2302 ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
2303 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2304 ui::EF_LEFT_MOUSE_BUTTON);
2305 textfield_->OnMousePressed(press_word);
2306 ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
2307 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2308 ui::EF_LEFT_MOUSE_BUTTON);
2309 textfield_->OnMouseReleased(release_word);
2310 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
2311 ui::EventTimeForNow(),
2312 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
2313 ui::EF_LEFT_MOUSE_BUTTON);
2314 textfield_->OnMousePressed(double_click);
2315 textfield_->OnMouseReleased(release_word);
2316 EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
2317 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2318 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2319 textfield_->OnMousePressed(press_word);
2320 textfield_->OnMouseReleased(release_word);
2321 EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
2322 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2323 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2325 // Selecting a range of text without any user interaction should not change
2326 // the clipboard content.
2327 textfield_->SelectRange(gfx::Range(0, 3));
2328 EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
2329 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2330 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2332 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
2333 textfield_->SelectAll(false);
2334 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2335 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2337 #endif
2339 // Long_Press gesture in Textfield can initiate a drag and drop now.
2340 TEST_F(TextfieldTest, TestLongPressInitiatesDragDrop) {
2341 InitTextfield();
2342 textfield_->SetText(ASCIIToUTF16("Hello string world"));
2344 // Ensure the textfield will provide selected text for drag data.
2345 textfield_->SelectRange(gfx::Range(6, 12));
2346 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
2348 // Enable touch-drag-drop to make long press effective.
2349 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2350 switches::kEnableTouchDragDrop);
2352 // Create a long press event in the selected region should start a drag.
2353 GestureEventForTest long_press(
2354 kStringPoint.x(),
2355 kStringPoint.y(),
2356 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2357 textfield_->OnGestureEvent(&long_press);
2358 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
2359 kStringPoint));
2362 TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
2363 InitTextfield();
2364 textfield_->SetText(UTF8ToUTF16("abc"));
2365 const int old_baseline = textfield_->GetBaseline();
2367 // Set text which may fall back to a font which has taller baseline than
2368 // the default font.
2369 textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2370 const int new_baseline = textfield_->GetBaseline();
2372 // Regardless of the text, the baseline must be the same.
2373 EXPECT_EQ(new_baseline, old_baseline);
2376 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2377 // controller and it does not crash.
2378 TEST_F(TextfieldTest, DestroyingTextfieldFromOnKeyEvent) {
2379 InitTextfield();
2381 // The controller assumes ownership of the textfield.
2382 TextfieldDestroyerController controller(textfield_);
2383 EXPECT_TRUE(controller.target());
2385 // Send a key to trigger OnKeyEvent().
2386 SendKeyEvent(ui::VKEY_RETURN);
2388 EXPECT_FALSE(controller.target());
2391 class TextfieldTouchSelectionTest : public TextfieldTest {
2392 public:
2393 // TextfieldTest:
2394 void SetUp() override {
2395 TextfieldTest::SetUp();
2396 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2397 switches::kEnableTouchEditing);
2400 protected:
2401 // Simulates a complete tap.
2402 void Tap(const gfx::Point& point) {
2403 GestureEventForTest begin(
2404 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
2405 textfield_->OnGestureEvent(&begin);
2407 GestureEventForTest tap_down(
2408 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
2409 textfield_->OnGestureEvent(&tap_down);
2411 GestureEventForTest show_press(
2412 point.x(),
2413 point.y(),
2414 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
2415 textfield_->OnGestureEvent(&show_press);
2417 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2418 tap_details.set_tap_count(1);
2419 GestureEventForTest tap(point.x(), point.y(), tap_details);
2420 textfield_->OnGestureEvent(&tap);
2422 GestureEventForTest end(
2423 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_END));
2424 textfield_->OnGestureEvent(&end);
2429 // Touch selection and dragging currently only works for chromeos.
2430 #if defined(OS_CHROMEOS)
2431 TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
2432 InitTextfield();
2433 textfield_->SetText(ASCIIToUTF16("hello world"));
2434 EXPECT_FALSE(test_api_->touch_selection_controller());
2435 const int x = GetCursorPositionX(2);
2437 // Tapping on the textfield should turn on the TouchSelectionController.
2438 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2439 tap_details.set_tap_count(1);
2440 GestureEventForTest tap(x, 0, tap_details);
2441 textfield_->OnGestureEvent(&tap);
2442 EXPECT_TRUE(test_api_->touch_selection_controller());
2444 // Un-focusing the textfield should reset the TouchSelectionController
2445 textfield_->GetFocusManager()->ClearFocus();
2446 EXPECT_FALSE(test_api_->touch_selection_controller());
2447 textfield_->RequestFocus();
2449 // With touch editing enabled, long press should not show context menu.
2450 // Instead, select word and invoke TouchSelectionController.
2451 GestureEventForTest long_press_1(
2452 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2453 textfield_->OnGestureEvent(&long_press_1);
2454 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2455 EXPECT_TRUE(test_api_->touch_selection_controller());
2456 EXPECT_TRUE(long_press_1.handled());
2458 // With touch drag drop enabled, long pressing in the selected region should
2459 // start a drag and remove TouchSelectionController.
2460 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2461 GestureEventForTest long_press_2(
2462 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2463 textfield_->OnGestureEvent(&long_press_2);
2464 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2465 EXPECT_FALSE(test_api_->touch_selection_controller());
2466 EXPECT_FALSE(long_press_2.handled());
2468 // After disabling touch drag drop, long pressing again in the selection
2469 // region should not do anything.
2470 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2471 switches::kDisableTouchDragDrop);
2472 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2473 GestureEventForTest long_press_3(
2474 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2475 textfield_->OnGestureEvent(&long_press_3);
2476 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2477 EXPECT_FALSE(test_api_->touch_selection_controller());
2478 EXPECT_FALSE(long_press_3.handled());
2480 #endif
2482 TEST_F(TextfieldTouchSelectionTest, TouchSelectionInUnfocusableTextfield) {
2483 InitTextfield();
2484 textfield_->SetText(ASCIIToUTF16("hello world"));
2485 gfx::Point touch_point(GetCursorPositionX(2), 0);
2487 // Disable textfield and tap on it. Touch text selection should not get
2488 // activated.
2489 textfield_->SetEnabled(false);
2490 Tap(touch_point);
2491 EXPECT_FALSE(test_api_->touch_selection_controller());
2492 textfield_->SetEnabled(true);
2494 // Make textfield unfocusable and tap on it. Touch text selection should not
2495 // get activated.
2496 textfield_->SetFocusable(false);
2497 Tap(touch_point);
2498 EXPECT_FALSE(textfield_->HasFocus());
2499 EXPECT_FALSE(test_api_->touch_selection_controller());
2500 textfield_->SetFocusable(true);
2503 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2504 #if defined(OS_MACOSX) && !defined(USE_AURA)
2505 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2506 #else
2507 #define MAYBE_TapOnSelection TapOnSelection
2508 #endif
2510 TEST_F(TextfieldTouchSelectionTest, MAYBE_TapOnSelection) {
2511 InitTextfield();
2512 textfield_->SetText(ASCIIToUTF16("hello world"));
2513 gfx::Range sel_range(2, 7);
2514 gfx::Range tap_range(5, 5);
2515 gfx::Rect tap_rect =
2516 GetCursorBounds(gfx::SelectionModel(tap_range, gfx::CURSOR_FORWARD));
2517 gfx::Point tap_point = tap_rect.CenterPoint();
2519 // Select range |sel_range| and check if touch selection handles are not
2520 // present and correct range is selected.
2521 textfield_->SetSelectionRange(sel_range);
2522 gfx::Range range;
2523 textfield_->GetSelectionRange(&range);
2524 EXPECT_FALSE(test_api_->touch_selection_controller());
2525 EXPECT_EQ(sel_range, range);
2527 // Tap on selection and check if touch selectoin handles are shown, but
2528 // selection range is not modified.
2529 Tap(tap_point);
2530 textfield_->GetSelectionRange(&range);
2531 EXPECT_TRUE(test_api_->touch_selection_controller());
2532 EXPECT_EQ(sel_range, range);
2534 // Tap again on selection and check if touch selection handles are still
2535 // present and selection is changed to a cursor at tap location.
2536 Tap(tap_point);
2537 textfield_->GetSelectionRange(&range);
2538 EXPECT_TRUE(test_api_->touch_selection_controller());
2539 EXPECT_EQ(tap_range, range);
2542 TEST_F(TextfieldTest, AccessiblePasswordTest) {
2543 InitTextfield();
2544 textfield_->SetText(ASCIIToUTF16("password"));
2546 ui::AXViewState state_regular;
2547 textfield_->GetAccessibleState(&state_regular);
2548 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_regular.role);
2549 EXPECT_EQ(ASCIIToUTF16("password"), state_regular.value);
2550 EXPECT_FALSE(state_regular.HasStateFlag(ui::AX_STATE_PROTECTED));
2552 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
2553 ui::AXViewState state_protected;
2554 textfield_->GetAccessibleState(&state_protected);
2555 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role);
2556 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value);
2557 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED));
2560 } // namespace views