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"
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"
43 #include "base/win/windows_version.h"
46 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
47 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
51 #include "ui/events/event_utils.h"
54 #if defined(OS_MACOSX) && !defined(USE_AURA)
55 #include "ui/events/test/event_generator.h"
58 using base::ASCIIToUTF16
;
59 using base::UTF8ToUTF16
;
60 using base::WideToUTF16
;
62 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
66 const base::char16 kHebrewLetterSamekh
= 0x05E1;
68 class MockInputMethod
: public ui::InputMethodBase
{
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.
94 void SetCompositionTextForNextKey(const ui::CompositionText
& composition
);
95 void SetResultTextForNextKey(const base::string16
& result
);
98 // Overridden from InputMethodBase.
99 void OnWillChangeFocusedClient(ui::TextInputClient
* focused_before
,
100 ui::TextInputClient
* focused
) override
;
102 // Clears boolean states defined below.
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
) {
140 *result
= NativeEventResult();
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())
151 bool handled
= !IsTextInputTypeNone() && HasComposition();
154 DCHECK(!key
->is_char());
155 ui::KeyEvent
mock_key(ui::ET_KEY_PRESSED
,
158 DispatchKeyEventPostIME(&mock_key
);
160 DispatchKeyEventPostIME(key
);
163 ui::TextInputClient
* client
= GetTextInputClient();
166 if (result_text_
.length())
167 client
->InsertText(result_text_
);
168 if (composition_
.text
.length())
169 client
->SetCompositionText(composition_
);
171 client
->ClearCompositionText();
172 } else if (key
->type() == ui::ET_KEY_PRESSED
) {
173 base::char16 ch
= key
->GetCharacter();
175 client
->InsertChar(ch
, key
->flags());
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;
196 std::string
MockInputMethod::GetInputLocale() {
200 bool MockInputMethod::IsCandidatePopupOpen() const {
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();
213 void MockInputMethod::Clear() {
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
{
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
);
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.
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;
284 bool key_handled() const { return key_handled_
; }
285 bool key_received() const { return key_received_
; }
287 void clear() { key_received_
= key_handled_
= false; }
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
{
301 GestureEventForTest(int x
, int y
, ui::GestureEventDetails details
)
302 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
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
{
312 explicit TextfieldDestroyerController(views::Textfield
* 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
{
328 scoped_ptr
<views::Textfield
> target_
;
331 base::string16
GetClipboardText(ui::ClipboardType type
) {
333 ui::Clipboard::GetForCurrentThread()->ReadText(type
, &text
);
337 void SetClipboardText(ui::ClipboardType type
, const std::string
& text
) {
338 ui::ScopedClipboardWriter(type
).WriteText(ASCIIToUTF16(text
));
345 class TextfieldTest
: public ViewsTestBase
, public TextfieldController
{
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_
);
360 void TearDown() override
{
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() {
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.
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()));
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)
460 bool TestingNativeCrOs() const {
461 #if defined(OS_CHROMEOS)
465 #endif // defined(OS_CHROMEOS)
469 void SendKeyPress(ui::KeyboardCode key_code
, int flags
) {
470 #if defined(OS_MACOSX) && !defined(USE_AURA)
471 // The Mac EventGenerator hooks in before IME. It sends events first to an
472 // NSResponder, which is necessary to interpret keyboard events into
473 // appropriate editing commands.
474 event_generator_
->PressKey(key_code
, flags
);
476 // TODO(shuchen): making EventGenerator support input method and using
477 // EventGenerator here. crbug.com/512315.
478 ui::KeyEvent
event(ui::ET_KEY_PRESSED
, key_code
, flags
);
479 input_method_
->DispatchKeyEvent(&event
);
483 void SendKeyEvent(ui::KeyboardCode key_code
,
486 bool control_or_command
,
488 bool control
= control_or_command
;
489 bool command
= false;
491 // By default, swap control and command for native events on Mac. This
492 // handles most cases.
493 if (TestingNativeMac())
494 std::swap(control
, command
);
496 int flags
= (alt
? ui::EF_ALT_DOWN
: 0) | (shift
? ui::EF_SHIFT_DOWN
: 0) |
497 (control
? ui::EF_CONTROL_DOWN
: 0) |
498 (command
? ui::EF_COMMAND_DOWN
: 0) |
499 (caps_lock
? ui::EF_CAPS_LOCK_DOWN
: 0);
501 SendKeyPress(key_code
, flags
);
504 void SendKeyEvent(ui::KeyboardCode key_code
,
506 bool control_or_command
) {
507 SendKeyEvent(key_code
, false, shift
, control_or_command
, false);
510 void SendKeyEvent(ui::KeyboardCode key_code
) {
511 SendKeyEvent(key_code
, false, false);
514 void SendKeyEvent(base::char16 ch
) {
516 ui::KeyboardCode code
=
517 ch
== ' ' ? ui::VKEY_SPACE
:
518 static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ ch
- 'a');
521 // For unicode characters, assume they come from IME rather than the
522 // keyboard. So they are dispatched directly to the input method.
523 ui::KeyEvent
event(ch
, ui::VKEY_UNKNOWN
, ui::EF_NONE
);
524 input_method_
->DispatchKeyEvent(&event
);
528 // Sends a platform-specific move (and select) to start of line.
529 void SendHomeEvent(bool shift
) {
530 if (TestingNativeMac()) {
531 // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
532 // default key-binding on Mac.
533 SendKeyEvent(ui::VKEY_LEFT
, shift
/* shift */, true /* command */);
536 SendKeyEvent(ui::VKEY_HOME
, shift
/* shift */, false /* control */);
539 // Sends a platform-specific move (and select) to end of line.
540 void SendEndEvent(bool shift
) {
541 if (TestingNativeMac()) {
542 SendKeyEvent(ui::VKEY_RIGHT
, shift
, true); // Cmd+Right.
545 SendKeyEvent(ui::VKEY_END
, shift
, false);
548 // Sends {delete, move, select} word {forward, backward}.
549 void SendWordEvent(ui::KeyboardCode key
, bool shift
) {
553 if (TestingNativeMac()) {
554 // Use Alt+Left/Right/Backspace on native Mac.
558 SendKeyEvent(key
, alt
, shift
, control
, caps
);
561 // Sends Shift+Delete if supported, otherwise Cmd+X again.
562 void SendAlternateCut() {
563 if (TestingNativeMac())
564 SendKeyEvent(ui::VKEY_X
, false, true);
566 SendKeyEvent(ui::VKEY_DELETE
, true, false);
569 // Sends Ctrl+Insert if supported, otherwise Cmd+C again.
570 void SendAlternateCopy() {
571 if (TestingNativeMac())
572 SendKeyEvent(ui::VKEY_C
, false, true);
574 SendKeyEvent(ui::VKEY_INSERT
, false, true);
577 // Sends Shift+Insert if supported, otherwise Cmd+V again.
578 void SendAlternatePaste() {
579 if (TestingNativeMac())
580 SendKeyEvent(ui::VKEY_V
, false, true);
582 SendKeyEvent(ui::VKEY_INSERT
, true, false);
585 View
* GetFocusedView() {
586 return widget_
->GetFocusManager()->GetFocusedView();
589 int GetCursorPositionX(int cursor_pos
) {
590 return test_api_
->GetRenderText()->GetCursorBounds(
591 gfx::SelectionModel(cursor_pos
, gfx::CURSOR_FORWARD
), false).x();
594 // Get the current cursor bounds.
595 gfx::Rect
GetCursorBounds() {
596 return test_api_
->GetRenderText()->GetUpdatedCursorBounds();
599 // Get the cursor bounds of |sel|.
600 gfx::Rect
GetCursorBounds(const gfx::SelectionModel
& sel
) {
601 return test_api_
->GetRenderText()->GetCursorBounds(sel
, true);
604 gfx::Rect
GetDisplayRect() {
605 return test_api_
->GetRenderText()->display_rect();
608 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
609 // y-axis is in the middle of |bound|'s vertical range.
610 void MouseClick(const gfx::Rect bound
, int x_offset
) {
611 gfx::Point
point(bound
.x() + x_offset
, bound
.y() + bound
.height() / 2);
612 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
613 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
614 ui::EF_LEFT_MOUSE_BUTTON
);
615 textfield_
->OnMousePressed(click
);
616 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point
, point
,
617 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
618 ui::EF_LEFT_MOUSE_BUTTON
);
619 textfield_
->OnMouseReleased(release
);
622 // This is to avoid double/triple click.
623 void NonClientMouseClick() {
624 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
625 ui::EventTimeForNow(),
626 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
627 ui::EF_LEFT_MOUSE_BUTTON
);
628 textfield_
->OnMousePressed(click
);
629 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
630 ui::EventTimeForNow(),
631 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_NON_CLIENT
,
632 ui::EF_LEFT_MOUSE_BUTTON
);
633 textfield_
->OnMouseReleased(release
);
636 void VerifyTextfieldContextMenuContents(bool textfield_has_selection
,
638 ui::MenuModel
* menu
) {
639 EXPECT_EQ(can_undo
, menu
->IsEnabledAt(0 /* UNDO */));
640 EXPECT_TRUE(menu
->IsEnabledAt(1 /* Separator */));
641 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(2 /* CUT */));
642 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(3 /* COPY */));
643 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
).empty(),
644 menu
->IsEnabledAt(4 /* PASTE */));
645 EXPECT_EQ(textfield_has_selection
, menu
->IsEnabledAt(5 /* DELETE */));
646 EXPECT_TRUE(menu
->IsEnabledAt(6 /* Separator */));
647 EXPECT_TRUE(menu
->IsEnabledAt(7 /* SELECT ALL */));
650 // We need widget to populate wrapper class.
653 TestTextfield
* textfield_
;
654 scoped_ptr
<TextfieldTestApi
> test_api_
;
655 TextfieldModel
* model_
;
657 // The string from Controller::ContentsChanged callback.
658 base::string16 last_contents_
;
660 // For testing input method related behaviors.
661 MockInputMethod
* input_method_
;
663 // Indicates how many times OnBeforeUserAction() is called.
664 int on_before_user_action_
;
666 // Indicates how many times OnAfterUserAction() is called.
667 int on_after_user_action_
;
670 ui::ClipboardType copied_to_clipboard_
;
671 scoped_ptr
<test::WidgetTest::FakeActivation
> fake_activation_
;
673 #if defined(OS_MACOSX) && !defined(USE_AURA)
674 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
677 DISALLOW_COPY_AND_ASSIGN(TextfieldTest
);
680 TEST_F(TextfieldTest
, ModelChangesTest
) {
683 // TextfieldController::ContentsChanged() shouldn't be called when changing
684 // text programmatically.
685 last_contents_
.clear();
686 textfield_
->SetText(ASCIIToUTF16("this is"));
688 EXPECT_STR_EQ("this is", model_
->text());
689 EXPECT_STR_EQ("this is", textfield_
->text());
690 EXPECT_TRUE(last_contents_
.empty());
692 textfield_
->AppendText(ASCIIToUTF16(" a test"));
693 EXPECT_STR_EQ("this is a test", model_
->text());
694 EXPECT_STR_EQ("this is a test", textfield_
->text());
695 EXPECT_TRUE(last_contents_
.empty());
697 EXPECT_EQ(base::string16(), textfield_
->GetSelectedText());
698 textfield_
->SelectAll(false);
699 EXPECT_STR_EQ("this is a test", textfield_
->GetSelectedText());
700 EXPECT_TRUE(last_contents_
.empty());
703 TEST_F(TextfieldTest
, KeyTest
) {
705 // Event flags: key, alt, shift, ctrl, caps-lock.
706 SendKeyEvent(ui::VKEY_T
, false, true, false, false);
707 SendKeyEvent(ui::VKEY_E
, false, false, false, false);
708 SendKeyEvent(ui::VKEY_X
, false, true, false, true);
709 SendKeyEvent(ui::VKEY_T
, false, false, false, true);
710 SendKeyEvent(ui::VKEY_1
, false, true, false, false);
711 SendKeyEvent(ui::VKEY_1
, false, false, false, false);
712 SendKeyEvent(ui::VKEY_1
, false, true, false, true);
713 SendKeyEvent(ui::VKEY_1
, false, false, false, true);
715 // On Mac, Caps+Shift remains uppercase.
716 if (TestingNativeMac())
717 EXPECT_STR_EQ("TeXT!1!1", textfield_
->text());
719 EXPECT_STR_EQ("TexT!1!1", textfield_
->text());
722 TEST_F(TextfieldTest
, KeysWithModifiersTest
) {
724 const int ctrl
= ui::EF_CONTROL_DOWN
;
725 const int alt
= ui::EF_ALT_DOWN
;
726 const int command
= ui::EF_COMMAND_DOWN
;
727 const int altgr
= ui::EF_ALTGR_DOWN
;
728 const int shift
= ui::EF_SHIFT_DOWN
;
730 SendKeyPress(ui::VKEY_T
, shift
| alt
| altgr
);
731 SendKeyPress(ui::VKEY_H
, alt
);
732 SendKeyPress(ui::VKEY_E
, altgr
);
733 SendKeyPress(ui::VKEY_T
, shift
);
734 SendKeyPress(ui::VKEY_E
, shift
| altgr
);
735 SendKeyPress(ui::VKEY_X
, 0);
736 SendKeyPress(ui::VKEY_T
, ctrl
);
737 SendKeyPress(ui::VKEY_1
, alt
);
738 SendKeyPress(ui::VKEY_2
, command
);
739 SendKeyPress(ui::VKEY_3
, 0);
740 SendKeyPress(ui::VKEY_4
, 0);
742 if (TestingNativeCrOs())
743 EXPECT_STR_EQ("TeTEx34", textfield_
->text());
745 EXPECT_STR_EQ("TeTEx234", textfield_
->text());
748 TEST_F(TextfieldTest
, ControlAndSelectTest
) {
749 // Insert a test string in a textfield.
751 textfield_
->SetText(ASCIIToUTF16("one two three"));
752 SendHomeEvent(false);
753 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
754 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
755 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
757 EXPECT_STR_EQ("one", textfield_
->GetSelectedText());
760 SendWordEvent(ui::VKEY_RIGHT
, true);
761 EXPECT_STR_EQ("one two", textfield_
->GetSelectedText());
762 SendWordEvent(ui::VKEY_RIGHT
, true);
763 EXPECT_STR_EQ("one two three", textfield_
->GetSelectedText());
764 SendWordEvent(ui::VKEY_LEFT
, true);
765 EXPECT_STR_EQ("one two ", textfield_
->GetSelectedText());
766 SendWordEvent(ui::VKEY_LEFT
, true);
767 EXPECT_STR_EQ("one ", textfield_
->GetSelectedText());
769 // Replace the selected text.
770 SendKeyEvent(ui::VKEY_Z
, true, false);
771 SendKeyEvent(ui::VKEY_E
, true, false);
772 SendKeyEvent(ui::VKEY_R
, true, false);
773 SendKeyEvent(ui::VKEY_O
, true, false);
774 SendKeyEvent(ui::VKEY_SPACE
, false, false);
775 EXPECT_STR_EQ("ZERO two three", textfield_
->text());
778 EXPECT_STR_EQ("two three", textfield_
->GetSelectedText());
780 EXPECT_STR_EQ("ZERO ", textfield_
->GetSelectedText());
783 TEST_F(TextfieldTest
, InsertionDeletionTest
) {
784 // Insert a test string in a textfield.
786 for (size_t i
= 0; i
< 10; i
++)
787 SendKeyEvent(static_cast<ui::KeyboardCode
>(ui::VKEY_A
+ i
));
788 EXPECT_STR_EQ("abcdefghij", textfield_
->text());
790 // Test the delete and backspace keys.
791 textfield_
->SelectRange(gfx::Range(5));
792 for (int i
= 0; i
< 3; i
++)
793 SendKeyEvent(ui::VKEY_BACK
);
794 EXPECT_STR_EQ("abfghij", textfield_
->text());
795 for (int i
= 0; i
< 3; i
++)
796 SendKeyEvent(ui::VKEY_DELETE
);
797 EXPECT_STR_EQ("abij", textfield_
->text());
799 // Select all and replace with "k".
800 textfield_
->SelectAll(false);
801 SendKeyEvent(ui::VKEY_K
);
802 EXPECT_STR_EQ("k", textfield_
->text());
804 // Delete the previous word from cursor.
806 textfield_
->SetText(ASCIIToUTF16("one two three four"));
808 SendWordEvent(ui::VKEY_BACK
, shift
);
809 EXPECT_STR_EQ("one two three ", textfield_
->text());
811 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
813 SendWordEvent(ui::VKEY_LEFT
, shift
);
815 SendWordEvent(ui::VKEY_BACK
, shift
);
816 #if defined(OS_LINUX)
817 EXPECT_STR_EQ("three ", textfield_
->text());
819 EXPECT_STR_EQ("one three ", textfield_
->text());
822 // Delete the next word from cursor.
823 textfield_
->SetText(ASCIIToUTF16("one two three four"));
825 SendHomeEvent(shift
);
826 SendWordEvent(ui::VKEY_DELETE
, shift
);
827 EXPECT_STR_EQ(" two three four", textfield_
->text());
829 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
831 SendWordEvent(ui::VKEY_RIGHT
, shift
);
833 SendWordEvent(ui::VKEY_DELETE
, shift
);
834 #if defined(OS_LINUX)
835 EXPECT_STR_EQ(" two", textfield_
->text());
837 EXPECT_STR_EQ(" two four", textfield_
->text());
841 TEST_F(TextfieldTest
, PasswordTest
) {
843 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
844 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
845 EXPECT_TRUE(textfield_
->enabled());
846 EXPECT_TRUE(textfield_
->IsFocusable());
848 last_contents_
.clear();
849 textfield_
->SetText(ASCIIToUTF16("password"));
850 // Ensure text() and the callback returns the actual text instead of "*".
851 EXPECT_STR_EQ("password", textfield_
->text());
852 EXPECT_TRUE(last_contents_
.empty());
853 model_
->SelectAll(false);
854 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
856 // Cut and copy should be disabled.
857 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
858 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
859 SendKeyEvent(ui::VKEY_X
, false, true);
860 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
861 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
862 SendKeyEvent(ui::VKEY_C
, false, true);
864 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
865 EXPECT_STR_EQ("password", textfield_
->text());
866 // [Shift]+[Delete] should just delete without copying text to the clipboard.
867 textfield_
->SelectAll(false);
868 SendKeyEvent(ui::VKEY_DELETE
, true, false);
870 // Paste should work normally.
871 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
872 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
873 SendKeyEvent(ui::VKEY_V
, false, true);
874 SendAlternatePaste();
875 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
876 EXPECT_STR_EQ("foofoofoo", textfield_
->text());
879 TEST_F(TextfieldTest
, TextInputType
) {
883 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, textfield_
->GetTextInputType());
886 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_URL
);
887 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL
, textfield_
->GetTextInputType());
888 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
889 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
891 // Readonly textfields have type NONE
892 textfield_
->SetReadOnly(true);
893 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
895 textfield_
->SetReadOnly(false);
896 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
898 // As do disabled textfields
899 textfield_
->SetEnabled(false);
900 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, textfield_
->GetTextInputType());
902 textfield_
->SetEnabled(true);
903 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD
, textfield_
->GetTextInputType());
906 TEST_F(TextfieldTest
, OnKeyPress
) {
909 // Character keys are handled by the input method.
910 SendKeyEvent(ui::VKEY_A
);
911 EXPECT_TRUE(textfield_
->key_received());
912 EXPECT_FALSE(textfield_
->key_handled());
915 // Arrow keys and home/end are handled by the textfield.
916 SendKeyEvent(ui::VKEY_LEFT
);
917 EXPECT_TRUE(textfield_
->key_received());
918 EXPECT_TRUE(textfield_
->key_handled());
921 SendKeyEvent(ui::VKEY_RIGHT
);
922 EXPECT_TRUE(textfield_
->key_received());
923 EXPECT_TRUE(textfield_
->key_handled());
926 const bool shift
= false;
927 SendHomeEvent(shift
);
928 EXPECT_TRUE(textfield_
->key_received());
929 EXPECT_TRUE(textfield_
->key_handled());
933 EXPECT_TRUE(textfield_
->key_received());
934 EXPECT_TRUE(textfield_
->key_handled());
937 // F20, up/down key won't be handled.
938 SendKeyEvent(ui::VKEY_F20
);
939 #if defined(OS_MACOSX)
940 // On Mac, key combinations that don't map to editing commands are forwarded
941 // on to the next responder, usually ending up at the window, which will beep.
942 EXPECT_FALSE(textfield_
->key_received());
944 EXPECT_TRUE(textfield_
->key_received());
946 EXPECT_FALSE(textfield_
->key_handled());
949 SendKeyEvent(ui::VKEY_UP
);
950 EXPECT_TRUE(textfield_
->key_received());
951 EXPECT_FALSE(textfield_
->key_handled());
954 SendKeyEvent(ui::VKEY_DOWN
);
955 EXPECT_TRUE(textfield_
->key_received());
956 EXPECT_FALSE(textfield_
->key_handled());
960 // Tests that default key bindings are handled even with a delegate installed.
961 TEST_F(TextfieldTest
, OnKeyPressBinding
) {
964 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
965 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
966 class TestDelegate
: public ui::TextEditKeyBindingsDelegateAuraLinux
{
969 ~TestDelegate() override
{}
972 const ui::Event
& event
,
973 std::vector
<ui::TextEditCommandAuraLinux
>* commands
) override
{
978 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
981 TestDelegate delegate
;
982 ui::SetTextEditKeyBindingsDelegate(&delegate
);
985 SendKeyEvent(ui::VKEY_A
, false, false);
986 EXPECT_STR_EQ("a", textfield_
->text());
989 // Undo/Redo command keys are handled by the textfield.
990 SendKeyEvent(ui::VKEY_Z
, false, true);
991 EXPECT_TRUE(textfield_
->key_received());
992 EXPECT_TRUE(textfield_
->key_handled());
993 EXPECT_TRUE(textfield_
->text().empty());
996 SendKeyEvent(ui::VKEY_Z
, true, true);
997 EXPECT_TRUE(textfield_
->key_received());
998 EXPECT_TRUE(textfield_
->key_handled());
999 EXPECT_STR_EQ("a", textfield_
->text());
1000 textfield_
->clear();
1002 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1003 ui::SetTextEditKeyBindingsDelegate(NULL
);
1007 TEST_F(TextfieldTest
, CursorMovement
) {
1010 // Test with trailing whitespace.
1011 textfield_
->SetText(ASCIIToUTF16("one two hre "));
1013 // Send the cursor at the end.
1014 SendKeyEvent(ui::VKEY_END
);
1016 // Ctrl+Left should move the cursor just before the last word.
1017 const bool shift
= false;
1018 SendWordEvent(ui::VKEY_LEFT
, shift
);
1019 SendKeyEvent(ui::VKEY_T
);
1020 EXPECT_STR_EQ("one two thre ", textfield_
->text());
1021 EXPECT_STR_EQ("one two thre ", last_contents_
);
1023 // Ctrl+Right should move the cursor to the end of the last word.
1024 SendWordEvent(ui::VKEY_RIGHT
, shift
);
1025 SendKeyEvent(ui::VKEY_E
);
1026 EXPECT_STR_EQ("one two three ", textfield_
->text());
1027 EXPECT_STR_EQ("one two three ", last_contents_
);
1029 // Ctrl+Right again should move the cursor to the end.
1030 SendWordEvent(ui::VKEY_RIGHT
, shift
);
1031 SendKeyEvent(ui::VKEY_BACK
);
1032 EXPECT_STR_EQ("one two three", textfield_
->text());
1033 EXPECT_STR_EQ("one two three", last_contents_
);
1035 // Test with leading whitespace.
1036 textfield_
->SetText(ASCIIToUTF16(" ne two"));
1038 // Send the cursor at the beginning.
1039 SendHomeEvent(shift
);
1041 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
1043 SendWordEvent(ui::VKEY_RIGHT
, shift
);
1044 SendWordEvent(ui::VKEY_LEFT
, shift
);
1045 SendKeyEvent(ui::VKEY_O
);
1046 EXPECT_STR_EQ(" one two", textfield_
->text());
1047 EXPECT_STR_EQ(" one two", last_contents_
);
1049 // Ctrl+Left to move the cursor to the beginning of the first word.
1050 SendWordEvent(ui::VKEY_LEFT
, shift
);
1051 // Ctrl+Left again should move the cursor back to the very beginning.
1052 SendWordEvent(ui::VKEY_LEFT
, shift
);
1053 SendKeyEvent(ui::VKEY_DELETE
);
1054 EXPECT_STR_EQ("one two", textfield_
->text());
1055 EXPECT_STR_EQ("one two", last_contents_
);
1058 TEST_F(TextfieldTest
, FocusTraversalTest
) {
1060 textfield_
->RequestFocus();
1062 EXPECT_EQ(1, GetFocusedView()->id());
1063 widget_
->GetFocusManager()->AdvanceFocus(false);
1064 EXPECT_EQ(2, GetFocusedView()->id());
1065 widget_
->GetFocusManager()->AdvanceFocus(false);
1066 EXPECT_EQ(3, GetFocusedView()->id());
1067 // Cycle back to the first textfield.
1068 widget_
->GetFocusManager()->AdvanceFocus(false);
1069 EXPECT_EQ(1, GetFocusedView()->id());
1071 widget_
->GetFocusManager()->AdvanceFocus(true);
1072 EXPECT_EQ(3, GetFocusedView()->id());
1073 widget_
->GetFocusManager()->AdvanceFocus(true);
1074 EXPECT_EQ(2, GetFocusedView()->id());
1075 widget_
->GetFocusManager()->AdvanceFocus(true);
1076 EXPECT_EQ(1, GetFocusedView()->id());
1077 // Cycle back to the last textfield.
1078 widget_
->GetFocusManager()->AdvanceFocus(true);
1079 EXPECT_EQ(3, GetFocusedView()->id());
1081 // Request focus should still work.
1082 textfield_
->RequestFocus();
1083 EXPECT_EQ(1, GetFocusedView()->id());
1085 // Test if clicking on textfield view sets the focus.
1086 widget_
->GetFocusManager()->AdvanceFocus(true);
1087 EXPECT_EQ(3, GetFocusedView()->id());
1088 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1089 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1090 ui::EF_LEFT_MOUSE_BUTTON
);
1091 textfield_
->OnMousePressed(click
);
1092 EXPECT_EQ(1, GetFocusedView()->id());
1094 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
1095 SendKeyEvent(ui::VKEY_TAB
, false, false);
1096 EXPECT_EQ(2, GetFocusedView()->id());
1097 SendKeyEvent(ui::VKEY_TAB
, false, false);
1098 EXPECT_EQ(3, GetFocusedView()->id());
1099 // Cycle back to the first textfield.
1100 SendKeyEvent(ui::VKEY_TAB
, false, false);
1101 EXPECT_EQ(1, GetFocusedView()->id());
1103 SendKeyEvent(ui::VKEY_TAB
, true, false);
1104 EXPECT_EQ(3, GetFocusedView()->id());
1105 SendKeyEvent(ui::VKEY_TAB
, true, false);
1106 EXPECT_EQ(2, GetFocusedView()->id());
1107 SendKeyEvent(ui::VKEY_TAB
, true, false);
1108 EXPECT_EQ(1, GetFocusedView()->id());
1109 // Cycle back to the last textfield.
1110 SendKeyEvent(ui::VKEY_TAB
, true, false);
1111 EXPECT_EQ(3, GetFocusedView()->id());
1114 TEST_F(TextfieldTest
, ContextMenuDisplayTest
) {
1116 EXPECT_TRUE(textfield_
->context_menu_controller());
1117 textfield_
->SetText(ASCIIToUTF16("hello world"));
1118 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE
);
1119 textfield_
->ClearEditHistory();
1120 EXPECT_TRUE(GetContextMenuModel());
1121 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
1123 textfield_
->SelectAll(false);
1124 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
1126 SendKeyEvent(ui::VKEY_T
);
1127 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
1129 textfield_
->SelectAll(false);
1130 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1132 // Exercise the "paste enabled?" check in the verifier.
1133 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1134 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1137 TEST_F(TextfieldTest
, DoubleAndTripleClickTest
) {
1139 textfield_
->SetText(ASCIIToUTF16("hello world"));
1140 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1141 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1142 ui::EF_LEFT_MOUSE_BUTTON
);
1143 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, gfx::Point(), gfx::Point(),
1144 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1145 ui::EF_LEFT_MOUSE_BUTTON
);
1146 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
1147 ui::EventTimeForNow(),
1148 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
1149 ui::EF_LEFT_MOUSE_BUTTON
);
1151 // Test for double click.
1152 textfield_
->OnMousePressed(click
);
1153 textfield_
->OnMouseReleased(release
);
1154 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1155 textfield_
->OnMousePressed(double_click
);
1156 textfield_
->OnMouseReleased(release
);
1157 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1159 // Test for triple click.
1160 textfield_
->OnMousePressed(click
);
1161 textfield_
->OnMouseReleased(release
);
1162 EXPECT_STR_EQ("hello world", textfield_
->GetSelectedText());
1164 // Another click should reset back to double click.
1165 textfield_
->OnMousePressed(click
);
1166 textfield_
->OnMouseReleased(release
);
1167 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
1170 TEST_F(TextfieldTest
, DragToSelect
) {
1172 textfield_
->SetText(ASCIIToUTF16("hello world"));
1173 const int kStart
= GetCursorPositionX(5);
1174 const int kEnd
= 500;
1175 gfx::Point
start_point(kStart
, 0);
1176 gfx::Point
end_point(kEnd
, 0);
1177 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, start_point
, start_point
,
1178 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1179 ui::EF_LEFT_MOUSE_BUTTON
);
1180 ui::MouseEvent
click_b(ui::ET_MOUSE_PRESSED
, end_point
, end_point
,
1181 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1182 ui::EF_LEFT_MOUSE_BUTTON
);
1183 ui::MouseEvent
drag_left(ui::ET_MOUSE_DRAGGED
, gfx::Point(), gfx::Point(),
1184 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1185 ui::MouseEvent
drag_right(ui::ET_MOUSE_DRAGGED
, end_point
, end_point
,
1186 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1187 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, end_point
, end_point
,
1188 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1189 ui::EF_LEFT_MOUSE_BUTTON
);
1190 textfield_
->OnMousePressed(click_a
);
1191 EXPECT_TRUE(textfield_
->GetSelectedText().empty());
1192 // Check that dragging left selects the beginning of the string.
1193 textfield_
->OnMouseDragged(drag_left
);
1194 base::string16 text_left
= textfield_
->GetSelectedText();
1195 EXPECT_STR_EQ("hello", text_left
);
1196 // Check that dragging right selects the rest of the string.
1197 textfield_
->OnMouseDragged(drag_right
);
1198 base::string16 text_right
= textfield_
->GetSelectedText();
1199 EXPECT_STR_EQ(" world", text_right
);
1200 // Check that releasing in the same location does not alter the selection.
1201 textfield_
->OnMouseReleased(release
);
1202 EXPECT_EQ(text_right
, textfield_
->GetSelectedText());
1203 // Check that dragging from beyond the text length works too.
1204 textfield_
->OnMousePressed(click_b
);
1205 textfield_
->OnMouseDragged(drag_left
);
1206 textfield_
->OnMouseReleased(release
);
1207 EXPECT_EQ(textfield_
->text(), textfield_
->GetSelectedText());
1211 TEST_F(TextfieldTest
, DragAndDrop_AcceptDrop
) {
1213 textfield_
->SetText(ASCIIToUTF16("hello world"));
1215 ui::OSExchangeData data
;
1216 base::string16
string(ASCIIToUTF16("string "));
1217 data
.SetString(string
);
1219 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1221 // Ensure that disabled textfields do not accept drops.
1222 textfield_
->SetEnabled(false);
1223 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1224 EXPECT_EQ(0, formats
);
1225 EXPECT_TRUE(custom_formats
.empty());
1226 EXPECT_FALSE(textfield_
->CanDrop(data
));
1227 textfield_
->SetEnabled(true);
1229 // Ensure that read-only textfields do not accept drops.
1230 textfield_
->SetReadOnly(true);
1231 EXPECT_FALSE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1232 EXPECT_EQ(0, formats
);
1233 EXPECT_TRUE(custom_formats
.empty());
1234 EXPECT_FALSE(textfield_
->CanDrop(data
));
1235 textfield_
->SetReadOnly(false);
1237 // Ensure that enabled and editable textfields do accept drops.
1238 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1239 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1240 EXPECT_TRUE(custom_formats
.empty());
1241 EXPECT_TRUE(textfield_
->CanDrop(data
));
1242 gfx::Point
drop_point(GetCursorPositionX(6), 0);
1243 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1244 ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
);
1245 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
| ui::DragDropTypes::DRAG_MOVE
,
1246 textfield_
->OnDragUpdated(drop
));
1247 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
, textfield_
->OnPerformDrop(drop
));
1248 EXPECT_STR_EQ("hello string world", textfield_
->text());
1250 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1251 ui::OSExchangeData bad_data
;
1252 bad_data
.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1253 ui::OSExchangeData::CustomFormat fmt
= ui::Clipboard::GetBitmapFormatType();
1254 bad_data
.SetPickledData(fmt
, base::Pickle());
1255 bad_data
.SetFileContents(base::FilePath(L
"x"), "x");
1256 bad_data
.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1257 ui::OSExchangeData::DownloadFileInfo
download(base::FilePath(), NULL
);
1258 bad_data
.SetDownloadFileInfo(download
);
1259 EXPECT_FALSE(textfield_
->CanDrop(bad_data
));
1263 TEST_F(TextfieldTest
, DragAndDrop_InitiateDrag
) {
1265 textfield_
->SetText(ASCIIToUTF16("hello string world"));
1267 // Ensure the textfield will provide selected text for drag data.
1268 base::string16 string
;
1269 ui::OSExchangeData data
;
1270 const gfx::Range
kStringRange(6, 12);
1271 textfield_
->SelectRange(kStringRange
);
1272 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
1273 textfield_
->WriteDragDataForView(NULL
, kStringPoint
, &data
);
1274 EXPECT_TRUE(data
.GetString(&string
));
1275 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1277 // Ensure that disabled textfields do not support drag operations.
1278 textfield_
->SetEnabled(false);
1279 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1280 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1281 textfield_
->SetEnabled(true);
1282 // Ensure that textfields without selections do not support drag operations.
1283 textfield_
->ClearSelection();
1284 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1285 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1286 textfield_
->SelectRange(kStringRange
);
1287 // Ensure that password textfields do not support drag operations.
1288 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1289 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1290 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1291 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT
);
1292 // Ensure that textfields only initiate drag operations inside the selection.
1293 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, kStringPoint
, kStringPoint
,
1294 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1295 ui::EF_LEFT_MOUSE_BUTTON
);
1296 textfield_
->OnMousePressed(press_event
);
1297 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE
,
1298 textfield_
->GetDragOperationsForView(NULL
, gfx::Point()));
1299 EXPECT_FALSE(textfield_
->CanStartDragForView(NULL
, gfx::Point(),
1301 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY
,
1302 textfield_
->GetDragOperationsForView(NULL
, kStringPoint
));
1303 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
1305 // Ensure that textfields support local moves.
1306 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1307 textfield_
->GetDragOperationsForView(textfield_
, kStringPoint
));
1310 TEST_F(TextfieldTest
, DragAndDrop_ToTheRight
) {
1312 textfield_
->SetText(ASCIIToUTF16("hello world"));
1314 base::string16 string
;
1315 ui::OSExchangeData data
;
1318 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1320 // Start dragging "ello".
1321 textfield_
->SelectRange(gfx::Range(1, 5));
1322 gfx::Point
point(GetCursorPositionX(3), 0);
1323 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1324 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1325 ui::EF_LEFT_MOUSE_BUTTON
);
1326 textfield_
->OnMousePressed(click_a
);
1327 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1329 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1330 click_a
.location());
1331 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1333 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1334 EXPECT_TRUE(data
.GetString(&string
));
1335 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1336 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1337 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1338 EXPECT_TRUE(custom_formats
.empty());
1340 // Drop "ello" after "w".
1341 const gfx::Point
kDropPoint(GetCursorPositionX(7), 0);
1342 EXPECT_TRUE(textfield_
->CanDrop(data
));
1343 ui::DropTargetEvent
drop_a(data
, kDropPoint
, kDropPoint
, operations
);
1344 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1345 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1346 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1347 textfield_
->OnDragDone();
1349 // Undo/Redo the drag&drop change.
1350 SendKeyEvent(ui::VKEY_Z
, false, true);
1351 EXPECT_STR_EQ("hello world", textfield_
->text());
1352 SendKeyEvent(ui::VKEY_Z
, false, true);
1353 EXPECT_STR_EQ("", textfield_
->text());
1354 SendKeyEvent(ui::VKEY_Z
, false, true);
1355 EXPECT_STR_EQ("", textfield_
->text());
1356 SendKeyEvent(ui::VKEY_Z
, true, true);
1357 EXPECT_STR_EQ("hello world", textfield_
->text());
1358 SendKeyEvent(ui::VKEY_Z
, true, true);
1359 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1360 SendKeyEvent(ui::VKEY_Z
, true, true);
1361 EXPECT_STR_EQ("h welloorld", textfield_
->text());
1364 TEST_F(TextfieldTest
, DragAndDrop_ToTheLeft
) {
1366 textfield_
->SetText(ASCIIToUTF16("hello world"));
1368 base::string16 string
;
1369 ui::OSExchangeData data
;
1372 std::set
<OSExchangeData::CustomFormat
> custom_formats
;
1374 // Start dragging " worl".
1375 textfield_
->SelectRange(gfx::Range(5, 10));
1376 gfx::Point
point(GetCursorPositionX(7), 0);
1377 ui::MouseEvent
click_a(ui::ET_MOUSE_PRESSED
, point
, point
,
1378 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1379 ui::EF_LEFT_MOUSE_BUTTON
);
1380 textfield_
->OnMousePressed(click_a
);
1381 EXPECT_TRUE(textfield_
->CanStartDragForView(textfield_
, click_a
.location(),
1383 operations
= textfield_
->GetDragOperationsForView(textfield_
,
1384 click_a
.location());
1385 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
| ui::DragDropTypes::DRAG_COPY
,
1387 textfield_
->WriteDragDataForView(NULL
, click_a
.location(), &data
);
1388 EXPECT_TRUE(data
.GetString(&string
));
1389 EXPECT_EQ(textfield_
->GetSelectedText(), string
);
1390 EXPECT_TRUE(textfield_
->GetDropFormats(&formats
, &custom_formats
));
1391 EXPECT_EQ(ui::OSExchangeData::STRING
, formats
);
1392 EXPECT_TRUE(custom_formats
.empty());
1394 // Drop " worl" after "h".
1395 EXPECT_TRUE(textfield_
->CanDrop(data
));
1396 gfx::Point
drop_point(GetCursorPositionX(1), 0);
1397 ui::DropTargetEvent
drop_a(data
, drop_point
, drop_point
, operations
);
1398 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop_a
));
1399 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnPerformDrop(drop_a
));
1400 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1401 textfield_
->OnDragDone();
1403 // Undo/Redo the drag&drop change.
1404 SendKeyEvent(ui::VKEY_Z
, false, true);
1405 EXPECT_STR_EQ("hello world", textfield_
->text());
1406 SendKeyEvent(ui::VKEY_Z
, false, true);
1407 EXPECT_STR_EQ("", textfield_
->text());
1408 SendKeyEvent(ui::VKEY_Z
, false, true);
1409 EXPECT_STR_EQ("", textfield_
->text());
1410 SendKeyEvent(ui::VKEY_Z
, true, true);
1411 EXPECT_STR_EQ("hello world", textfield_
->text());
1412 SendKeyEvent(ui::VKEY_Z
, true, true);
1413 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1414 SendKeyEvent(ui::VKEY_Z
, true, true);
1415 EXPECT_STR_EQ("h worlellod", textfield_
->text());
1418 TEST_F(TextfieldTest
, DragAndDrop_Canceled
) {
1420 textfield_
->SetText(ASCIIToUTF16("hello world"));
1422 // Start dragging "worl".
1423 textfield_
->SelectRange(gfx::Range(6, 10));
1424 gfx::Point
point(GetCursorPositionX(8), 0);
1425 ui::MouseEvent
click(ui::ET_MOUSE_PRESSED
, point
, point
,
1426 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1427 ui::EF_LEFT_MOUSE_BUTTON
);
1428 textfield_
->OnMousePressed(click
);
1429 ui::OSExchangeData data
;
1430 textfield_
->WriteDragDataForView(NULL
, click
.location(), &data
);
1431 EXPECT_TRUE(textfield_
->CanDrop(data
));
1432 // Drag the text over somewhere valid, outside the current selection.
1433 gfx::Point
drop_point(GetCursorPositionX(2), 0);
1434 ui::DropTargetEvent
drop(data
, drop_point
, drop_point
,
1435 ui::DragDropTypes::DRAG_MOVE
);
1436 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE
, textfield_
->OnDragUpdated(drop
));
1437 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1438 gfx::Point
drag_point(GetCursorPositionX(9), 0);
1439 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, drag_point
, drag_point
,
1440 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
1441 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, drag_point
, drag_point
,
1442 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
1443 ui::EF_LEFT_MOUSE_BUTTON
);
1444 textfield_
->OnMouseDragged(drag
);
1445 textfield_
->OnMouseReleased(release
);
1446 textfield_
->OnDragDone();
1447 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_
->text());
1450 TEST_F(TextfieldTest
, ReadOnlyTest
) {
1452 textfield_
->SetText(ASCIIToUTF16("read only"));
1453 textfield_
->SetReadOnly(true);
1454 EXPECT_TRUE(textfield_
->enabled());
1455 EXPECT_TRUE(textfield_
->IsFocusable());
1458 SendHomeEvent(shift
);
1459 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1460 SendEndEvent(shift
);
1461 EXPECT_EQ(9U, textfield_
->GetCursorPosition());
1463 SendKeyEvent(ui::VKEY_LEFT
, shift
, false);
1464 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1465 SendWordEvent(ui::VKEY_LEFT
, shift
);
1466 EXPECT_EQ(5U, textfield_
->GetCursorPosition());
1468 SendWordEvent(ui::VKEY_LEFT
, shift
);
1469 EXPECT_EQ(0U, textfield_
->GetCursorPosition());
1470 EXPECT_STR_EQ("read ", textfield_
->GetSelectedText());
1471 textfield_
->SelectAll(false);
1472 EXPECT_STR_EQ("read only", textfield_
->GetSelectedText());
1474 // Cut should be disabled.
1475 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1476 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1477 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1478 SendKeyEvent(ui::VKEY_X
, false, true);
1480 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1481 EXPECT_STR_EQ("read only", textfield_
->text());
1483 // Paste should be disabled.
1484 EXPECT_FALSE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1485 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1486 SendKeyEvent(ui::VKEY_V
, false, true);
1487 SendAlternatePaste();
1488 EXPECT_STR_EQ("read only", textfield_
->text());
1490 // Copy should work normally.
1491 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1492 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1493 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1494 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1495 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1496 SendKeyEvent(ui::VKEY_C
, false, true);
1497 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1498 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "Test");
1499 SendAlternateCopy();
1500 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1502 // SetText should work even in read only mode.
1503 textfield_
->SetText(ASCIIToUTF16(" four five six "));
1504 EXPECT_STR_EQ(" four five six ", textfield_
->text());
1506 textfield_
->SelectAll(false);
1507 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1509 // Text field is unmodifiable and selection shouldn't change.
1510 SendKeyEvent(ui::VKEY_DELETE
);
1511 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1512 SendKeyEvent(ui::VKEY_BACK
);
1513 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1514 SendKeyEvent(ui::VKEY_T
);
1515 EXPECT_STR_EQ(" four five six ", textfield_
->GetSelectedText());
1518 TEST_F(TextfieldTest
, TextInputClientTest
) {
1520 ui::TextInputClient
* client
= textfield_
;
1521 EXPECT_TRUE(client
);
1522 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT
, client
->GetTextInputType());
1524 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1526 EXPECT_TRUE(client
->GetTextRange(&range
));
1527 EXPECT_EQ(0U, range
.start());
1528 EXPECT_EQ(10U, range
.end());
1530 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(1, 4)));
1531 EXPECT_TRUE(client
->GetSelectionRange(&range
));
1532 EXPECT_EQ(gfx::Range(1, 4), range
);
1534 base::string16 substring
;
1535 EXPECT_TRUE(client
->GetTextFromRange(range
, &substring
));
1536 EXPECT_STR_EQ("123", substring
);
1538 EXPECT_TRUE(client
->DeleteRange(range
));
1539 EXPECT_STR_EQ("0456789", textfield_
->text());
1541 ui::CompositionText composition
;
1542 composition
.text
= UTF8ToUTF16("321");
1543 // Set composition through input method.
1544 input_method_
->Clear();
1545 input_method_
->SetCompositionTextForNextKey(composition
);
1546 textfield_
->clear();
1548 on_before_user_action_
= on_after_user_action_
= 0;
1550 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1551 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1552 // whenever it has a test composition). However, on Mac, it can't be a letter
1553 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1554 // and don't have a meaningful ui::KeyEvent that would trigger
1555 // DispatchKeyEvent().
1556 SendKeyEvent(ui::VKEY_RETURN
);
1558 EXPECT_TRUE(textfield_
->key_received());
1559 EXPECT_FALSE(textfield_
->key_handled());
1560 EXPECT_TRUE(client
->HasCompositionText());
1561 EXPECT_TRUE(client
->GetCompositionTextRange(&range
));
1562 EXPECT_STR_EQ("0321456789", textfield_
->text());
1563 EXPECT_EQ(gfx::Range(1, 4), range
);
1564 EXPECT_EQ(1, on_before_user_action_
);
1565 EXPECT_EQ(1, on_after_user_action_
);
1567 input_method_
->SetResultTextForNextKey(UTF8ToUTF16("123"));
1568 on_before_user_action_
= on_after_user_action_
= 0;
1569 textfield_
->clear();
1570 SendKeyEvent(ui::VKEY_RETURN
);
1571 EXPECT_TRUE(textfield_
->key_received());
1572 EXPECT_FALSE(textfield_
->key_handled());
1573 EXPECT_FALSE(client
->HasCompositionText());
1574 EXPECT_FALSE(input_method_
->cancel_composition_called());
1575 EXPECT_STR_EQ("0123456789", textfield_
->text());
1576 EXPECT_EQ(1, on_before_user_action_
);
1577 EXPECT_EQ(1, on_after_user_action_
);
1579 input_method_
->Clear();
1580 input_method_
->SetCompositionTextForNextKey(composition
);
1581 textfield_
->clear();
1582 SendKeyEvent(ui::VKEY_RETURN
);
1583 EXPECT_TRUE(client
->HasCompositionText());
1584 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1586 on_before_user_action_
= on_after_user_action_
= 0;
1587 textfield_
->clear();
1588 SendKeyEvent(ui::VKEY_RIGHT
);
1589 EXPECT_FALSE(client
->HasCompositionText());
1590 EXPECT_TRUE(input_method_
->cancel_composition_called());
1591 EXPECT_TRUE(textfield_
->key_received());
1592 EXPECT_TRUE(textfield_
->key_handled());
1593 EXPECT_STR_EQ("0123321456789", textfield_
->text());
1594 EXPECT_EQ(8U, textfield_
->GetCursorPosition());
1595 EXPECT_EQ(1, on_before_user_action_
);
1596 EXPECT_EQ(1, on_after_user_action_
);
1598 textfield_
->clear();
1599 textfield_
->SetText(ASCIIToUTF16("0123456789"));
1600 EXPECT_TRUE(client
->SetSelectionRange(gfx::Range(5, 5)));
1601 client
->ExtendSelectionAndDelete(4, 2);
1602 EXPECT_STR_EQ("0789", textfield_
->text());
1604 // On{Before,After}UserAction should be called by whatever user action
1605 // triggers clearing or setting a selection if appropriate.
1606 on_before_user_action_
= on_after_user_action_
= 0;
1607 textfield_
->clear();
1608 textfield_
->ClearSelection();
1609 textfield_
->SelectAll(false);
1610 EXPECT_EQ(0, on_before_user_action_
);
1611 EXPECT_EQ(0, on_after_user_action_
);
1613 input_method_
->Clear();
1615 // Changing the Textfield to readonly shouldn't change the input client, since
1616 // it's still required for selections and clipboard copy.
1617 ui::TextInputClient
* text_input_client
= textfield_
;
1618 EXPECT_TRUE(text_input_client
);
1619 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1620 textfield_
->SetReadOnly(true);
1621 EXPECT_TRUE(input_method_
->text_input_type_changed());
1622 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1624 input_method_
->Clear();
1625 textfield_
->SetReadOnly(false);
1626 EXPECT_TRUE(input_method_
->text_input_type_changed());
1627 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE
, text_input_client
->GetTextInputType());
1629 input_method_
->Clear();
1630 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
1631 EXPECT_TRUE(input_method_
->text_input_type_changed());
1634 TEST_F(TextfieldTest
, UndoRedoTest
) {
1636 SendKeyEvent(ui::VKEY_A
);
1637 EXPECT_STR_EQ("a", textfield_
->text());
1638 SendKeyEvent(ui::VKEY_Z
, false, true);
1639 EXPECT_STR_EQ("", textfield_
->text());
1640 SendKeyEvent(ui::VKEY_Z
, false, true);
1641 EXPECT_STR_EQ("", textfield_
->text());
1642 SendKeyEvent(ui::VKEY_Z
, true, true);
1643 EXPECT_STR_EQ("a", textfield_
->text());
1644 SendKeyEvent(ui::VKEY_Z
, true, true);
1645 EXPECT_STR_EQ("a", textfield_
->text());
1648 textfield_
->AppendText(ASCIIToUTF16("b"));
1649 last_contents_
.clear(); // AppendText doesn't call ContentsChanged.
1650 EXPECT_STR_EQ("ab", textfield_
->text());
1651 SendKeyEvent(ui::VKEY_Z
, false, true);
1652 EXPECT_STR_EQ("a", textfield_
->text());
1653 SendKeyEvent(ui::VKEY_Z
, true, true);
1654 EXPECT_STR_EQ("ab", textfield_
->text());
1657 SendKeyEvent(ui::VKEY_C
);
1658 // Undo'ing append moves the cursor to the end for now.
1659 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1660 EXPECT_STR_EQ("abc", textfield_
->text());
1661 textfield_
->SetText(ASCIIToUTF16("abc"));
1662 EXPECT_STR_EQ("abc", textfield_
->text());
1663 SendKeyEvent(ui::VKEY_Z
, false, true);
1664 EXPECT_STR_EQ("ab", textfield_
->text());
1665 SendKeyEvent(ui::VKEY_Z
, true, true);
1666 EXPECT_STR_EQ("abc", textfield_
->text());
1667 SendKeyEvent(ui::VKEY_Z
, true, true);
1668 EXPECT_STR_EQ("abc", textfield_
->text());
1669 textfield_
->SetText(ASCIIToUTF16("123"));
1670 textfield_
->SetText(ASCIIToUTF16("123"));
1671 EXPECT_STR_EQ("123", textfield_
->text());
1672 SendKeyEvent(ui::VKEY_END
, false, false);
1673 SendKeyEvent(ui::VKEY_4
, false, false);
1674 EXPECT_STR_EQ("1234", textfield_
->text());
1675 last_contents_
.clear();
1676 SendKeyEvent(ui::VKEY_Z
, false, true);
1677 EXPECT_STR_EQ("123", textfield_
->text());
1678 SendKeyEvent(ui::VKEY_Z
, false, true);
1679 // the insert edit "c" and set edit "123" are merged to single edit,
1680 // so text becomes "ab" after undo.
1681 EXPECT_STR_EQ("ab", textfield_
->text());
1682 SendKeyEvent(ui::VKEY_Z
, false, true);
1683 EXPECT_STR_EQ("a", textfield_
->text());
1684 SendKeyEvent(ui::VKEY_Z
, true, true);
1685 EXPECT_STR_EQ("ab", textfield_
->text());
1686 SendKeyEvent(ui::VKEY_Z
, true, true);
1687 EXPECT_STR_EQ("123", textfield_
->text());
1688 SendKeyEvent(ui::VKEY_Z
, true, true);
1689 EXPECT_STR_EQ("1234", textfield_
->text());
1691 // Undoing to the same text shouldn't call ContentsChanged.
1692 SendKeyEvent(ui::VKEY_A
, false, true); // select all
1693 SendKeyEvent(ui::VKEY_A
);
1694 EXPECT_STR_EQ("a", textfield_
->text());
1695 SendKeyEvent(ui::VKEY_B
);
1696 SendKeyEvent(ui::VKEY_C
);
1697 EXPECT_STR_EQ("abc", textfield_
->text());
1698 SendKeyEvent(ui::VKEY_Z
, false, true);
1699 EXPECT_STR_EQ("1234", textfield_
->text());
1700 SendKeyEvent(ui::VKEY_Z
, true, true);
1701 EXPECT_STR_EQ("abc", textfield_
->text());
1704 SendKeyEvent(ui::VKEY_BACK
);
1705 EXPECT_STR_EQ("ab", textfield_
->text());
1706 SendHomeEvent(false);
1707 SendKeyEvent(ui::VKEY_DELETE
);
1708 EXPECT_STR_EQ("b", textfield_
->text());
1709 SendKeyEvent(ui::VKEY_A
, false, true);
1710 SendKeyEvent(ui::VKEY_DELETE
);
1711 EXPECT_STR_EQ("", textfield_
->text());
1712 SendKeyEvent(ui::VKEY_Z
, false, true);
1713 EXPECT_STR_EQ("b", textfield_
->text());
1714 SendKeyEvent(ui::VKEY_Z
, false, true);
1715 EXPECT_STR_EQ("ab", textfield_
->text());
1716 SendKeyEvent(ui::VKEY_Z
, false, true);
1717 EXPECT_STR_EQ("abc", textfield_
->text());
1718 SendKeyEvent(ui::VKEY_Z
, true, true);
1719 EXPECT_STR_EQ("ab", textfield_
->text());
1720 SendKeyEvent(ui::VKEY_Z
, true, true);
1721 EXPECT_STR_EQ("b", textfield_
->text());
1722 SendKeyEvent(ui::VKEY_Z
, true, true);
1723 EXPECT_STR_EQ("", textfield_
->text());
1724 SendKeyEvent(ui::VKEY_Z
, true, true);
1725 EXPECT_STR_EQ("", textfield_
->text());
1728 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1729 // that is bound to "Show full history", so is not mapped as an editing
1730 // command. So, on Mac, send Cmd+Shift+Z.
1731 #if !defined(OS_MACOSX)
1733 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1734 TEST_F(TextfieldTest
, RedoWithCtrlY
) {
1736 SendKeyEvent(ui::VKEY_A
);
1737 EXPECT_STR_EQ("a", textfield_
->text());
1738 SendKeyEvent(ui::VKEY_Z
, false, true);
1739 EXPECT_STR_EQ("", textfield_
->text());
1740 SendKeyEvent(ui::VKEY_Y
, false, true);
1741 EXPECT_STR_EQ("a", textfield_
->text());
1742 SendKeyEvent(ui::VKEY_Z
, false, true);
1743 EXPECT_STR_EQ("", textfield_
->text());
1744 SendKeyEvent(ui::VKEY_Z
, true, true);
1745 EXPECT_STR_EQ("a", textfield_
->text());
1748 #endif // !defined(OS_MACOSX)
1750 TEST_F(TextfieldTest
, CutCopyPaste
) {
1753 // Ensure IDS_APP_CUT cuts.
1754 textfield_
->SetText(ASCIIToUTF16("123"));
1755 textfield_
->SelectAll(false);
1756 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_CUT
));
1757 textfield_
->ExecuteCommand(IDS_APP_CUT
, 0);
1758 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1759 EXPECT_STR_EQ("", textfield_
->text());
1760 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1762 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1763 textfield_
->SetText(ASCIIToUTF16("456"));
1764 textfield_
->SelectAll(false);
1765 SendKeyEvent(ui::VKEY_X
, true, false, true, false);
1766 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1767 EXPECT_STR_EQ("456", textfield_
->text());
1768 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1769 SendKeyEvent(ui::VKEY_X
, false, true);
1770 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1771 EXPECT_STR_EQ("", textfield_
->text());
1772 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1774 // Ensure [Shift]+[Delete] cuts.
1775 textfield_
->SetText(ASCIIToUTF16("123"));
1776 textfield_
->SelectAll(false);
1778 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1779 EXPECT_STR_EQ("", textfield_
->text());
1780 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1782 // Ensure IDS_APP_COPY copies.
1783 textfield_
->SetText(ASCIIToUTF16("789"));
1784 textfield_
->SelectAll(false);
1785 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_COPY
));
1786 textfield_
->ExecuteCommand(IDS_APP_COPY
, 0);
1787 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1788 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1790 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1791 textfield_
->SetText(ASCIIToUTF16("012"));
1792 textfield_
->SelectAll(false);
1793 SendKeyEvent(ui::VKEY_C
, true, false, true, false);
1794 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1795 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1796 SendKeyEvent(ui::VKEY_C
, false, true);
1797 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1798 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1800 // Ensure [Ctrl]+[Insert] copies.
1801 textfield_
->SetText(ASCIIToUTF16("345"));
1802 textfield_
->SelectAll(false);
1803 SendAlternateCopy();
1804 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1805 EXPECT_STR_EQ("345", textfield_
->text());
1806 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE
, GetAndResetCopiedToClipboard());
1808 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1809 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1810 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "abc");
1811 textfield_
->SetText(base::string16());
1812 EXPECT_TRUE(textfield_
->IsCommandIdEnabled(IDS_APP_PASTE
));
1813 textfield_
->ExecuteCommand(IDS_APP_PASTE
, 0);
1814 EXPECT_STR_EQ("abc", textfield_
->text());
1815 SendKeyEvent(ui::VKEY_V
, false, true);
1816 EXPECT_STR_EQ("abcabc", textfield_
->text());
1817 SendAlternatePaste();
1818 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1819 SendKeyEvent(ui::VKEY_V
, true, false, true, false);
1820 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1822 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1823 textfield_
->SelectAll(false);
1824 SendKeyEvent(ui::VKEY_INSERT
, true, true);
1825 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
));
1826 EXPECT_STR_EQ("abcabcabc", textfield_
->text());
1827 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
1830 TEST_F(TextfieldTest
, OvertypeMode
) {
1832 // Overtype mode should be disabled (no-op [Insert]).
1833 textfield_
->SetText(ASCIIToUTF16("2"));
1834 const bool shift
= false;
1835 SendHomeEvent(shift
);
1836 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1837 // since there is no overtype on toolkit-views, the behavior happens to match.
1838 // However, there's no enable-overtype equivalent key combination on OSX.
1839 SendKeyEvent(ui::VKEY_INSERT
);
1840 SendKeyEvent(ui::VKEY_1
, false, false);
1841 EXPECT_STR_EQ("12", textfield_
->text());
1844 TEST_F(TextfieldTest
, TextCursorDisplayTest
) {
1846 // LTR-RTL string in LTR context.
1848 EXPECT_STR_EQ("a", textfield_
->text());
1849 int x
= GetCursorBounds().x();
1853 EXPECT_STR_EQ("ab", textfield_
->text());
1854 x
= GetCursorBounds().x();
1855 EXPECT_LT(prev_x
, x
);
1858 SendKeyEvent(0x05E1);
1859 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1860 x
= GetCursorBounds().x();
1861 EXPECT_GE(1, std::abs(x
- prev_x
));
1863 SendKeyEvent(0x05E2);
1864 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1865 x
= GetCursorBounds().x();
1866 EXPECT_GE(1, std::abs(x
- prev_x
));
1869 SendKeyEvent(ui::VKEY_A
, false, true);
1870 SendKeyEvent(ui::VKEY_DELETE
);
1872 // RTL-LTR string in LTR context.
1873 SendKeyEvent(0x05E1);
1874 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1875 x
= GetCursorBounds().x();
1876 EXPECT_EQ(GetDisplayRect().x(), x
);
1879 SendKeyEvent(0x05E2);
1880 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1881 x
= GetCursorBounds().x();
1882 EXPECT_GE(1, std::abs(x
- prev_x
));
1885 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1886 x
= GetCursorBounds().x();
1887 EXPECT_LT(prev_x
, x
);
1891 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1892 x
= GetCursorBounds().x();
1893 EXPECT_LT(prev_x
, x
);
1896 TEST_F(TextfieldTest
, TextCursorDisplayInRTLTest
) {
1897 std::string locale
= l10n_util::GetApplicationLocale("");
1898 base::i18n::SetICUDefaultLocale("he");
1901 // LTR-RTL string in RTL context.
1903 EXPECT_STR_EQ("a", textfield_
->text());
1904 int x
= GetCursorBounds().x();
1905 EXPECT_EQ(GetDisplayRect().right() - 1, x
);
1909 EXPECT_STR_EQ("ab", textfield_
->text());
1910 x
= GetCursorBounds().x();
1911 EXPECT_GE(1, std::abs(x
- prev_x
));
1913 SendKeyEvent(0x05E1);
1914 EXPECT_EQ(WideToUTF16(L
"ab\x05E1"), textfield_
->text());
1915 x
= GetCursorBounds().x();
1916 EXPECT_GT(prev_x
, x
);
1919 SendKeyEvent(0x05E2);
1920 EXPECT_EQ(WideToUTF16(L
"ab\x05E1\x5E2"), textfield_
->text());
1921 x
= GetCursorBounds().x();
1922 EXPECT_GT(prev_x
, x
);
1925 SendKeyEvent(ui::VKEY_A
, false, true);
1926 SendKeyEvent(ui::VKEY_DELETE
);
1928 // RTL-LTR string in RTL context.
1929 SendKeyEvent(0x05E1);
1930 EXPECT_EQ(WideToUTF16(L
"\x05E1"), textfield_
->text());
1931 x
= GetCursorBounds().x();
1934 SendKeyEvent(0x05E2);
1935 EXPECT_EQ(WideToUTF16(L
"\x05E1\x05E2"), textfield_
->text());
1936 x
= GetCursorBounds().x();
1937 EXPECT_GT(prev_x
, x
);
1941 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"a"), textfield_
->text());
1942 x
= GetCursorBounds().x();
1943 EXPECT_GE(1, std::abs(x
- prev_x
));
1947 EXPECT_EQ(WideToUTF16(L
"\x05E1\x5E2" L
"ab"), textfield_
->text());
1948 x
= GetCursorBounds().x();
1949 EXPECT_GE(1, std::abs(x
- prev_x
));
1952 base::i18n::SetICUDefaultLocale(locale
);
1955 TEST_F(TextfieldTest
, HitInsideTextAreaTest
) {
1957 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
1958 std::vector
<gfx::Rect
> cursor_bounds
;
1960 // Save each cursor bound.
1961 gfx::SelectionModel
sel(0, gfx::CURSOR_FORWARD
);
1962 cursor_bounds
.push_back(GetCursorBounds(sel
));
1964 sel
= gfx::SelectionModel(1, gfx::CURSOR_BACKWARD
);
1965 gfx::Rect bound
= GetCursorBounds(sel
);
1966 sel
= gfx::SelectionModel(1, gfx::CURSOR_FORWARD
);
1967 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1968 cursor_bounds
.push_back(bound
);
1970 // Check that a cursor at the end of the Latin portion of the text is at the
1971 // same position as a cursor placed at the end of the RTL Hebrew portion.
1972 sel
= gfx::SelectionModel(2, gfx::CURSOR_BACKWARD
);
1973 bound
= GetCursorBounds(sel
);
1974 sel
= gfx::SelectionModel(4, gfx::CURSOR_BACKWARD
);
1975 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1976 cursor_bounds
.push_back(bound
);
1978 sel
= gfx::SelectionModel(3, gfx::CURSOR_BACKWARD
);
1979 bound
= GetCursorBounds(sel
);
1980 sel
= gfx::SelectionModel(3, gfx::CURSOR_FORWARD
);
1981 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1982 cursor_bounds
.push_back(bound
);
1984 sel
= gfx::SelectionModel(2, gfx::CURSOR_FORWARD
);
1985 bound
= GetCursorBounds(sel
);
1986 sel
= gfx::SelectionModel(4, gfx::CURSOR_FORWARD
);
1987 EXPECT_EQ(bound
.x(), GetCursorBounds(sel
).x());
1988 cursor_bounds
.push_back(bound
);
1990 // Expected cursor position when clicking left and right of each character.
1991 size_t cursor_pos_expected
[] = {0, 1, 1, 2, 4, 3, 3, 2};
1994 for (int i
= 0; i
< static_cast<int>(cursor_bounds
.size() - 1); ++i
) {
1995 int half_width
= (cursor_bounds
[i
+ 1].x() - cursor_bounds
[i
].x()) / 2;
1996 MouseClick(cursor_bounds
[i
], half_width
/ 2);
1997 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
1999 // To avoid trigger double click. Not using sleep() since it takes longer
2000 // for the test to run if using sleep().
2001 NonClientMouseClick();
2003 MouseClick(cursor_bounds
[i
+ 1], - (half_width
/ 2));
2004 EXPECT_EQ(cursor_pos_expected
[index
++], textfield_
->GetCursorPosition());
2006 NonClientMouseClick();
2010 TEST_F(TextfieldTest
, HitOutsideTextAreaTest
) {
2013 // LTR-RTL string in LTR context.
2014 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
2016 const bool shift
= false;
2017 SendHomeEvent(shift
);
2018 gfx::Rect bound
= GetCursorBounds();
2019 MouseClick(bound
, -10);
2020 EXPECT_EQ(bound
, GetCursorBounds());
2022 SendEndEvent(shift
);
2023 bound
= GetCursorBounds();
2024 MouseClick(bound
, 10);
2025 EXPECT_EQ(bound
, GetCursorBounds());
2027 NonClientMouseClick();
2029 // RTL-LTR string in LTR context.
2030 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
2032 SendHomeEvent(shift
);
2033 bound
= GetCursorBounds();
2034 MouseClick(bound
, 10);
2035 EXPECT_EQ(bound
, GetCursorBounds());
2037 SendEndEvent(shift
);
2038 bound
= GetCursorBounds();
2039 MouseClick(bound
, -10);
2040 EXPECT_EQ(bound
, GetCursorBounds());
2043 TEST_F(TextfieldTest
, HitOutsideTextAreaInRTLTest
) {
2044 std::string locale
= l10n_util::GetApplicationLocale("");
2045 base::i18n::SetICUDefaultLocale("he");
2049 // RTL-LTR string in RTL context.
2050 textfield_
->SetText(WideToUTF16(L
"\x05E1\x5E2" L
"ab"));
2051 const bool shift
= false;
2052 SendHomeEvent(shift
);
2053 gfx::Rect bound
= GetCursorBounds();
2054 MouseClick(bound
, 10);
2055 EXPECT_EQ(bound
, GetCursorBounds());
2057 SendEndEvent(shift
);
2058 bound
= GetCursorBounds();
2059 MouseClick(bound
, -10);
2060 EXPECT_EQ(bound
, GetCursorBounds());
2062 NonClientMouseClick();
2064 // LTR-RTL string in RTL context.
2065 textfield_
->SetText(WideToUTF16(L
"ab\x05E1\x5E2"));
2066 SendHomeEvent(shift
);
2067 bound
= GetCursorBounds();
2068 MouseClick(bound
, -10);
2069 EXPECT_EQ(bound
, GetCursorBounds());
2071 SendEndEvent(shift
);
2072 bound
= GetCursorBounds();
2073 MouseClick(bound
, 10);
2074 EXPECT_EQ(bound
, GetCursorBounds());
2077 base::i18n::SetICUDefaultLocale(locale
);
2080 TEST_F(TextfieldTest
, OverflowTest
) {
2084 for (int i
= 0; i
< 500; ++i
)
2086 SendKeyEvent(kHebrewLetterSamekh
);
2087 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2089 // Test mouse pointing.
2090 MouseClick(GetCursorBounds(), -1);
2091 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2094 SendKeyEvent(ui::VKEY_A
, false, true);
2095 SendKeyEvent(ui::VKEY_DELETE
);
2097 for (int i
= 0; i
< 500; ++i
)
2098 SendKeyEvent(kHebrewLetterSamekh
);
2100 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2102 MouseClick(GetCursorBounds(), -1);
2103 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2106 TEST_F(TextfieldTest
, OverflowInRTLTest
) {
2107 std::string locale
= l10n_util::GetApplicationLocale("");
2108 base::i18n::SetICUDefaultLocale("he");
2113 for (int i
= 0; i
< 500; ++i
)
2115 SendKeyEvent(kHebrewLetterSamekh
);
2116 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2118 MouseClick(GetCursorBounds(), 1);
2119 EXPECT_EQ(501U, textfield_
->GetCursorPosition());
2122 SendKeyEvent(ui::VKEY_A
, false, true);
2123 SendKeyEvent(ui::VKEY_DELETE
);
2125 for (int i
= 0; i
< 500; ++i
)
2126 SendKeyEvent(kHebrewLetterSamekh
);
2128 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2130 MouseClick(GetCursorBounds(), 1);
2131 EXPECT_EQ(500U, textfield_
->GetCursorPosition());
2134 base::i18n::SetICUDefaultLocale(locale
);
2137 TEST_F(TextfieldTest
, GetCompositionCharacterBoundsTest
) {
2139 ui::CompositionText composition
;
2140 composition
.text
= UTF8ToUTF16("abc123");
2141 const uint32 char_count
= static_cast<uint32
>(composition
.text
.length());
2142 ui::TextInputClient
* client
= textfield_
;
2144 // Compare the composition character bounds with surrounding cursor bounds.
2145 for (uint32 i
= 0; i
< char_count
; ++i
) {
2146 composition
.selection
= gfx::Range(i
);
2147 client
->SetCompositionText(composition
);
2148 gfx::Point cursor_origin
= GetCursorBounds().origin();
2149 views::View::ConvertPointToScreen(textfield_
, &cursor_origin
);
2151 composition
.selection
= gfx::Range(i
+ 1);
2152 client
->SetCompositionText(composition
);
2153 gfx::Point next_cursor_bottom_left
= GetCursorBounds().bottom_left();
2154 views::View::ConvertPointToScreen(textfield_
, &next_cursor_bottom_left
);
2156 gfx::Rect character
;
2157 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &character
));
2158 EXPECT_EQ(character
.origin(), cursor_origin
) << " i=" << i
;
2159 EXPECT_EQ(character
.bottom_right(), next_cursor_bottom_left
) << " i=" << i
;
2162 // Return false if the index is out of range.
2164 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
, &rect
));
2165 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 1, &rect
));
2166 EXPECT_FALSE(client
->GetCompositionCharacterBounds(char_count
+ 100, &rect
));
2169 TEST_F(TextfieldTest
, GetCompositionCharacterBounds_ComplexText
) {
2172 const base::char16 kUtf16Chars
[] = {
2175 // U+1F408 (CAT) as surrogate pair
2177 // U+5642 as Ideographic Variation Sequences
2178 0x5642, 0xDB40, 0xDD00,
2179 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
2184 const size_t kUtf16CharsCount
= arraysize(kUtf16Chars
);
2186 ui::CompositionText composition
;
2187 composition
.text
.assign(kUtf16Chars
, kUtf16Chars
+ kUtf16CharsCount
);
2188 ui::TextInputClient
* client
= textfield_
;
2189 client
->SetCompositionText(composition
);
2191 // Make sure GetCompositionCharacterBounds never fails for index.
2192 gfx::Rect rects
[kUtf16CharsCount
];
2193 gfx::Rect prev_cursor
= GetCursorBounds();
2194 for (uint32 i
= 0; i
< kUtf16CharsCount
; ++i
)
2195 EXPECT_TRUE(client
->GetCompositionCharacterBounds(i
, &rects
[i
]));
2197 // Here we might expect the following results but it actually depends on how
2198 // Uniscribe or HarfBuzz treats them with given font.
2199 // - rects[1] == rects[2]
2200 // - rects[3] == rects[4] == rects[5]
2201 // - rects[6] == rects[7]
2204 // The word we select by double clicking should remain selected regardless of
2205 // where we drag the mouse afterwards without releasing the left button.
2206 TEST_F(TextfieldTest
, KeepInitiallySelectedWord
) {
2209 textfield_
->SetText(ASCIIToUTF16("abc def ghi"));
2211 textfield_
->SelectRange(gfx::Range(5, 5));
2212 const gfx::Rect middle_cursor
= GetCursorBounds();
2213 textfield_
->SelectRange(gfx::Range(0, 0));
2214 const gfx::Point beginning
= GetCursorBounds().origin();
2216 // Double click, but do not release the left button.
2217 MouseClick(middle_cursor
, 0);
2218 const gfx::Point
middle(middle_cursor
.x(),
2219 middle_cursor
.y() + middle_cursor
.height() / 2);
2220 ui::MouseEvent
press_event(ui::ET_MOUSE_PRESSED
, middle
, middle
,
2221 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2222 ui::EF_LEFT_MOUSE_BUTTON
);
2223 textfield_
->OnMousePressed(press_event
);
2224 EXPECT_EQ(gfx::Range(4, 7), textfield_
->GetSelectedRange());
2226 // Drag the mouse to the beginning of the textfield.
2227 ui::MouseEvent
drag_event(ui::ET_MOUSE_DRAGGED
, beginning
, beginning
,
2228 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
, 0);
2229 textfield_
->OnMouseDragged(drag_event
);
2230 EXPECT_EQ(gfx::Range(7, 0), textfield_
->GetSelectedRange());
2233 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2234 // flaky: http://crbug.com/396477
2235 TEST_F(TextfieldTest
, DISABLED_SelectionClipboard
) {
2237 textfield_
->SetText(ASCIIToUTF16("0123"));
2238 gfx::Point
point_1(GetCursorPositionX(1), 0);
2239 gfx::Point
point_2(GetCursorPositionX(2), 0);
2240 gfx::Point
point_3(GetCursorPositionX(3), 0);
2241 gfx::Point
point_4(GetCursorPositionX(4), 0);
2243 // Text selected by the mouse should be placed on the selection clipboard.
2244 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, point_1
, point_1
,
2245 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2246 ui::EF_LEFT_MOUSE_BUTTON
);
2247 textfield_
->OnMousePressed(press
);
2248 ui::MouseEvent
drag(ui::ET_MOUSE_DRAGGED
, point_3
, point_3
,
2249 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2250 ui::EF_LEFT_MOUSE_BUTTON
);
2251 textfield_
->OnMouseDragged(drag
);
2252 ui::MouseEvent
release(ui::ET_MOUSE_RELEASED
, point_3
, point_3
,
2253 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2254 ui::EF_LEFT_MOUSE_BUTTON
);
2255 textfield_
->OnMouseReleased(release
);
2256 EXPECT_EQ(gfx::Range(1, 3), textfield_
->GetSelectedRange());
2257 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2259 // Select-all should update the selection clipboard.
2260 SendKeyEvent(ui::VKEY_A
, false, true);
2261 EXPECT_EQ(gfx::Range(0, 4), textfield_
->GetSelectedRange());
2262 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2263 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2265 // Shift-click selection modifications should update the clipboard.
2266 NonClientMouseClick();
2267 ui::MouseEvent
press_2(ui::ET_MOUSE_PRESSED
, point_2
, point_2
,
2268 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2269 ui::EF_LEFT_MOUSE_BUTTON
);
2270 press_2
.set_flags(press_2
.flags() | ui::EF_SHIFT_DOWN
);
2271 #if defined(USE_X11)
2272 ui::UpdateX11EventForFlags(&press_2
);
2274 textfield_
->OnMousePressed(press_2
);
2275 ui::MouseEvent
release_2(ui::ET_MOUSE_RELEASED
, point_2
, point_2
,
2276 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2277 ui::EF_LEFT_MOUSE_BUTTON
);
2278 textfield_
->OnMouseReleased(release_2
);
2279 EXPECT_EQ(gfx::Range(0, 2), textfield_
->GetSelectedRange());
2280 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2281 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2283 // Shift-Left/Right should update the selection clipboard.
2284 SendKeyEvent(ui::VKEY_RIGHT
, true, false);
2285 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2286 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2287 SendKeyEvent(ui::VKEY_LEFT
, true, false);
2288 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2289 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2290 SendKeyEvent(ui::VKEY_RIGHT
, true, true);
2291 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2292 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2294 // Moving the cursor without a selection should not change the clipboard.
2295 SendKeyEvent(ui::VKEY_LEFT
, false, false);
2296 EXPECT_EQ(gfx::Range(0, 0), textfield_
->GetSelectedRange());
2297 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2298 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2300 // Middle clicking should paste at the mouse (not cursor) location.
2301 // The cursor should be placed at the end of the pasted text.
2302 ui::MouseEvent
middle(ui::ET_MOUSE_PRESSED
, point_4
, point_4
,
2303 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON
,
2304 ui::EF_MIDDLE_MOUSE_BUTTON
);
2305 textfield_
->OnMousePressed(middle
);
2306 EXPECT_STR_EQ("01230123", textfield_
->text());
2307 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2308 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2310 // Middle clicking on an unfocused textfield should focus it and paste.
2311 textfield_
->GetFocusManager()->ClearFocus();
2312 EXPECT_FALSE(textfield_
->HasFocus());
2313 textfield_
->OnMousePressed(middle
);
2314 EXPECT_TRUE(textfield_
->HasFocus());
2315 EXPECT_STR_EQ("012301230123", textfield_
->text());
2316 EXPECT_EQ(gfx::Range(8, 8), textfield_
->GetSelectedRange());
2317 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2319 // Middle clicking with an empty selection clipboard should still focus.
2320 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, std::string());
2321 textfield_
->GetFocusManager()->ClearFocus();
2322 EXPECT_FALSE(textfield_
->HasFocus());
2323 textfield_
->OnMousePressed(middle
);
2324 EXPECT_TRUE(textfield_
->HasFocus());
2325 EXPECT_STR_EQ("012301230123", textfield_
->text());
2326 EXPECT_EQ(gfx::Range(4, 4), textfield_
->GetSelectedRange());
2327 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2329 // Middle clicking in the selection should clear the clipboard and selection.
2330 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE
, "foo");
2331 textfield_
->SelectRange(gfx::Range(2, 6));
2332 textfield_
->OnMousePressed(middle
);
2333 EXPECT_STR_EQ("012301230123", textfield_
->text());
2334 EXPECT_EQ(gfx::Range(6, 6), textfield_
->GetSelectedRange());
2335 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
).empty());
2337 // Double and triple clicking should update the clipboard contents.
2338 textfield_
->SetText(ASCIIToUTF16("ab cd ef"));
2339 gfx::Point
word(GetCursorPositionX(4), 0);
2340 ui::MouseEvent
press_word(ui::ET_MOUSE_PRESSED
, word
, word
,
2341 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2342 ui::EF_LEFT_MOUSE_BUTTON
);
2343 textfield_
->OnMousePressed(press_word
);
2344 ui::MouseEvent
release_word(ui::ET_MOUSE_RELEASED
, word
, word
,
2345 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2346 ui::EF_LEFT_MOUSE_BUTTON
);
2347 textfield_
->OnMouseReleased(release_word
);
2348 ui::MouseEvent
double_click(ui::ET_MOUSE_PRESSED
, word
, word
,
2349 ui::EventTimeForNow(),
2350 ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_IS_DOUBLE_CLICK
,
2351 ui::EF_LEFT_MOUSE_BUTTON
);
2352 textfield_
->OnMousePressed(double_click
);
2353 textfield_
->OnMouseReleased(release_word
);
2354 EXPECT_EQ(gfx::Range(3, 5), textfield_
->GetSelectedRange());
2355 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2356 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2357 textfield_
->OnMousePressed(press_word
);
2358 textfield_
->OnMouseReleased(release_word
);
2359 EXPECT_EQ(gfx::Range(0, 8), textfield_
->GetSelectedRange());
2360 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2361 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION
, GetAndResetCopiedToClipboard());
2363 // Selecting a range of text without any user interaction should not change
2364 // the clipboard content.
2365 textfield_
->SelectRange(gfx::Range(0, 3));
2366 EXPECT_STR_EQ("ab ", textfield_
->GetSelectedText());
2367 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2368 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2370 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
, "other");
2371 textfield_
->SelectAll(false);
2372 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION
));
2373 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST
, GetAndResetCopiedToClipboard());
2377 // Long_Press gesture in Textfield can initiate a drag and drop now.
2378 TEST_F(TextfieldTest
, TestLongPressInitiatesDragDrop
) {
2380 textfield_
->SetText(ASCIIToUTF16("Hello string world"));
2382 // Ensure the textfield will provide selected text for drag data.
2383 textfield_
->SelectRange(gfx::Range(6, 12));
2384 const gfx::Point
kStringPoint(GetCursorPositionX(9), 0);
2386 // Enable touch-drag-drop to make long press effective.
2387 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2388 switches::kEnableTouchDragDrop
);
2390 // Create a long press event in the selected region should start a drag.
2391 GestureEventForTest
long_press(
2394 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2395 textfield_
->OnGestureEvent(&long_press
);
2396 EXPECT_TRUE(textfield_
->CanStartDragForView(NULL
, kStringPoint
,
2400 TEST_F(TextfieldTest
, GetTextfieldBaseline_FontFallbackTest
) {
2402 textfield_
->SetText(UTF8ToUTF16("abc"));
2403 const int old_baseline
= textfield_
->GetBaseline();
2405 // Set text which may fall back to a font which has taller baseline than
2406 // the default font.
2407 textfield_
->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2408 const int new_baseline
= textfield_
->GetBaseline();
2410 // Regardless of the text, the baseline must be the same.
2411 EXPECT_EQ(new_baseline
, old_baseline
);
2414 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2415 // controller and it does not crash.
2416 TEST_F(TextfieldTest
, DestroyingTextfieldFromOnKeyEvent
) {
2419 // The controller assumes ownership of the textfield.
2420 TextfieldDestroyerController
controller(textfield_
);
2421 EXPECT_TRUE(controller
.target());
2423 // Send a key to trigger OnKeyEvent().
2424 SendKeyEvent(ui::VKEY_RETURN
);
2426 EXPECT_FALSE(controller
.target());
2429 class TextfieldTouchSelectionTest
: public TextfieldTest
{
2432 void SetUp() override
{
2433 TextfieldTest::SetUp();
2434 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2435 switches::kEnableTouchEditing
);
2439 // Simulates a complete tap.
2440 void Tap(const gfx::Point
& point
) {
2441 GestureEventForTest
begin(
2442 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN
));
2443 textfield_
->OnGestureEvent(&begin
);
2445 GestureEventForTest
tap_down(
2446 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2447 textfield_
->OnGestureEvent(&tap_down
);
2449 GestureEventForTest
show_press(
2452 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS
));
2453 textfield_
->OnGestureEvent(&show_press
);
2455 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2456 tap_details
.set_tap_count(1);
2457 GestureEventForTest
tap(point
.x(), point
.y(), tap_details
);
2458 textfield_
->OnGestureEvent(&tap
);
2460 GestureEventForTest
end(
2461 point
.x(), point
.y(), ui::GestureEventDetails(ui::ET_GESTURE_END
));
2462 textfield_
->OnGestureEvent(&end
);
2467 // Touch selection and dragging currently only works for chromeos.
2468 #if defined(OS_CHROMEOS)
2469 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionAndDraggingTest
) {
2471 textfield_
->SetText(ASCIIToUTF16("hello world"));
2472 EXPECT_FALSE(test_api_
->touch_selection_controller());
2473 const int x
= GetCursorPositionX(2);
2475 // Tapping on the textfield should turn on the TouchSelectionController.
2476 ui::GestureEventDetails
tap_details(ui::ET_GESTURE_TAP
);
2477 tap_details
.set_tap_count(1);
2478 GestureEventForTest
tap(x
, 0, tap_details
);
2479 textfield_
->OnGestureEvent(&tap
);
2480 EXPECT_TRUE(test_api_
->touch_selection_controller());
2482 // Un-focusing the textfield should reset the TouchSelectionController
2483 textfield_
->GetFocusManager()->ClearFocus();
2484 EXPECT_FALSE(test_api_
->touch_selection_controller());
2485 textfield_
->RequestFocus();
2487 // With touch editing enabled, long press should not show context menu.
2488 // Instead, select word and invoke TouchSelectionController.
2489 GestureEventForTest
long_press_1(
2490 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2491 textfield_
->OnGestureEvent(&long_press_1
);
2492 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2493 EXPECT_TRUE(test_api_
->touch_selection_controller());
2494 EXPECT_TRUE(long_press_1
.handled());
2496 // With touch drag drop enabled, long pressing in the selected region should
2497 // start a drag and remove TouchSelectionController.
2498 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2499 GestureEventForTest
long_press_2(
2500 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2501 textfield_
->OnGestureEvent(&long_press_2
);
2502 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2503 EXPECT_FALSE(test_api_
->touch_selection_controller());
2504 EXPECT_FALSE(long_press_2
.handled());
2506 // After disabling touch drag drop, long pressing again in the selection
2507 // region should not do anything.
2508 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2509 switches::kDisableTouchDragDrop
);
2510 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2511 GestureEventForTest
long_press_3(
2512 x
, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS
));
2513 textfield_
->OnGestureEvent(&long_press_3
);
2514 EXPECT_STR_EQ("hello", textfield_
->GetSelectedText());
2515 EXPECT_FALSE(test_api_
->touch_selection_controller());
2516 EXPECT_FALSE(long_press_3
.handled());
2520 TEST_F(TextfieldTouchSelectionTest
, TouchSelectionInUnfocusableTextfield
) {
2522 textfield_
->SetText(ASCIIToUTF16("hello world"));
2523 gfx::Point
touch_point(GetCursorPositionX(2), 0);
2525 // Disable textfield and tap on it. Touch text selection should not get
2527 textfield_
->SetEnabled(false);
2529 EXPECT_FALSE(test_api_
->touch_selection_controller());
2530 textfield_
->SetEnabled(true);
2532 // Make textfield unfocusable and tap on it. Touch text selection should not
2534 textfield_
->SetFocusable(false);
2536 EXPECT_FALSE(textfield_
->HasFocus());
2537 EXPECT_FALSE(test_api_
->touch_selection_controller());
2538 textfield_
->SetFocusable(true);
2541 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2542 #if defined(OS_MACOSX) && !defined(USE_AURA)
2543 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2545 #define MAYBE_TapOnSelection TapOnSelection
2548 TEST_F(TextfieldTouchSelectionTest
, MAYBE_TapOnSelection
) {
2550 textfield_
->SetText(ASCIIToUTF16("hello world"));
2551 gfx::Range
sel_range(2, 7);
2552 gfx::Range
tap_range(5, 5);
2553 gfx::Rect tap_rect
=
2554 GetCursorBounds(gfx::SelectionModel(tap_range
, gfx::CURSOR_FORWARD
));
2555 gfx::Point tap_point
= tap_rect
.CenterPoint();
2557 // Select range |sel_range| and check if touch selection handles are not
2558 // present and correct range is selected.
2559 textfield_
->SetSelectionRange(sel_range
);
2561 textfield_
->GetSelectionRange(&range
);
2562 EXPECT_FALSE(test_api_
->touch_selection_controller());
2563 EXPECT_EQ(sel_range
, range
);
2565 // Tap on selection and check if touch selectoin handles are shown, but
2566 // selection range is not modified.
2568 textfield_
->GetSelectionRange(&range
);
2569 EXPECT_TRUE(test_api_
->touch_selection_controller());
2570 EXPECT_EQ(sel_range
, range
);
2572 // Tap again on selection and check if touch selection handles are still
2573 // present and selection is changed to a cursor at tap location.
2575 textfield_
->GetSelectionRange(&range
);
2576 EXPECT_TRUE(test_api_
->touch_selection_controller());
2577 EXPECT_EQ(tap_range
, range
);
2580 TEST_F(TextfieldTest
, AccessiblePasswordTest
) {
2582 textfield_
->SetText(ASCIIToUTF16("password"));
2584 ui::AXViewState state_regular
;
2585 textfield_
->GetAccessibleState(&state_regular
);
2586 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_regular
.role
);
2587 EXPECT_EQ(ASCIIToUTF16("password"), state_regular
.value
);
2588 EXPECT_FALSE(state_regular
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2590 textfield_
->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD
);
2591 ui::AXViewState state_protected
;
2592 textfield_
->GetAccessibleState(&state_protected
);
2593 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD
, state_protected
.role
);
2594 EXPECT_EQ(ASCIIToUTF16("********"), state_protected
.value
);
2595 EXPECT_TRUE(state_protected
.HasStateFlag(ui::AX_STATE_PROTECTED
));
2598 } // namespace views