Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / ui / views / controls / textfield / textfield_unittest.cc
blob4bb9f54d45230ff2fe7f71b3538b43ab2dbdf7f3
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/controls/textfield/textfield.h"
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/command_line.h"
12 #include "base/pickle.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "ui/accessibility/ax_view_state.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/base/clipboard/scoped_clipboard_writer.h"
18 #include "ui/base/dragdrop/drag_drop_types.h"
19 #include "ui/base/ime/input_method_base.h"
20 #include "ui/base/ime/input_method_delegate.h"
21 #include "ui/base/ime/input_method_factory.h"
22 #include "ui/base/ime/text_input_client.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/base/ui_base_switches_util.h"
26 #include "ui/events/event.h"
27 #include "ui/events/event_processor.h"
28 #include "ui/events/event_utils.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
30 #include "ui/gfx/render_text.h"
31 #include "ui/strings/grit/ui_strings.h"
32 #include "ui/views/controls/textfield/textfield_controller.h"
33 #include "ui/views/controls/textfield/textfield_model.h"
34 #include "ui/views/controls/textfield/textfield_test_api.h"
35 #include "ui/views/focus/focus_manager.h"
36 #include "ui/views/test/test_views_delegate.h"
37 #include "ui/views/test/views_test_base.h"
38 #include "ui/views/test/widget_test.h"
39 #include "ui/views/widget/widget.h"
40 #include "url/gurl.h"
42 #if defined(OS_WIN)
43 #include "base/win/windows_version.h"
44 #endif
46 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
47 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
48 #endif
50 #if defined(USE_X11)
51 #include "ui/events/event_utils.h"
52 #endif
54 #if defined(OS_MACOSX) && !defined(USE_AURA)
55 #include "ui/events/test/event_generator.h"
56 #endif
58 using base::ASCIIToUTF16;
59 using base::UTF8ToUTF16;
60 using base::WideToUTF16;
62 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
64 namespace {
66 const base::char16 kHebrewLetterSamekh = 0x05E1;
68 class MockInputMethod : public ui::InputMethodBase {
69 public:
70 MockInputMethod();
71 ~MockInputMethod() override;
73 // Overridden from InputMethod:
74 bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
75 NativeEventResult* result) override;
76 void DispatchKeyEvent(ui::KeyEvent* key) override;
77 void OnTextInputTypeChanged(const ui::TextInputClient* client) override;
78 void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
79 void CancelComposition(const ui::TextInputClient* client) override;
80 void OnInputLocaleChanged() override {}
81 std::string GetInputLocale() override;
82 bool IsCandidatePopupOpen() const override;
83 void ShowImeIfNeeded() override {}
85 bool untranslated_ime_message_called() const {
86 return untranslated_ime_message_called_;
88 bool text_input_type_changed() const { return text_input_type_changed_; }
89 bool cancel_composition_called() const { return cancel_composition_called_; }
91 // Clears all internal states and result.
92 void Clear();
94 void SetCompositionTextForNextKey(const ui::CompositionText& composition);
95 void SetResultTextForNextKey(const base::string16& result);
97 private:
98 // Overridden from InputMethodBase.
99 void OnWillChangeFocusedClient(ui::TextInputClient* focused_before,
100 ui::TextInputClient* focused) override;
102 // Clears boolean states defined below.
103 void ClearStates();
105 // Whether a mock composition or result is scheduled for the next key event.
106 bool HasComposition();
108 // Clears only composition information and result text.
109 void ClearComposition();
111 // Composition information for the next key event. It'll be cleared
112 // automatically after dispatching the next key event.
113 ui::CompositionText composition_;
115 // Result text for the next key event. It'll be cleared automatically after
116 // dispatching the next key event.
117 base::string16 result_text_;
119 // Record call state of corresponding methods. They will be set to false
120 // automatically before dispatching a key event.
121 bool untranslated_ime_message_called_;
122 bool text_input_type_changed_;
123 bool cancel_composition_called_;
125 DISALLOW_COPY_AND_ASSIGN(MockInputMethod);
128 MockInputMethod::MockInputMethod()
129 : untranslated_ime_message_called_(false),
130 text_input_type_changed_(false),
131 cancel_composition_called_(false) {
134 MockInputMethod::~MockInputMethod() {
137 bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
138 NativeEventResult* result) {
139 if (result)
140 *result = NativeEventResult();
141 return false;
144 void MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
145 // Checks whether the key event is from EventGenerator on Windows which will
146 // generate key event for WM_CHAR.
147 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here.
148 if (key->is_char() && key->HasNativeEvent())
149 return;
151 bool handled = !IsTextInputTypeNone() && HasComposition();
152 ClearStates();
153 if (handled) {
154 DCHECK(!key->is_char());
155 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED,
156 ui::VKEY_PROCESSKEY,
157 key->flags());
158 DispatchKeyEventPostIME(&mock_key);
159 } else {
160 DispatchKeyEventPostIME(key);
163 ui::TextInputClient* client = GetTextInputClient();
164 if (client) {
165 if (handled) {
166 if (result_text_.length())
167 client->InsertText(result_text_);
168 if (composition_.text.length())
169 client->SetCompositionText(composition_);
170 else
171 client->ClearCompositionText();
172 } else if (key->type() == ui::ET_KEY_PRESSED) {
173 base::char16 ch = key->GetCharacter();
174 if (ch)
175 client->InsertChar(ch, key->flags());
179 ClearComposition();
182 void MockInputMethod::OnTextInputTypeChanged(
183 const ui::TextInputClient* client) {
184 if (IsTextInputClientFocused(client))
185 text_input_type_changed_ = true;
186 InputMethodBase::OnTextInputTypeChanged(client);
189 void MockInputMethod::CancelComposition(const ui::TextInputClient* client) {
190 if (IsTextInputClientFocused(client)) {
191 cancel_composition_called_ = true;
192 ClearComposition();
196 std::string MockInputMethod::GetInputLocale() {
197 return "en-US";
200 bool MockInputMethod::IsCandidatePopupOpen() const {
201 return false;
204 void MockInputMethod::OnWillChangeFocusedClient(
205 ui::TextInputClient* focused_before,
206 ui::TextInputClient* focused) {
207 ui::TextInputClient* client = GetTextInputClient();
208 if (client && client->HasCompositionText())
209 client->ConfirmCompositionText();
210 ClearComposition();
213 void MockInputMethod::Clear() {
214 ClearStates();
215 ClearComposition();
218 void MockInputMethod::SetCompositionTextForNextKey(
219 const ui::CompositionText& composition) {
220 composition_ = composition;
223 void MockInputMethod::SetResultTextForNextKey(const base::string16& result) {
224 result_text_ = result;
227 void MockInputMethod::ClearStates() {
228 untranslated_ime_message_called_ = false;
229 text_input_type_changed_ = false;
230 cancel_composition_called_ = false;
233 bool MockInputMethod::HasComposition() {
234 return composition_.text.length() || result_text_.length();
237 void MockInputMethod::ClearComposition() {
238 composition_.Clear();
239 result_text_.clear();
242 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
243 class TestTextfield : public views::Textfield {
244 public:
245 TestTextfield()
246 : Textfield(),
247 key_handled_(false),
248 key_received_(false),
249 weak_ptr_factory_(this) {}
251 bool OnKeyPressed(const ui::KeyEvent& e) override {
252 key_received_ = true;
254 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
255 // verify it isn't null before writing the bool value to key_handled_.
256 base::WeakPtr<TestTextfield> textfield(weak_ptr_factory_.GetWeakPtr());
257 bool key = views::Textfield::OnKeyPressed(e);
259 if (!textfield)
260 return key;
262 key_handled_ = key;
264 return key_handled_;
267 bool OnKeyReleased(const ui::KeyEvent& e) override {
268 key_received_ = true;
269 key_handled_ = views::Textfield::OnKeyReleased(e);
270 EXPECT_FALSE(key_handled_); // Textfield doesn't override OnKeyReleased.
271 return key_handled_;
274 // ui::TextInputClient overrides:
275 void InsertChar(base::char16 ch, int flags) override {
276 views::Textfield::InsertChar(ch, flags);
277 #if defined(OS_MACOSX)
278 // On Mac, characters are inserted directly rather than attempting to get a
279 // unicode character from the ui::KeyEvent (which isn't always possible).
280 key_received_ = true;
281 #endif
284 bool key_handled() const { return key_handled_; }
285 bool key_received() const { return key_received_; }
287 void clear() { key_received_ = key_handled_ = false; }
289 private:
290 bool key_handled_;
291 bool key_received_;
293 base::WeakPtrFactory<TestTextfield> weak_ptr_factory_;
295 DISALLOW_COPY_AND_ASSIGN(TestTextfield);
298 // Convenience to make constructing a GestureEvent simpler.
299 class GestureEventForTest : public ui::GestureEvent {
300 public:
301 GestureEventForTest(int x, int y, ui::GestureEventDetails details)
302 : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
304 private:
305 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
308 // This controller will happily destroy the target textfield passed on
309 // construction when a key event is triggered.
310 class TextfieldDestroyerController : public views::TextfieldController {
311 public:
312 explicit TextfieldDestroyerController(views::Textfield* target)
313 : target_(target) {
314 target_->set_controller(this);
317 views::Textfield* target() { return target_.get(); }
319 // views::TextfieldController:
320 bool HandleKeyEvent(views::Textfield* sender,
321 const ui::KeyEvent& key_event) override {
322 target_->OnBlur();
323 target_.reset();
324 return false;
327 private:
328 scoped_ptr<views::Textfield> target_;
331 base::string16 GetClipboardText(ui::ClipboardType type) {
332 base::string16 text;
333 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
334 return text;
337 void SetClipboardText(ui::ClipboardType type, const std::string& text) {
338 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text));
341 } // namespace
343 namespace views {
345 class TextfieldTest : public ViewsTestBase, public TextfieldController {
346 public:
347 TextfieldTest()
348 : widget_(NULL),
349 textfield_(NULL),
350 model_(NULL),
351 input_method_(NULL),
352 on_before_user_action_(0),
353 on_after_user_action_(0),
354 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
355 input_method_ = new MockInputMethod();
356 ui::SetUpInputMethodForTesting(input_method_);
359 // ::testing::Test:
360 void TearDown() override {
361 if (widget_)
362 widget_->Close();
363 ViewsTestBase::TearDown();
366 ui::ClipboardType GetAndResetCopiedToClipboard() {
367 ui::ClipboardType clipboard_type = copied_to_clipboard_;
368 copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
369 return clipboard_type;
372 // TextfieldController:
373 void ContentsChanged(Textfield* sender,
374 const base::string16& new_contents) override {
375 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
376 // paste action did not change the content. So |new_contents| may match
377 // |last_contents_|. For more info, see http://crbug.com/79002
378 last_contents_ = new_contents;
381 void OnBeforeUserAction(Textfield* sender) override {
382 ++on_before_user_action_;
385 void OnAfterUserAction(Textfield* sender) override {
386 ++on_after_user_action_;
389 void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) override {
390 copied_to_clipboard_ = clipboard_type;
393 void InitTextfield() {
394 InitTextfields(1);
397 void InitTextfields(int count) {
398 ASSERT_FALSE(textfield_);
399 textfield_ = new TestTextfield();
400 textfield_->set_controller(this);
401 widget_ = new Widget();
403 // The widget type must be an activatable type, and we don't want to worry
404 // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
405 Widget::InitParams params =
406 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
408 params.bounds = gfx::Rect(100, 100, 100, 100);
409 widget_->Init(params);
410 input_method_->SetDelegate(
411 test::WidgetTest::GetInputMethodDelegateForWidget(widget_));
412 View* container = new View();
413 widget_->SetContentsView(container);
414 container->AddChildView(textfield_);
415 textfield_->SetBoundsRect(params.bounds);
416 textfield_->set_id(1);
417 test_api_.reset(new TextfieldTestApi(textfield_));
419 for (int i = 1; i < count; i++) {
420 Textfield* textfield = new Textfield();
421 container->AddChildView(textfield);
422 textfield->set_id(i + 1);
425 model_ = test_api_->model();
426 model_->ClearEditHistory();
428 // Since the window type is activatable, showing the widget will also
429 // activate it. Calling Activate directly is insufficient, since that does
430 // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
431 // widget and the textfield must have focus to properly handle input.
432 widget_->Show();
433 textfield_->RequestFocus();
435 // On Mac, activation is asynchronous since desktop widgets are used. We
436 // don't want parallel tests to steal active status either, so fake it.
437 #if defined(OS_MACOSX) && !defined(USE_AURA)
438 fake_activation_ = test::WidgetTest::FakeWidgetIsActiveAlways();
440 // This is only used on Mac. See comment regarding |event_generator_| below.
441 event_generator_.reset(
442 new ui::test::EventGenerator(GetContext(), widget_->GetNativeWindow()));
443 #endif
446 ui::MenuModel* GetContextMenuModel() {
447 test_api_->UpdateContextMenu();
448 return test_api_->context_menu_contents();
451 // True if native Mac keystrokes should be used (to avoid ifdef litter).
452 bool TestingNativeMac() {
453 #if defined(OS_MACOSX)
454 return true;
455 #else
456 return false;
457 #endif
460 bool TestingNativeCrOs() const {
461 #if defined(OS_CHROMEOS)
462 return true;
463 #else
464 return false;
465 #endif // defined(OS_CHROMEOS)
468 protected:
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);
475 #else
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);
480 #endif
483 void SendKeyEvent(ui::KeyboardCode key_code,
484 bool alt,
485 bool shift,
486 bool control_or_command,
487 bool caps_lock) {
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,
505 bool shift,
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) {
515 if (ch < 0x80) {
516 ui::KeyboardCode code =
517 ch == ' ' ? ui::VKEY_SPACE :
518 static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a');
519 SendKeyEvent(code);
520 } else {
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 */);
534 return;
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.
543 return;
545 SendKeyEvent(ui::VKEY_END, shift, false);
548 // Sends {delete, move, select} word {forward, backward}.
549 void SendWordEvent(ui::KeyboardCode key, bool shift) {
550 bool alt = false;
551 bool control = true;
552 bool caps = false;
553 if (TestingNativeMac()) {
554 // Use Alt+Left/Right/Backspace on native Mac.
555 alt = true;
556 control = false;
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);
565 else
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);
573 else
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);
581 else
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,
637 bool can_undo,
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.
651 Widget* widget_;
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_;
669 private:
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_;
675 #endif
677 DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
680 TEST_F(TextfieldTest, ModelChangesTest) {
681 InitTextfield();
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) {
704 InitTextfield();
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());
718 else
719 EXPECT_STR_EQ("TexT!1!1", textfield_->text());
722 TEST_F(TextfieldTest, KeysWithModifiersTest) {
723 InitTextfield();
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);
731 SendKeyPress(ui::VKEY_E, shift | altgr);
732 SendKeyPress(ui::VKEY_X, 0);
733 SendKeyPress(ui::VKEY_T, ctrl);
734 SendKeyPress(ui::VKEY_1, alt);
735 SendKeyPress(ui::VKEY_2, command);
736 SendKeyPress(ui::VKEY_3, 0);
737 SendKeyPress(ui::VKEY_4, 0);
739 if (TestingNativeCrOs())
740 EXPECT_STR_EQ("TEx34", textfield_->text());
741 else
742 EXPECT_STR_EQ("TEx234", textfield_->text());
745 TEST_F(TextfieldTest, ControlAndSelectTest) {
746 // Insert a test string in a textfield.
747 InitTextfield();
748 textfield_->SetText(ASCIIToUTF16("one two three"));
749 SendHomeEvent(false);
750 SendKeyEvent(ui::VKEY_RIGHT, true, false);
751 SendKeyEvent(ui::VKEY_RIGHT, true, false);
752 SendKeyEvent(ui::VKEY_RIGHT, true, false);
754 EXPECT_STR_EQ("one", textfield_->GetSelectedText());
756 // Test word select.
757 SendWordEvent(ui::VKEY_RIGHT, true);
758 EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
759 SendWordEvent(ui::VKEY_RIGHT, true);
760 EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
761 SendWordEvent(ui::VKEY_LEFT, true);
762 EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
763 SendWordEvent(ui::VKEY_LEFT, true);
764 EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
766 // Replace the selected text.
767 SendKeyEvent(ui::VKEY_Z, true, false);
768 SendKeyEvent(ui::VKEY_E, true, false);
769 SendKeyEvent(ui::VKEY_R, true, false);
770 SendKeyEvent(ui::VKEY_O, true, false);
771 SendKeyEvent(ui::VKEY_SPACE, false, false);
772 EXPECT_STR_EQ("ZERO two three", textfield_->text());
774 SendEndEvent(true);
775 EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
776 SendHomeEvent(true);
777 EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
780 TEST_F(TextfieldTest, InsertionDeletionTest) {
781 // Insert a test string in a textfield.
782 InitTextfield();
783 for (size_t i = 0; i < 10; i++)
784 SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
785 EXPECT_STR_EQ("abcdefghij", textfield_->text());
787 // Test the delete and backspace keys.
788 textfield_->SelectRange(gfx::Range(5));
789 for (int i = 0; i < 3; i++)
790 SendKeyEvent(ui::VKEY_BACK);
791 EXPECT_STR_EQ("abfghij", textfield_->text());
792 for (int i = 0; i < 3; i++)
793 SendKeyEvent(ui::VKEY_DELETE);
794 EXPECT_STR_EQ("abij", textfield_->text());
796 // Select all and replace with "k".
797 textfield_->SelectAll(false);
798 SendKeyEvent(ui::VKEY_K);
799 EXPECT_STR_EQ("k", textfield_->text());
801 // Delete the previous word from cursor.
802 bool shift = false;
803 textfield_->SetText(ASCIIToUTF16("one two three four"));
804 SendEndEvent(shift);
805 SendWordEvent(ui::VKEY_BACK, shift);
806 EXPECT_STR_EQ("one two three ", textfield_->text());
808 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
809 // and Mac.
810 SendWordEvent(ui::VKEY_LEFT, shift);
811 shift = true;
812 SendWordEvent(ui::VKEY_BACK, shift);
813 #if defined(OS_LINUX)
814 EXPECT_STR_EQ("three ", textfield_->text());
815 #else
816 EXPECT_STR_EQ("one three ", textfield_->text());
817 #endif
819 // Delete the next word from cursor.
820 textfield_->SetText(ASCIIToUTF16("one two three four"));
821 shift = false;
822 SendHomeEvent(shift);
823 SendWordEvent(ui::VKEY_DELETE, shift);
824 EXPECT_STR_EQ(" two three four", textfield_->text());
826 // Delete to a line break on Linux and ChromeOS, to a word break on Windows
827 // and Mac.
828 SendWordEvent(ui::VKEY_RIGHT, shift);
829 shift = true;
830 SendWordEvent(ui::VKEY_DELETE, shift);
831 #if defined(OS_LINUX)
832 EXPECT_STR_EQ(" two", textfield_->text());
833 #else
834 EXPECT_STR_EQ(" two four", textfield_->text());
835 #endif
838 TEST_F(TextfieldTest, PasswordTest) {
839 InitTextfield();
840 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
841 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
842 EXPECT_TRUE(textfield_->enabled());
843 EXPECT_TRUE(textfield_->IsFocusable());
845 last_contents_.clear();
846 textfield_->SetText(ASCIIToUTF16("password"));
847 // Ensure text() and the callback returns the actual text instead of "*".
848 EXPECT_STR_EQ("password", textfield_->text());
849 EXPECT_TRUE(last_contents_.empty());
850 model_->SelectAll(false);
851 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
853 // Cut and copy should be disabled.
854 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
855 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
856 SendKeyEvent(ui::VKEY_X, false, true);
857 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
858 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
859 SendKeyEvent(ui::VKEY_C, false, true);
860 SendAlternateCopy();
861 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
862 EXPECT_STR_EQ("password", textfield_->text());
863 // [Shift]+[Delete] should just delete without copying text to the clipboard.
864 textfield_->SelectAll(false);
865 SendKeyEvent(ui::VKEY_DELETE, true, false);
867 // Paste should work normally.
868 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
869 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
870 SendKeyEvent(ui::VKEY_V, false, true);
871 SendAlternatePaste();
872 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
873 EXPECT_STR_EQ("foofoofoo", textfield_->text());
876 TEST_F(TextfieldTest, TextInputType) {
877 InitTextfield();
879 // Defaults to TEXT
880 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
882 // And can be set.
883 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
884 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
885 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
886 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
888 // Readonly textfields have type NONE
889 textfield_->SetReadOnly(true);
890 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
892 textfield_->SetReadOnly(false);
893 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
895 // As do disabled textfields
896 textfield_->SetEnabled(false);
897 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
899 textfield_->SetEnabled(true);
900 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
903 TEST_F(TextfieldTest, OnKeyPress) {
904 InitTextfield();
906 // Character keys are handled by the input method.
907 SendKeyEvent(ui::VKEY_A);
908 EXPECT_TRUE(textfield_->key_received());
909 EXPECT_FALSE(textfield_->key_handled());
910 textfield_->clear();
912 // Arrow keys and home/end are handled by the textfield.
913 SendKeyEvent(ui::VKEY_LEFT);
914 EXPECT_TRUE(textfield_->key_received());
915 EXPECT_TRUE(textfield_->key_handled());
916 textfield_->clear();
918 SendKeyEvent(ui::VKEY_RIGHT);
919 EXPECT_TRUE(textfield_->key_received());
920 EXPECT_TRUE(textfield_->key_handled());
921 textfield_->clear();
923 const bool shift = false;
924 SendHomeEvent(shift);
925 EXPECT_TRUE(textfield_->key_received());
926 EXPECT_TRUE(textfield_->key_handled());
927 textfield_->clear();
929 SendEndEvent(shift);
930 EXPECT_TRUE(textfield_->key_received());
931 EXPECT_TRUE(textfield_->key_handled());
932 textfield_->clear();
934 // F20, up/down key won't be handled.
935 SendKeyEvent(ui::VKEY_F20);
936 #if defined(OS_MACOSX)
937 // On Mac, key combinations that don't map to editing commands are forwarded
938 // on to the next responder, usually ending up at the window, which will beep.
939 EXPECT_FALSE(textfield_->key_received());
940 #else
941 EXPECT_TRUE(textfield_->key_received());
942 #endif
943 EXPECT_FALSE(textfield_->key_handled());
944 textfield_->clear();
946 SendKeyEvent(ui::VKEY_UP);
947 EXPECT_TRUE(textfield_->key_received());
948 EXPECT_FALSE(textfield_->key_handled());
949 textfield_->clear();
951 SendKeyEvent(ui::VKEY_DOWN);
952 EXPECT_TRUE(textfield_->key_received());
953 EXPECT_FALSE(textfield_->key_handled());
954 textfield_->clear();
957 // Tests that default key bindings are handled even with a delegate installed.
958 TEST_F(TextfieldTest, OnKeyPressBinding) {
959 InitTextfield();
961 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
962 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
963 class TestDelegate : public ui::TextEditKeyBindingsDelegateAuraLinux {
964 public:
965 TestDelegate() {}
966 ~TestDelegate() override {}
968 bool MatchEvent(
969 const ui::Event& event,
970 std::vector<ui::TextEditCommandAuraLinux>* commands) override {
971 return false;
974 private:
975 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
978 TestDelegate delegate;
979 ui::SetTextEditKeyBindingsDelegate(&delegate);
980 #endif
982 SendKeyEvent(ui::VKEY_A, false, false);
983 EXPECT_STR_EQ("a", textfield_->text());
984 textfield_->clear();
986 // Undo/Redo command keys are handled by the textfield.
987 SendKeyEvent(ui::VKEY_Z, false, true);
988 EXPECT_TRUE(textfield_->key_received());
989 EXPECT_TRUE(textfield_->key_handled());
990 EXPECT_TRUE(textfield_->text().empty());
991 textfield_->clear();
993 SendKeyEvent(ui::VKEY_Z, true, true);
994 EXPECT_TRUE(textfield_->key_received());
995 EXPECT_TRUE(textfield_->key_handled());
996 EXPECT_STR_EQ("a", textfield_->text());
997 textfield_->clear();
999 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1000 ui::SetTextEditKeyBindingsDelegate(NULL);
1001 #endif
1004 TEST_F(TextfieldTest, CursorMovement) {
1005 InitTextfield();
1007 // Test with trailing whitespace.
1008 textfield_->SetText(ASCIIToUTF16("one two hre "));
1010 // Send the cursor at the end.
1011 SendKeyEvent(ui::VKEY_END);
1013 // Ctrl+Left should move the cursor just before the last word.
1014 const bool shift = false;
1015 SendWordEvent(ui::VKEY_LEFT, shift);
1016 SendKeyEvent(ui::VKEY_T);
1017 EXPECT_STR_EQ("one two thre ", textfield_->text());
1018 EXPECT_STR_EQ("one two thre ", last_contents_);
1020 // Ctrl+Right should move the cursor to the end of the last word.
1021 SendWordEvent(ui::VKEY_RIGHT, shift);
1022 SendKeyEvent(ui::VKEY_E);
1023 EXPECT_STR_EQ("one two three ", textfield_->text());
1024 EXPECT_STR_EQ("one two three ", last_contents_);
1026 // Ctrl+Right again should move the cursor to the end.
1027 SendWordEvent(ui::VKEY_RIGHT, shift);
1028 SendKeyEvent(ui::VKEY_BACK);
1029 EXPECT_STR_EQ("one two three", textfield_->text());
1030 EXPECT_STR_EQ("one two three", last_contents_);
1032 // Test with leading whitespace.
1033 textfield_->SetText(ASCIIToUTF16(" ne two"));
1035 // Send the cursor at the beginning.
1036 SendHomeEvent(shift);
1038 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
1039 // first word.
1040 SendWordEvent(ui::VKEY_RIGHT, shift);
1041 SendWordEvent(ui::VKEY_LEFT, shift);
1042 SendKeyEvent(ui::VKEY_O);
1043 EXPECT_STR_EQ(" one two", textfield_->text());
1044 EXPECT_STR_EQ(" one two", last_contents_);
1046 // Ctrl+Left to move the cursor to the beginning of the first word.
1047 SendWordEvent(ui::VKEY_LEFT, shift);
1048 // Ctrl+Left again should move the cursor back to the very beginning.
1049 SendWordEvent(ui::VKEY_LEFT, shift);
1050 SendKeyEvent(ui::VKEY_DELETE);
1051 EXPECT_STR_EQ("one two", textfield_->text());
1052 EXPECT_STR_EQ("one two", last_contents_);
1055 TEST_F(TextfieldTest, FocusTraversalTest) {
1056 InitTextfields(3);
1057 textfield_->RequestFocus();
1059 EXPECT_EQ(1, GetFocusedView()->id());
1060 widget_->GetFocusManager()->AdvanceFocus(false);
1061 EXPECT_EQ(2, GetFocusedView()->id());
1062 widget_->GetFocusManager()->AdvanceFocus(false);
1063 EXPECT_EQ(3, GetFocusedView()->id());
1064 // Cycle back to the first textfield.
1065 widget_->GetFocusManager()->AdvanceFocus(false);
1066 EXPECT_EQ(1, GetFocusedView()->id());
1068 widget_->GetFocusManager()->AdvanceFocus(true);
1069 EXPECT_EQ(3, GetFocusedView()->id());
1070 widget_->GetFocusManager()->AdvanceFocus(true);
1071 EXPECT_EQ(2, GetFocusedView()->id());
1072 widget_->GetFocusManager()->AdvanceFocus(true);
1073 EXPECT_EQ(1, GetFocusedView()->id());
1074 // Cycle back to the last textfield.
1075 widget_->GetFocusManager()->AdvanceFocus(true);
1076 EXPECT_EQ(3, GetFocusedView()->id());
1078 // Request focus should still work.
1079 textfield_->RequestFocus();
1080 EXPECT_EQ(1, GetFocusedView()->id());
1082 // Test if clicking on textfield view sets the focus.
1083 widget_->GetFocusManager()->AdvanceFocus(true);
1084 EXPECT_EQ(3, GetFocusedView()->id());
1085 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1086 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1087 ui::EF_LEFT_MOUSE_BUTTON);
1088 textfield_->OnMousePressed(click);
1089 EXPECT_EQ(1, GetFocusedView()->id());
1091 // Tab/Shift+Tab should also cycle focus, not insert a tab character.
1092 SendKeyEvent(ui::VKEY_TAB, false, false);
1093 EXPECT_EQ(2, GetFocusedView()->id());
1094 SendKeyEvent(ui::VKEY_TAB, false, false);
1095 EXPECT_EQ(3, GetFocusedView()->id());
1096 // Cycle back to the first textfield.
1097 SendKeyEvent(ui::VKEY_TAB, false, false);
1098 EXPECT_EQ(1, GetFocusedView()->id());
1100 SendKeyEvent(ui::VKEY_TAB, true, false);
1101 EXPECT_EQ(3, GetFocusedView()->id());
1102 SendKeyEvent(ui::VKEY_TAB, true, false);
1103 EXPECT_EQ(2, GetFocusedView()->id());
1104 SendKeyEvent(ui::VKEY_TAB, true, false);
1105 EXPECT_EQ(1, GetFocusedView()->id());
1106 // Cycle back to the last textfield.
1107 SendKeyEvent(ui::VKEY_TAB, true, false);
1108 EXPECT_EQ(3, GetFocusedView()->id());
1111 TEST_F(TextfieldTest, ContextMenuDisplayTest) {
1112 InitTextfield();
1113 EXPECT_TRUE(textfield_->context_menu_controller());
1114 textfield_->SetText(ASCIIToUTF16("hello world"));
1115 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
1116 textfield_->ClearEditHistory();
1117 EXPECT_TRUE(GetContextMenuModel());
1118 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
1120 textfield_->SelectAll(false);
1121 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
1123 SendKeyEvent(ui::VKEY_T);
1124 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
1126 textfield_->SelectAll(false);
1127 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1129 // Exercise the "paste enabled?" check in the verifier.
1130 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1131 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
1134 TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
1135 InitTextfield();
1136 textfield_->SetText(ASCIIToUTF16("hello world"));
1137 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1138 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1139 ui::EF_LEFT_MOUSE_BUTTON);
1140 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
1141 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1142 ui::EF_LEFT_MOUSE_BUTTON);
1143 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
1144 ui::EventTimeForNow(),
1145 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
1146 ui::EF_LEFT_MOUSE_BUTTON);
1148 // Test for double click.
1149 textfield_->OnMousePressed(click);
1150 textfield_->OnMouseReleased(release);
1151 EXPECT_TRUE(textfield_->GetSelectedText().empty());
1152 textfield_->OnMousePressed(double_click);
1153 textfield_->OnMouseReleased(release);
1154 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1156 // Test for triple click.
1157 textfield_->OnMousePressed(click);
1158 textfield_->OnMouseReleased(release);
1159 EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
1161 // Another click should reset back to double click.
1162 textfield_->OnMousePressed(click);
1163 textfield_->OnMouseReleased(release);
1164 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1167 TEST_F(TextfieldTest, DragToSelect) {
1168 InitTextfield();
1169 textfield_->SetText(ASCIIToUTF16("hello world"));
1170 const int kStart = GetCursorPositionX(5);
1171 const int kEnd = 500;
1172 gfx::Point start_point(kStart, 0);
1173 gfx::Point end_point(kEnd, 0);
1174 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point,
1175 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1176 ui::EF_LEFT_MOUSE_BUTTON);
1177 ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point,
1178 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1179 ui::EF_LEFT_MOUSE_BUTTON);
1180 ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(),
1181 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1182 ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point,
1183 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1184 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point,
1185 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1186 ui::EF_LEFT_MOUSE_BUTTON);
1187 textfield_->OnMousePressed(click_a);
1188 EXPECT_TRUE(textfield_->GetSelectedText().empty());
1189 // Check that dragging left selects the beginning of the string.
1190 textfield_->OnMouseDragged(drag_left);
1191 base::string16 text_left = textfield_->GetSelectedText();
1192 EXPECT_STR_EQ("hello", text_left);
1193 // Check that dragging right selects the rest of the string.
1194 textfield_->OnMouseDragged(drag_right);
1195 base::string16 text_right = textfield_->GetSelectedText();
1196 EXPECT_STR_EQ(" world", text_right);
1197 // Check that releasing in the same location does not alter the selection.
1198 textfield_->OnMouseReleased(release);
1199 EXPECT_EQ(text_right, textfield_->GetSelectedText());
1200 // Check that dragging from beyond the text length works too.
1201 textfield_->OnMousePressed(click_b);
1202 textfield_->OnMouseDragged(drag_left);
1203 textfield_->OnMouseReleased(release);
1204 EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText());
1207 #if defined(OS_WIN)
1208 TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
1209 InitTextfield();
1210 textfield_->SetText(ASCIIToUTF16("hello world"));
1212 ui::OSExchangeData data;
1213 base::string16 string(ASCIIToUTF16("string "));
1214 data.SetString(string);
1215 int formats = 0;
1216 std::set<OSExchangeData::CustomFormat> custom_formats;
1218 // Ensure that disabled textfields do not accept drops.
1219 textfield_->SetEnabled(false);
1220 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
1221 EXPECT_EQ(0, formats);
1222 EXPECT_TRUE(custom_formats.empty());
1223 EXPECT_FALSE(textfield_->CanDrop(data));
1224 textfield_->SetEnabled(true);
1226 // Ensure that read-only textfields do not accept drops.
1227 textfield_->SetReadOnly(true);
1228 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
1229 EXPECT_EQ(0, formats);
1230 EXPECT_TRUE(custom_formats.empty());
1231 EXPECT_FALSE(textfield_->CanDrop(data));
1232 textfield_->SetReadOnly(false);
1234 // Ensure that enabled and editable textfields do accept drops.
1235 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1236 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1237 EXPECT_TRUE(custom_formats.empty());
1238 EXPECT_TRUE(textfield_->CanDrop(data));
1239 gfx::Point drop_point(GetCursorPositionX(6), 0);
1240 ui::DropTargetEvent drop(data, drop_point, drop_point,
1241 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE);
1242 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
1243 textfield_->OnDragUpdated(drop));
1244 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_->OnPerformDrop(drop));
1245 EXPECT_STR_EQ("hello string world", textfield_->text());
1247 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
1248 ui::OSExchangeData bad_data;
1249 bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
1250 ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType();
1251 bad_data.SetPickledData(fmt, base::Pickle());
1252 bad_data.SetFileContents(base::FilePath(L"x"), "x");
1253 bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
1254 ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL);
1255 bad_data.SetDownloadFileInfo(download);
1256 EXPECT_FALSE(textfield_->CanDrop(bad_data));
1258 #endif
1260 TEST_F(TextfieldTest, DragAndDrop_InitiateDrag) {
1261 InitTextfield();
1262 textfield_->SetText(ASCIIToUTF16("hello string world"));
1264 // Ensure the textfield will provide selected text for drag data.
1265 base::string16 string;
1266 ui::OSExchangeData data;
1267 const gfx::Range kStringRange(6, 12);
1268 textfield_->SelectRange(kStringRange);
1269 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
1270 textfield_->WriteDragDataForView(NULL, kStringPoint, &data);
1271 EXPECT_TRUE(data.GetString(&string));
1272 EXPECT_EQ(textfield_->GetSelectedText(), string);
1274 // Ensure that disabled textfields do not support drag operations.
1275 textfield_->SetEnabled(false);
1276 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1277 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1278 textfield_->SetEnabled(true);
1279 // Ensure that textfields without selections do not support drag operations.
1280 textfield_->ClearSelection();
1281 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1282 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1283 textfield_->SelectRange(kStringRange);
1284 // Ensure that password textfields do not support drag operations.
1285 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1286 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1287 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1288 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
1289 // Ensure that textfields only initiate drag operations inside the selection.
1290 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint,
1291 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1292 ui::EF_LEFT_MOUSE_BUTTON);
1293 textfield_->OnMousePressed(press_event);
1294 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
1295 textfield_->GetDragOperationsForView(NULL, gfx::Point()));
1296 EXPECT_FALSE(textfield_->CanStartDragForView(NULL, gfx::Point(),
1297 gfx::Point()));
1298 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY,
1299 textfield_->GetDragOperationsForView(NULL, kStringPoint));
1300 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
1301 gfx::Point()));
1302 // Ensure that textfields support local moves.
1303 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1304 textfield_->GetDragOperationsForView(textfield_, kStringPoint));
1307 TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
1308 InitTextfield();
1309 textfield_->SetText(ASCIIToUTF16("hello world"));
1311 base::string16 string;
1312 ui::OSExchangeData data;
1313 int formats = 0;
1314 int operations = 0;
1315 std::set<OSExchangeData::CustomFormat> custom_formats;
1317 // Start dragging "ello".
1318 textfield_->SelectRange(gfx::Range(1, 5));
1319 gfx::Point point(GetCursorPositionX(3), 0);
1320 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1321 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1322 ui::EF_LEFT_MOUSE_BUTTON);
1323 textfield_->OnMousePressed(click_a);
1324 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1325 gfx::Point()));
1326 operations = textfield_->GetDragOperationsForView(textfield_,
1327 click_a.location());
1328 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1329 operations);
1330 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1331 EXPECT_TRUE(data.GetString(&string));
1332 EXPECT_EQ(textfield_->GetSelectedText(), string);
1333 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1334 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1335 EXPECT_TRUE(custom_formats.empty());
1337 // Drop "ello" after "w".
1338 const gfx::Point kDropPoint(GetCursorPositionX(7), 0);
1339 EXPECT_TRUE(textfield_->CanDrop(data));
1340 ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
1341 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1342 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1343 EXPECT_STR_EQ("h welloorld", textfield_->text());
1344 textfield_->OnDragDone();
1346 // Undo/Redo the drag&drop change.
1347 SendKeyEvent(ui::VKEY_Z, false, true);
1348 EXPECT_STR_EQ("hello world", textfield_->text());
1349 SendKeyEvent(ui::VKEY_Z, false, true);
1350 EXPECT_STR_EQ("", textfield_->text());
1351 SendKeyEvent(ui::VKEY_Z, false, true);
1352 EXPECT_STR_EQ("", textfield_->text());
1353 SendKeyEvent(ui::VKEY_Z, true, true);
1354 EXPECT_STR_EQ("hello world", textfield_->text());
1355 SendKeyEvent(ui::VKEY_Z, true, true);
1356 EXPECT_STR_EQ("h welloorld", textfield_->text());
1357 SendKeyEvent(ui::VKEY_Z, true, true);
1358 EXPECT_STR_EQ("h welloorld", textfield_->text());
1361 TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
1362 InitTextfield();
1363 textfield_->SetText(ASCIIToUTF16("hello world"));
1365 base::string16 string;
1366 ui::OSExchangeData data;
1367 int formats = 0;
1368 int operations = 0;
1369 std::set<OSExchangeData::CustomFormat> custom_formats;
1371 // Start dragging " worl".
1372 textfield_->SelectRange(gfx::Range(5, 10));
1373 gfx::Point point(GetCursorPositionX(7), 0);
1374 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1375 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1376 ui::EF_LEFT_MOUSE_BUTTON);
1377 textfield_->OnMousePressed(click_a);
1378 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1379 gfx::Point()));
1380 operations = textfield_->GetDragOperationsForView(textfield_,
1381 click_a.location());
1382 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1383 operations);
1384 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1385 EXPECT_TRUE(data.GetString(&string));
1386 EXPECT_EQ(textfield_->GetSelectedText(), string);
1387 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1388 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1389 EXPECT_TRUE(custom_formats.empty());
1391 // Drop " worl" after "h".
1392 EXPECT_TRUE(textfield_->CanDrop(data));
1393 gfx::Point drop_point(GetCursorPositionX(1), 0);
1394 ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
1395 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1396 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1397 EXPECT_STR_EQ("h worlellod", textfield_->text());
1398 textfield_->OnDragDone();
1400 // Undo/Redo the drag&drop change.
1401 SendKeyEvent(ui::VKEY_Z, false, true);
1402 EXPECT_STR_EQ("hello world", textfield_->text());
1403 SendKeyEvent(ui::VKEY_Z, false, true);
1404 EXPECT_STR_EQ("", textfield_->text());
1405 SendKeyEvent(ui::VKEY_Z, false, true);
1406 EXPECT_STR_EQ("", textfield_->text());
1407 SendKeyEvent(ui::VKEY_Z, true, true);
1408 EXPECT_STR_EQ("hello world", textfield_->text());
1409 SendKeyEvent(ui::VKEY_Z, true, true);
1410 EXPECT_STR_EQ("h worlellod", textfield_->text());
1411 SendKeyEvent(ui::VKEY_Z, true, true);
1412 EXPECT_STR_EQ("h worlellod", textfield_->text());
1415 TEST_F(TextfieldTest, DragAndDrop_Canceled) {
1416 InitTextfield();
1417 textfield_->SetText(ASCIIToUTF16("hello world"));
1419 // Start dragging "worl".
1420 textfield_->SelectRange(gfx::Range(6, 10));
1421 gfx::Point point(GetCursorPositionX(8), 0);
1422 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
1423 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1424 ui::EF_LEFT_MOUSE_BUTTON);
1425 textfield_->OnMousePressed(click);
1426 ui::OSExchangeData data;
1427 textfield_->WriteDragDataForView(NULL, click.location(), &data);
1428 EXPECT_TRUE(textfield_->CanDrop(data));
1429 // Drag the text over somewhere valid, outside the current selection.
1430 gfx::Point drop_point(GetCursorPositionX(2), 0);
1431 ui::DropTargetEvent drop(data, drop_point, drop_point,
1432 ui::DragDropTypes::DRAG_MOVE);
1433 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop));
1434 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1435 gfx::Point drag_point(GetCursorPositionX(9), 0);
1436 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point,
1437 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1438 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point,
1439 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1440 ui::EF_LEFT_MOUSE_BUTTON);
1441 textfield_->OnMouseDragged(drag);
1442 textfield_->OnMouseReleased(release);
1443 textfield_->OnDragDone();
1444 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text());
1447 TEST_F(TextfieldTest, ReadOnlyTest) {
1448 InitTextfield();
1449 textfield_->SetText(ASCIIToUTF16("read only"));
1450 textfield_->SetReadOnly(true);
1451 EXPECT_TRUE(textfield_->enabled());
1452 EXPECT_TRUE(textfield_->IsFocusable());
1454 bool shift = false;
1455 SendHomeEvent(shift);
1456 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1457 SendEndEvent(shift);
1458 EXPECT_EQ(9U, textfield_->GetCursorPosition());
1460 SendKeyEvent(ui::VKEY_LEFT, shift, false);
1461 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1462 SendWordEvent(ui::VKEY_LEFT, shift);
1463 EXPECT_EQ(5U, textfield_->GetCursorPosition());
1464 shift = true;
1465 SendWordEvent(ui::VKEY_LEFT, shift);
1466 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1467 EXPECT_STR_EQ("read ", textfield_->GetSelectedText());
1468 textfield_->SelectAll(false);
1469 EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
1471 // Cut should be disabled.
1472 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1473 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1474 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1475 SendKeyEvent(ui::VKEY_X, false, true);
1476 SendAlternateCut();
1477 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1478 EXPECT_STR_EQ("read only", textfield_->text());
1480 // Paste should be disabled.
1481 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1482 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1483 SendKeyEvent(ui::VKEY_V, false, true);
1484 SendAlternatePaste();
1485 EXPECT_STR_EQ("read only", textfield_->text());
1487 // Copy should work normally.
1488 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1489 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1490 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1491 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1492 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1493 SendKeyEvent(ui::VKEY_C, false, true);
1494 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1495 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1496 SendAlternateCopy();
1497 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1499 // SetText should work even in read only mode.
1500 textfield_->SetText(ASCIIToUTF16(" four five six "));
1501 EXPECT_STR_EQ(" four five six ", textfield_->text());
1503 textfield_->SelectAll(false);
1504 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1506 // Text field is unmodifiable and selection shouldn't change.
1507 SendKeyEvent(ui::VKEY_DELETE);
1508 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1509 SendKeyEvent(ui::VKEY_BACK);
1510 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1511 SendKeyEvent(ui::VKEY_T);
1512 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1515 TEST_F(TextfieldTest, TextInputClientTest) {
1516 InitTextfield();
1517 ui::TextInputClient* client = textfield_;
1518 EXPECT_TRUE(client);
1519 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType());
1521 textfield_->SetText(ASCIIToUTF16("0123456789"));
1522 gfx::Range range;
1523 EXPECT_TRUE(client->GetTextRange(&range));
1524 EXPECT_EQ(0U, range.start());
1525 EXPECT_EQ(10U, range.end());
1527 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4)));
1528 EXPECT_TRUE(client->GetSelectionRange(&range));
1529 EXPECT_EQ(gfx::Range(1, 4), range);
1531 base::string16 substring;
1532 EXPECT_TRUE(client->GetTextFromRange(range, &substring));
1533 EXPECT_STR_EQ("123", substring);
1535 EXPECT_TRUE(client->DeleteRange(range));
1536 EXPECT_STR_EQ("0456789", textfield_->text());
1538 ui::CompositionText composition;
1539 composition.text = UTF8ToUTF16("321");
1540 // Set composition through input method.
1541 input_method_->Clear();
1542 input_method_->SetCompositionTextForNextKey(composition);
1543 textfield_->clear();
1545 on_before_user_action_ = on_after_user_action_ = 0;
1547 // Send a key to trigger MockInputMethod::DispatchKeyEvent(). Note the
1548 // specific VKEY isn't used (MockInputMethod will mock a ui::VKEY_PROCESSKEY
1549 // whenever it has a test composition). However, on Mac, it can't be a letter
1550 // (e.g. VKEY_A) since all native character events on Mac are unicode events
1551 // and don't have a meaningful ui::KeyEvent that would trigger
1552 // DispatchKeyEvent().
1553 SendKeyEvent(ui::VKEY_RETURN);
1555 EXPECT_TRUE(textfield_->key_received());
1556 EXPECT_FALSE(textfield_->key_handled());
1557 EXPECT_TRUE(client->HasCompositionText());
1558 EXPECT_TRUE(client->GetCompositionTextRange(&range));
1559 EXPECT_STR_EQ("0321456789", textfield_->text());
1560 EXPECT_EQ(gfx::Range(1, 4), range);
1561 EXPECT_EQ(1, on_before_user_action_);
1562 EXPECT_EQ(1, on_after_user_action_);
1564 input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
1565 on_before_user_action_ = on_after_user_action_ = 0;
1566 textfield_->clear();
1567 SendKeyEvent(ui::VKEY_RETURN);
1568 EXPECT_TRUE(textfield_->key_received());
1569 EXPECT_FALSE(textfield_->key_handled());
1570 EXPECT_FALSE(client->HasCompositionText());
1571 EXPECT_FALSE(input_method_->cancel_composition_called());
1572 EXPECT_STR_EQ("0123456789", textfield_->text());
1573 EXPECT_EQ(1, on_before_user_action_);
1574 EXPECT_EQ(1, on_after_user_action_);
1576 input_method_->Clear();
1577 input_method_->SetCompositionTextForNextKey(composition);
1578 textfield_->clear();
1579 SendKeyEvent(ui::VKEY_RETURN);
1580 EXPECT_TRUE(client->HasCompositionText());
1581 EXPECT_STR_EQ("0123321456789", textfield_->text());
1583 on_before_user_action_ = on_after_user_action_ = 0;
1584 textfield_->clear();
1585 SendKeyEvent(ui::VKEY_RIGHT);
1586 EXPECT_FALSE(client->HasCompositionText());
1587 EXPECT_TRUE(input_method_->cancel_composition_called());
1588 EXPECT_TRUE(textfield_->key_received());
1589 EXPECT_TRUE(textfield_->key_handled());
1590 EXPECT_STR_EQ("0123321456789", textfield_->text());
1591 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1592 EXPECT_EQ(1, on_before_user_action_);
1593 EXPECT_EQ(1, on_after_user_action_);
1595 textfield_->clear();
1596 textfield_->SetText(ASCIIToUTF16("0123456789"));
1597 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5)));
1598 client->ExtendSelectionAndDelete(4, 2);
1599 EXPECT_STR_EQ("0789", textfield_->text());
1601 // On{Before,After}UserAction should be called by whatever user action
1602 // triggers clearing or setting a selection if appropriate.
1603 on_before_user_action_ = on_after_user_action_ = 0;
1604 textfield_->clear();
1605 textfield_->ClearSelection();
1606 textfield_->SelectAll(false);
1607 EXPECT_EQ(0, on_before_user_action_);
1608 EXPECT_EQ(0, on_after_user_action_);
1610 input_method_->Clear();
1612 // Changing the Textfield to readonly shouldn't change the input client, since
1613 // it's still required for selections and clipboard copy.
1614 ui::TextInputClient* text_input_client = textfield_;
1615 EXPECT_TRUE(text_input_client);
1616 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1617 textfield_->SetReadOnly(true);
1618 EXPECT_TRUE(input_method_->text_input_type_changed());
1619 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1621 input_method_->Clear();
1622 textfield_->SetReadOnly(false);
1623 EXPECT_TRUE(input_method_->text_input_type_changed());
1624 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, text_input_client->GetTextInputType());
1626 input_method_->Clear();
1627 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1628 EXPECT_TRUE(input_method_->text_input_type_changed());
1631 TEST_F(TextfieldTest, UndoRedoTest) {
1632 InitTextfield();
1633 SendKeyEvent(ui::VKEY_A);
1634 EXPECT_STR_EQ("a", textfield_->text());
1635 SendKeyEvent(ui::VKEY_Z, false, true);
1636 EXPECT_STR_EQ("", textfield_->text());
1637 SendKeyEvent(ui::VKEY_Z, false, true);
1638 EXPECT_STR_EQ("", textfield_->text());
1639 SendKeyEvent(ui::VKEY_Z, true, true);
1640 EXPECT_STR_EQ("a", textfield_->text());
1641 SendKeyEvent(ui::VKEY_Z, true, true);
1642 EXPECT_STR_EQ("a", textfield_->text());
1644 // AppendText
1645 textfield_->AppendText(ASCIIToUTF16("b"));
1646 last_contents_.clear(); // AppendText doesn't call ContentsChanged.
1647 EXPECT_STR_EQ("ab", textfield_->text());
1648 SendKeyEvent(ui::VKEY_Z, false, true);
1649 EXPECT_STR_EQ("a", textfield_->text());
1650 SendKeyEvent(ui::VKEY_Z, true, true);
1651 EXPECT_STR_EQ("ab", textfield_->text());
1653 // SetText
1654 SendKeyEvent(ui::VKEY_C);
1655 // Undo'ing append moves the cursor to the end for now.
1656 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1657 EXPECT_STR_EQ("abc", textfield_->text());
1658 textfield_->SetText(ASCIIToUTF16("abc"));
1659 EXPECT_STR_EQ("abc", textfield_->text());
1660 SendKeyEvent(ui::VKEY_Z, false, true);
1661 EXPECT_STR_EQ("ab", textfield_->text());
1662 SendKeyEvent(ui::VKEY_Z, true, true);
1663 EXPECT_STR_EQ("abc", textfield_->text());
1664 SendKeyEvent(ui::VKEY_Z, true, true);
1665 EXPECT_STR_EQ("abc", textfield_->text());
1666 textfield_->SetText(ASCIIToUTF16("123"));
1667 textfield_->SetText(ASCIIToUTF16("123"));
1668 EXPECT_STR_EQ("123", textfield_->text());
1669 SendKeyEvent(ui::VKEY_END, false, false);
1670 SendKeyEvent(ui::VKEY_4, false, false);
1671 EXPECT_STR_EQ("1234", textfield_->text());
1672 last_contents_.clear();
1673 SendKeyEvent(ui::VKEY_Z, false, true);
1674 EXPECT_STR_EQ("123", textfield_->text());
1675 SendKeyEvent(ui::VKEY_Z, false, true);
1676 // the insert edit "c" and set edit "123" are merged to single edit,
1677 // so text becomes "ab" after undo.
1678 EXPECT_STR_EQ("ab", textfield_->text());
1679 SendKeyEvent(ui::VKEY_Z, false, true);
1680 EXPECT_STR_EQ("a", textfield_->text());
1681 SendKeyEvent(ui::VKEY_Z, true, true);
1682 EXPECT_STR_EQ("ab", textfield_->text());
1683 SendKeyEvent(ui::VKEY_Z, true, true);
1684 EXPECT_STR_EQ("123", textfield_->text());
1685 SendKeyEvent(ui::VKEY_Z, true, true);
1686 EXPECT_STR_EQ("1234", textfield_->text());
1688 // Undoing to the same text shouldn't call ContentsChanged.
1689 SendKeyEvent(ui::VKEY_A, false, true); // select all
1690 SendKeyEvent(ui::VKEY_A);
1691 EXPECT_STR_EQ("a", textfield_->text());
1692 SendKeyEvent(ui::VKEY_B);
1693 SendKeyEvent(ui::VKEY_C);
1694 EXPECT_STR_EQ("abc", textfield_->text());
1695 SendKeyEvent(ui::VKEY_Z, false, true);
1696 EXPECT_STR_EQ("1234", textfield_->text());
1697 SendKeyEvent(ui::VKEY_Z, true, true);
1698 EXPECT_STR_EQ("abc", textfield_->text());
1700 // Delete/Backspace
1701 SendKeyEvent(ui::VKEY_BACK);
1702 EXPECT_STR_EQ("ab", textfield_->text());
1703 SendHomeEvent(false);
1704 SendKeyEvent(ui::VKEY_DELETE);
1705 EXPECT_STR_EQ("b", textfield_->text());
1706 SendKeyEvent(ui::VKEY_A, false, true);
1707 SendKeyEvent(ui::VKEY_DELETE);
1708 EXPECT_STR_EQ("", textfield_->text());
1709 SendKeyEvent(ui::VKEY_Z, false, true);
1710 EXPECT_STR_EQ("b", textfield_->text());
1711 SendKeyEvent(ui::VKEY_Z, false, true);
1712 EXPECT_STR_EQ("ab", textfield_->text());
1713 SendKeyEvent(ui::VKEY_Z, false, true);
1714 EXPECT_STR_EQ("abc", textfield_->text());
1715 SendKeyEvent(ui::VKEY_Z, true, true);
1716 EXPECT_STR_EQ("ab", textfield_->text());
1717 SendKeyEvent(ui::VKEY_Z, true, true);
1718 EXPECT_STR_EQ("b", textfield_->text());
1719 SendKeyEvent(ui::VKEY_Z, true, true);
1720 EXPECT_STR_EQ("", textfield_->text());
1721 SendKeyEvent(ui::VKEY_Z, true, true);
1722 EXPECT_STR_EQ("", textfield_->text());
1725 // Most platforms support Ctrl+Y as an alternative to Ctrl+Shift+Z, but on Mac
1726 // that is bound to "Show full history", so is not mapped as an editing
1727 // command. So, on Mac, send Cmd+Shift+Z.
1728 #if !defined(OS_MACOSX)
1730 // Test that Ctrl+Y works for Redo, as well as Ctrl+Shift+Z.
1731 TEST_F(TextfieldTest, RedoWithCtrlY) {
1732 InitTextfield();
1733 SendKeyEvent(ui::VKEY_A);
1734 EXPECT_STR_EQ("a", textfield_->text());
1735 SendKeyEvent(ui::VKEY_Z, false, true);
1736 EXPECT_STR_EQ("", textfield_->text());
1737 SendKeyEvent(ui::VKEY_Y, false, true);
1738 EXPECT_STR_EQ("a", textfield_->text());
1739 SendKeyEvent(ui::VKEY_Z, false, true);
1740 EXPECT_STR_EQ("", textfield_->text());
1741 SendKeyEvent(ui::VKEY_Z, true, true);
1742 EXPECT_STR_EQ("a", textfield_->text());
1745 #endif // !defined(OS_MACOSX)
1747 TEST_F(TextfieldTest, CutCopyPaste) {
1748 InitTextfield();
1750 // Ensure IDS_APP_CUT cuts.
1751 textfield_->SetText(ASCIIToUTF16("123"));
1752 textfield_->SelectAll(false);
1753 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1754 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1755 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1756 EXPECT_STR_EQ("", textfield_->text());
1757 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1759 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1760 textfield_->SetText(ASCIIToUTF16("456"));
1761 textfield_->SelectAll(false);
1762 SendKeyEvent(ui::VKEY_X, true, false, true, false);
1763 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1764 EXPECT_STR_EQ("456", textfield_->text());
1765 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1766 SendKeyEvent(ui::VKEY_X, false, true);
1767 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1768 EXPECT_STR_EQ("", textfield_->text());
1769 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1771 // Ensure [Shift]+[Delete] cuts.
1772 textfield_->SetText(ASCIIToUTF16("123"));
1773 textfield_->SelectAll(false);
1774 SendAlternateCut();
1775 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1776 EXPECT_STR_EQ("", textfield_->text());
1777 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1779 // Ensure IDS_APP_COPY copies.
1780 textfield_->SetText(ASCIIToUTF16("789"));
1781 textfield_->SelectAll(false);
1782 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1783 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1784 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1785 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1787 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1788 textfield_->SetText(ASCIIToUTF16("012"));
1789 textfield_->SelectAll(false);
1790 SendKeyEvent(ui::VKEY_C, true, false, true, false);
1791 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1792 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1793 SendKeyEvent(ui::VKEY_C, false, true);
1794 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1795 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1797 // Ensure [Ctrl]+[Insert] copies.
1798 textfield_->SetText(ASCIIToUTF16("345"));
1799 textfield_->SelectAll(false);
1800 SendAlternateCopy();
1801 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1802 EXPECT_STR_EQ("345", textfield_->text());
1803 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1805 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1806 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1807 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
1808 textfield_->SetText(base::string16());
1809 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1810 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1811 EXPECT_STR_EQ("abc", textfield_->text());
1812 SendKeyEvent(ui::VKEY_V, false, true);
1813 EXPECT_STR_EQ("abcabc", textfield_->text());
1814 SendAlternatePaste();
1815 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1816 SendKeyEvent(ui::VKEY_V, true, false, true, false);
1817 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1819 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1820 textfield_->SelectAll(false);
1821 SendKeyEvent(ui::VKEY_INSERT, true, true);
1822 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1823 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1824 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1827 TEST_F(TextfieldTest, OvertypeMode) {
1828 InitTextfield();
1829 // Overtype mode should be disabled (no-op [Insert]).
1830 textfield_->SetText(ASCIIToUTF16("2"));
1831 const bool shift = false;
1832 SendHomeEvent(shift);
1833 // Note: On Mac, there is no insert key. Insert sends kVK_Help. Currently,
1834 // since there is no overtype on toolkit-views, the behavior happens to match.
1835 // However, there's no enable-overtype equivalent key combination on OSX.
1836 SendKeyEvent(ui::VKEY_INSERT);
1837 SendKeyEvent(ui::VKEY_1, false, false);
1838 EXPECT_STR_EQ("12", textfield_->text());
1841 TEST_F(TextfieldTest, TextCursorDisplayTest) {
1842 InitTextfield();
1843 // LTR-RTL string in LTR context.
1844 SendKeyEvent('a');
1845 EXPECT_STR_EQ("a", textfield_->text());
1846 int x = GetCursorBounds().x();
1847 int prev_x = x;
1849 SendKeyEvent('b');
1850 EXPECT_STR_EQ("ab", textfield_->text());
1851 x = GetCursorBounds().x();
1852 EXPECT_LT(prev_x, x);
1853 prev_x = x;
1855 SendKeyEvent(0x05E1);
1856 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1857 x = GetCursorBounds().x();
1858 EXPECT_GE(1, std::abs(x - prev_x));
1860 SendKeyEvent(0x05E2);
1861 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1862 x = GetCursorBounds().x();
1863 EXPECT_GE(1, std::abs(x - prev_x));
1865 // Clear text.
1866 SendKeyEvent(ui::VKEY_A, false, true);
1867 SendKeyEvent(ui::VKEY_DELETE);
1869 // RTL-LTR string in LTR context.
1870 SendKeyEvent(0x05E1);
1871 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1872 x = GetCursorBounds().x();
1873 EXPECT_EQ(GetDisplayRect().x(), x);
1874 prev_x = x;
1876 SendKeyEvent(0x05E2);
1877 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1878 x = GetCursorBounds().x();
1879 EXPECT_GE(1, std::abs(x - prev_x));
1881 SendKeyEvent('a');
1882 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1883 x = GetCursorBounds().x();
1884 EXPECT_LT(prev_x, x);
1885 prev_x = x;
1887 SendKeyEvent('b');
1888 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1889 x = GetCursorBounds().x();
1890 EXPECT_LT(prev_x, x);
1893 TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
1894 std::string locale = l10n_util::GetApplicationLocale("");
1895 base::i18n::SetICUDefaultLocale("he");
1897 InitTextfield();
1898 // LTR-RTL string in RTL context.
1899 SendKeyEvent('a');
1900 EXPECT_STR_EQ("a", textfield_->text());
1901 int x = GetCursorBounds().x();
1902 EXPECT_EQ(GetDisplayRect().right() - 1, x);
1903 int prev_x = x;
1905 SendKeyEvent('b');
1906 EXPECT_STR_EQ("ab", textfield_->text());
1907 x = GetCursorBounds().x();
1908 EXPECT_GE(1, std::abs(x - prev_x));
1910 SendKeyEvent(0x05E1);
1911 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1912 x = GetCursorBounds().x();
1913 EXPECT_GT(prev_x, x);
1914 prev_x = x;
1916 SendKeyEvent(0x05E2);
1917 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1918 x = GetCursorBounds().x();
1919 EXPECT_GT(prev_x, x);
1921 // Clear text.
1922 SendKeyEvent(ui::VKEY_A, false, true);
1923 SendKeyEvent(ui::VKEY_DELETE);
1925 // RTL-LTR string in RTL context.
1926 SendKeyEvent(0x05E1);
1927 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1928 x = GetCursorBounds().x();
1929 prev_x = x;
1931 SendKeyEvent(0x05E2);
1932 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1933 x = GetCursorBounds().x();
1934 EXPECT_GT(prev_x, x);
1935 prev_x = x;
1937 SendKeyEvent('a');
1938 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1939 x = GetCursorBounds().x();
1940 EXPECT_GE(1, std::abs(x - prev_x));
1941 prev_x = x;
1943 SendKeyEvent('b');
1944 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1945 x = GetCursorBounds().x();
1946 EXPECT_GE(1, std::abs(x - prev_x));
1948 // Reset locale.
1949 base::i18n::SetICUDefaultLocale(locale);
1952 TEST_F(TextfieldTest, HitInsideTextAreaTest) {
1953 InitTextfield();
1954 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1955 std::vector<gfx::Rect> cursor_bounds;
1957 // Save each cursor bound.
1958 gfx::SelectionModel sel(0, gfx::CURSOR_FORWARD);
1959 cursor_bounds.push_back(GetCursorBounds(sel));
1961 sel = gfx::SelectionModel(1, gfx::CURSOR_BACKWARD);
1962 gfx::Rect bound = GetCursorBounds(sel);
1963 sel = gfx::SelectionModel(1, gfx::CURSOR_FORWARD);
1964 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1965 cursor_bounds.push_back(bound);
1967 // Check that a cursor at the end of the Latin portion of the text is at the
1968 // same position as a cursor placed at the end of the RTL Hebrew portion.
1969 sel = gfx::SelectionModel(2, gfx::CURSOR_BACKWARD);
1970 bound = GetCursorBounds(sel);
1971 sel = gfx::SelectionModel(4, gfx::CURSOR_BACKWARD);
1972 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1973 cursor_bounds.push_back(bound);
1975 sel = gfx::SelectionModel(3, gfx::CURSOR_BACKWARD);
1976 bound = GetCursorBounds(sel);
1977 sel = gfx::SelectionModel(3, gfx::CURSOR_FORWARD);
1978 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1979 cursor_bounds.push_back(bound);
1981 sel = gfx::SelectionModel(2, gfx::CURSOR_FORWARD);
1982 bound = GetCursorBounds(sel);
1983 sel = gfx::SelectionModel(4, gfx::CURSOR_FORWARD);
1984 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1985 cursor_bounds.push_back(bound);
1987 // Expected cursor position when clicking left and right of each character.
1988 size_t cursor_pos_expected[] = {0, 1, 1, 2, 4, 3, 3, 2};
1990 int index = 0;
1991 for (int i = 0; i < static_cast<int>(cursor_bounds.size() - 1); ++i) {
1992 int half_width = (cursor_bounds[i + 1].x() - cursor_bounds[i].x()) / 2;
1993 MouseClick(cursor_bounds[i], half_width / 2);
1994 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1996 // To avoid trigger double click. Not using sleep() since it takes longer
1997 // for the test to run if using sleep().
1998 NonClientMouseClick();
2000 MouseClick(cursor_bounds[i + 1], - (half_width / 2));
2001 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
2003 NonClientMouseClick();
2007 TEST_F(TextfieldTest, HitOutsideTextAreaTest) {
2008 InitTextfield();
2010 // LTR-RTL string in LTR context.
2011 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
2013 const bool shift = false;
2014 SendHomeEvent(shift);
2015 gfx::Rect bound = GetCursorBounds();
2016 MouseClick(bound, -10);
2017 EXPECT_EQ(bound, GetCursorBounds());
2019 SendEndEvent(shift);
2020 bound = GetCursorBounds();
2021 MouseClick(bound, 10);
2022 EXPECT_EQ(bound, GetCursorBounds());
2024 NonClientMouseClick();
2026 // RTL-LTR string in LTR context.
2027 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
2029 SendHomeEvent(shift);
2030 bound = GetCursorBounds();
2031 MouseClick(bound, 10);
2032 EXPECT_EQ(bound, GetCursorBounds());
2034 SendEndEvent(shift);
2035 bound = GetCursorBounds();
2036 MouseClick(bound, -10);
2037 EXPECT_EQ(bound, GetCursorBounds());
2040 TEST_F(TextfieldTest, HitOutsideTextAreaInRTLTest) {
2041 std::string locale = l10n_util::GetApplicationLocale("");
2042 base::i18n::SetICUDefaultLocale("he");
2044 InitTextfield();
2046 // RTL-LTR string in RTL context.
2047 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
2048 const bool shift = false;
2049 SendHomeEvent(shift);
2050 gfx::Rect bound = GetCursorBounds();
2051 MouseClick(bound, 10);
2052 EXPECT_EQ(bound, GetCursorBounds());
2054 SendEndEvent(shift);
2055 bound = GetCursorBounds();
2056 MouseClick(bound, -10);
2057 EXPECT_EQ(bound, GetCursorBounds());
2059 NonClientMouseClick();
2061 // LTR-RTL string in RTL context.
2062 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
2063 SendHomeEvent(shift);
2064 bound = GetCursorBounds();
2065 MouseClick(bound, -10);
2066 EXPECT_EQ(bound, GetCursorBounds());
2068 SendEndEvent(shift);
2069 bound = GetCursorBounds();
2070 MouseClick(bound, 10);
2071 EXPECT_EQ(bound, GetCursorBounds());
2073 // Reset locale.
2074 base::i18n::SetICUDefaultLocale(locale);
2077 TEST_F(TextfieldTest, OverflowTest) {
2078 InitTextfield();
2080 base::string16 str;
2081 for (int i = 0; i < 500; ++i)
2082 SendKeyEvent('a');
2083 SendKeyEvent(kHebrewLetterSamekh);
2084 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2086 // Test mouse pointing.
2087 MouseClick(GetCursorBounds(), -1);
2088 EXPECT_EQ(500U, textfield_->GetCursorPosition());
2090 // Clear text.
2091 SendKeyEvent(ui::VKEY_A, false, true);
2092 SendKeyEvent(ui::VKEY_DELETE);
2094 for (int i = 0; i < 500; ++i)
2095 SendKeyEvent(kHebrewLetterSamekh);
2096 SendKeyEvent('a');
2097 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2099 MouseClick(GetCursorBounds(), -1);
2100 EXPECT_EQ(501U, textfield_->GetCursorPosition());
2103 TEST_F(TextfieldTest, OverflowInRTLTest) {
2104 std::string locale = l10n_util::GetApplicationLocale("");
2105 base::i18n::SetICUDefaultLocale("he");
2107 InitTextfield();
2109 base::string16 str;
2110 for (int i = 0; i < 500; ++i)
2111 SendKeyEvent('a');
2112 SendKeyEvent(kHebrewLetterSamekh);
2113 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2115 MouseClick(GetCursorBounds(), 1);
2116 EXPECT_EQ(501U, textfield_->GetCursorPosition());
2118 // Clear text.
2119 SendKeyEvent(ui::VKEY_A, false, true);
2120 SendKeyEvent(ui::VKEY_DELETE);
2122 for (int i = 0; i < 500; ++i)
2123 SendKeyEvent(kHebrewLetterSamekh);
2124 SendKeyEvent('a');
2125 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
2127 MouseClick(GetCursorBounds(), 1);
2128 EXPECT_EQ(500U, textfield_->GetCursorPosition());
2130 // Reset locale.
2131 base::i18n::SetICUDefaultLocale(locale);
2134 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) {
2135 InitTextfield();
2136 ui::CompositionText composition;
2137 composition.text = UTF8ToUTF16("abc123");
2138 const uint32 char_count = static_cast<uint32>(composition.text.length());
2139 ui::TextInputClient* client = textfield_;
2141 // Compare the composition character bounds with surrounding cursor bounds.
2142 for (uint32 i = 0; i < char_count; ++i) {
2143 composition.selection = gfx::Range(i);
2144 client->SetCompositionText(composition);
2145 gfx::Point cursor_origin = GetCursorBounds().origin();
2146 views::View::ConvertPointToScreen(textfield_, &cursor_origin);
2148 composition.selection = gfx::Range(i + 1);
2149 client->SetCompositionText(composition);
2150 gfx::Point next_cursor_bottom_left = GetCursorBounds().bottom_left();
2151 views::View::ConvertPointToScreen(textfield_, &next_cursor_bottom_left);
2153 gfx::Rect character;
2154 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &character));
2155 EXPECT_EQ(character.origin(), cursor_origin) << " i=" << i;
2156 EXPECT_EQ(character.bottom_right(), next_cursor_bottom_left) << " i=" << i;
2159 // Return false if the index is out of range.
2160 gfx::Rect rect;
2161 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count, &rect));
2162 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 1, &rect));
2163 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect));
2166 TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
2167 InitTextfield();
2169 const base::char16 kUtf16Chars[] = {
2170 // U+0020 SPACE
2171 0x0020,
2172 // U+1F408 (CAT) as surrogate pair
2173 0xd83d, 0xdc08,
2174 // U+5642 as Ideographic Variation Sequences
2175 0x5642, 0xDB40, 0xDD00,
2176 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
2177 0x260E, 0xFE0F,
2178 // U+0020 SPACE
2179 0x0020,
2181 const size_t kUtf16CharsCount = arraysize(kUtf16Chars);
2183 ui::CompositionText composition;
2184 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount);
2185 ui::TextInputClient* client = textfield_;
2186 client->SetCompositionText(composition);
2188 // Make sure GetCompositionCharacterBounds never fails for index.
2189 gfx::Rect rects[kUtf16CharsCount];
2190 gfx::Rect prev_cursor = GetCursorBounds();
2191 for (uint32 i = 0; i < kUtf16CharsCount; ++i)
2192 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i]));
2194 // Here we might expect the following results but it actually depends on how
2195 // Uniscribe or HarfBuzz treats them with given font.
2196 // - rects[1] == rects[2]
2197 // - rects[3] == rects[4] == rects[5]
2198 // - rects[6] == rects[7]
2201 // The word we select by double clicking should remain selected regardless of
2202 // where we drag the mouse afterwards without releasing the left button.
2203 TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
2204 InitTextfield();
2206 textfield_->SetText(ASCIIToUTF16("abc def ghi"));
2208 textfield_->SelectRange(gfx::Range(5, 5));
2209 const gfx::Rect middle_cursor = GetCursorBounds();
2210 textfield_->SelectRange(gfx::Range(0, 0));
2211 const gfx::Point beginning = GetCursorBounds().origin();
2213 // Double click, but do not release the left button.
2214 MouseClick(middle_cursor, 0);
2215 const gfx::Point middle(middle_cursor.x(),
2216 middle_cursor.y() + middle_cursor.height() / 2);
2217 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle,
2218 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2219 ui::EF_LEFT_MOUSE_BUTTON);
2220 textfield_->OnMousePressed(press_event);
2221 EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange());
2223 // Drag the mouse to the beginning of the textfield.
2224 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning,
2225 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
2226 textfield_->OnMouseDragged(drag_event);
2227 EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
2230 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2231 // flaky: http://crbug.com/396477
2232 TEST_F(TextfieldTest, DISABLED_SelectionClipboard) {
2233 InitTextfield();
2234 textfield_->SetText(ASCIIToUTF16("0123"));
2235 gfx::Point point_1(GetCursorPositionX(1), 0);
2236 gfx::Point point_2(GetCursorPositionX(2), 0);
2237 gfx::Point point_3(GetCursorPositionX(3), 0);
2238 gfx::Point point_4(GetCursorPositionX(4), 0);
2240 // Text selected by the mouse should be placed on the selection clipboard.
2241 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
2242 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2243 ui::EF_LEFT_MOUSE_BUTTON);
2244 textfield_->OnMousePressed(press);
2245 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
2246 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2247 ui::EF_LEFT_MOUSE_BUTTON);
2248 textfield_->OnMouseDragged(drag);
2249 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
2250 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2251 ui::EF_LEFT_MOUSE_BUTTON);
2252 textfield_->OnMouseReleased(release);
2253 EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
2254 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2256 // Select-all should update the selection clipboard.
2257 SendKeyEvent(ui::VKEY_A, false, true);
2258 EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
2259 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2260 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2262 // Shift-click selection modifications should update the clipboard.
2263 NonClientMouseClick();
2264 ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
2265 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2266 ui::EF_LEFT_MOUSE_BUTTON);
2267 press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
2268 #if defined(USE_X11)
2269 ui::UpdateX11EventForFlags(&press_2);
2270 #endif
2271 textfield_->OnMousePressed(press_2);
2272 ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
2273 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2274 ui::EF_LEFT_MOUSE_BUTTON);
2275 textfield_->OnMouseReleased(release_2);
2276 EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
2277 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2278 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2280 // Shift-Left/Right should update the selection clipboard.
2281 SendKeyEvent(ui::VKEY_RIGHT, true, false);
2282 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2283 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2284 SendKeyEvent(ui::VKEY_LEFT, true, false);
2285 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2286 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2287 SendKeyEvent(ui::VKEY_RIGHT, true, true);
2288 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2289 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2291 // Moving the cursor without a selection should not change the clipboard.
2292 SendKeyEvent(ui::VKEY_LEFT, false, false);
2293 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
2294 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2295 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2297 // Middle clicking should paste at the mouse (not cursor) location.
2298 // The cursor should be placed at the end of the pasted text.
2299 ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
2300 ui::EventTimeForNow(), ui::EF_MIDDLE_MOUSE_BUTTON,
2301 ui::EF_MIDDLE_MOUSE_BUTTON);
2302 textfield_->OnMousePressed(middle);
2303 EXPECT_STR_EQ("01230123", textfield_->text());
2304 EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
2305 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2307 // Middle clicking on an unfocused textfield should focus it and paste.
2308 textfield_->GetFocusManager()->ClearFocus();
2309 EXPECT_FALSE(textfield_->HasFocus());
2310 textfield_->OnMousePressed(middle);
2311 EXPECT_TRUE(textfield_->HasFocus());
2312 EXPECT_STR_EQ("012301230123", textfield_->text());
2313 EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
2314 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2316 // Middle clicking with an empty selection clipboard should still focus.
2317 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, std::string());
2318 textfield_->GetFocusManager()->ClearFocus();
2319 EXPECT_FALSE(textfield_->HasFocus());
2320 textfield_->OnMousePressed(middle);
2321 EXPECT_TRUE(textfield_->HasFocus());
2322 EXPECT_STR_EQ("012301230123", textfield_->text());
2323 EXPECT_EQ(gfx::Range(4, 4), textfield_->GetSelectedRange());
2324 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
2326 // Middle clicking in the selection should clear the clipboard and selection.
2327 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
2328 textfield_->SelectRange(gfx::Range(2, 6));
2329 textfield_->OnMousePressed(middle);
2330 EXPECT_STR_EQ("012301230123", textfield_->text());
2331 EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
2332 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
2334 // Double and triple clicking should update the clipboard contents.
2335 textfield_->SetText(ASCIIToUTF16("ab cd ef"));
2336 gfx::Point word(GetCursorPositionX(4), 0);
2337 ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
2338 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2339 ui::EF_LEFT_MOUSE_BUTTON);
2340 textfield_->OnMousePressed(press_word);
2341 ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
2342 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
2343 ui::EF_LEFT_MOUSE_BUTTON);
2344 textfield_->OnMouseReleased(release_word);
2345 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
2346 ui::EventTimeForNow(),
2347 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
2348 ui::EF_LEFT_MOUSE_BUTTON);
2349 textfield_->OnMousePressed(double_click);
2350 textfield_->OnMouseReleased(release_word);
2351 EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
2352 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2353 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2354 textfield_->OnMousePressed(press_word);
2355 textfield_->OnMouseReleased(release_word);
2356 EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
2357 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2358 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
2360 // Selecting a range of text without any user interaction should not change
2361 // the clipboard content.
2362 textfield_->SelectRange(gfx::Range(0, 3));
2363 EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
2364 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2365 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2367 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
2368 textfield_->SelectAll(false);
2369 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
2370 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
2372 #endif
2374 // Long_Press gesture in Textfield can initiate a drag and drop now.
2375 TEST_F(TextfieldTest, TestLongPressInitiatesDragDrop) {
2376 InitTextfield();
2377 textfield_->SetText(ASCIIToUTF16("Hello string world"));
2379 // Ensure the textfield will provide selected text for drag data.
2380 textfield_->SelectRange(gfx::Range(6, 12));
2381 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
2383 // Enable touch-drag-drop to make long press effective.
2384 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2385 switches::kEnableTouchDragDrop);
2387 // Create a long press event in the selected region should start a drag.
2388 GestureEventForTest long_press(
2389 kStringPoint.x(),
2390 kStringPoint.y(),
2391 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2392 textfield_->OnGestureEvent(&long_press);
2393 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
2394 kStringPoint));
2397 TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
2398 InitTextfield();
2399 textfield_->SetText(UTF8ToUTF16("abc"));
2400 const int old_baseline = textfield_->GetBaseline();
2402 // Set text which may fall back to a font which has taller baseline than
2403 // the default font.
2404 textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2405 const int new_baseline = textfield_->GetBaseline();
2407 // Regardless of the text, the baseline must be the same.
2408 EXPECT_EQ(new_baseline, old_baseline);
2411 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2412 // controller and it does not crash.
2413 TEST_F(TextfieldTest, DestroyingTextfieldFromOnKeyEvent) {
2414 InitTextfield();
2416 // The controller assumes ownership of the textfield.
2417 TextfieldDestroyerController controller(textfield_);
2418 EXPECT_TRUE(controller.target());
2420 // Send a key to trigger OnKeyEvent().
2421 SendKeyEvent(ui::VKEY_RETURN);
2423 EXPECT_FALSE(controller.target());
2426 class TextfieldTouchSelectionTest : public TextfieldTest {
2427 public:
2428 // TextfieldTest:
2429 void SetUp() override {
2430 TextfieldTest::SetUp();
2431 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2432 switches::kEnableTouchEditing);
2435 protected:
2436 // Simulates a complete tap.
2437 void Tap(const gfx::Point& point) {
2438 GestureEventForTest begin(
2439 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
2440 textfield_->OnGestureEvent(&begin);
2442 GestureEventForTest tap_down(
2443 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
2444 textfield_->OnGestureEvent(&tap_down);
2446 GestureEventForTest show_press(
2447 point.x(),
2448 point.y(),
2449 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
2450 textfield_->OnGestureEvent(&show_press);
2452 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2453 tap_details.set_tap_count(1);
2454 GestureEventForTest tap(point.x(), point.y(), tap_details);
2455 textfield_->OnGestureEvent(&tap);
2457 GestureEventForTest end(
2458 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_END));
2459 textfield_->OnGestureEvent(&end);
2464 // Touch selection and dragging currently only works for chromeos.
2465 #if defined(OS_CHROMEOS)
2466 TEST_F(TextfieldTouchSelectionTest, TouchSelectionAndDraggingTest) {
2467 InitTextfield();
2468 textfield_->SetText(ASCIIToUTF16("hello world"));
2469 EXPECT_FALSE(test_api_->touch_selection_controller());
2470 const int x = GetCursorPositionX(2);
2472 // Tapping on the textfield should turn on the TouchSelectionController.
2473 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
2474 tap_details.set_tap_count(1);
2475 GestureEventForTest tap(x, 0, tap_details);
2476 textfield_->OnGestureEvent(&tap);
2477 EXPECT_TRUE(test_api_->touch_selection_controller());
2479 // Un-focusing the textfield should reset the TouchSelectionController
2480 textfield_->GetFocusManager()->ClearFocus();
2481 EXPECT_FALSE(test_api_->touch_selection_controller());
2482 textfield_->RequestFocus();
2484 // With touch editing enabled, long press should not show context menu.
2485 // Instead, select word and invoke TouchSelectionController.
2486 GestureEventForTest long_press_1(
2487 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2488 textfield_->OnGestureEvent(&long_press_1);
2489 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2490 EXPECT_TRUE(test_api_->touch_selection_controller());
2491 EXPECT_TRUE(long_press_1.handled());
2493 // With touch drag drop enabled, long pressing in the selected region should
2494 // start a drag and remove TouchSelectionController.
2495 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
2496 GestureEventForTest long_press_2(
2497 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2498 textfield_->OnGestureEvent(&long_press_2);
2499 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2500 EXPECT_FALSE(test_api_->touch_selection_controller());
2501 EXPECT_FALSE(long_press_2.handled());
2503 // After disabling touch drag drop, long pressing again in the selection
2504 // region should not do anything.
2505 base::CommandLine::ForCurrentProcess()->AppendSwitch(
2506 switches::kDisableTouchDragDrop);
2507 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
2508 GestureEventForTest long_press_3(
2509 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2510 textfield_->OnGestureEvent(&long_press_3);
2511 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
2512 EXPECT_FALSE(test_api_->touch_selection_controller());
2513 EXPECT_FALSE(long_press_3.handled());
2515 #endif
2517 TEST_F(TextfieldTouchSelectionTest, TouchSelectionInUnfocusableTextfield) {
2518 InitTextfield();
2519 textfield_->SetText(ASCIIToUTF16("hello world"));
2520 gfx::Point touch_point(GetCursorPositionX(2), 0);
2522 // Disable textfield and tap on it. Touch text selection should not get
2523 // activated.
2524 textfield_->SetEnabled(false);
2525 Tap(touch_point);
2526 EXPECT_FALSE(test_api_->touch_selection_controller());
2527 textfield_->SetEnabled(true);
2529 // Make textfield unfocusable and tap on it. Touch text selection should not
2530 // get activated.
2531 textfield_->SetFocusable(false);
2532 Tap(touch_point);
2533 EXPECT_FALSE(textfield_->HasFocus());
2534 EXPECT_FALSE(test_api_->touch_selection_controller());
2535 textfield_->SetFocusable(true);
2538 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2539 #if defined(OS_MACOSX) && !defined(USE_AURA)
2540 #define MAYBE_TapOnSelection DISABLED_TapOnSelection
2541 #else
2542 #define MAYBE_TapOnSelection TapOnSelection
2543 #endif
2545 TEST_F(TextfieldTouchSelectionTest, MAYBE_TapOnSelection) {
2546 InitTextfield();
2547 textfield_->SetText(ASCIIToUTF16("hello world"));
2548 gfx::Range sel_range(2, 7);
2549 gfx::Range tap_range(5, 5);
2550 gfx::Rect tap_rect =
2551 GetCursorBounds(gfx::SelectionModel(tap_range, gfx::CURSOR_FORWARD));
2552 gfx::Point tap_point = tap_rect.CenterPoint();
2554 // Select range |sel_range| and check if touch selection handles are not
2555 // present and correct range is selected.
2556 textfield_->SetSelectionRange(sel_range);
2557 gfx::Range range;
2558 textfield_->GetSelectionRange(&range);
2559 EXPECT_FALSE(test_api_->touch_selection_controller());
2560 EXPECT_EQ(sel_range, range);
2562 // Tap on selection and check if touch selectoin handles are shown, but
2563 // selection range is not modified.
2564 Tap(tap_point);
2565 textfield_->GetSelectionRange(&range);
2566 EXPECT_TRUE(test_api_->touch_selection_controller());
2567 EXPECT_EQ(sel_range, range);
2569 // Tap again on selection and check if touch selection handles are still
2570 // present and selection is changed to a cursor at tap location.
2571 Tap(tap_point);
2572 textfield_->GetSelectionRange(&range);
2573 EXPECT_TRUE(test_api_->touch_selection_controller());
2574 EXPECT_EQ(tap_range, range);
2577 TEST_F(TextfieldTest, AccessiblePasswordTest) {
2578 InitTextfield();
2579 textfield_->SetText(ASCIIToUTF16("password"));
2581 ui::AXViewState state_regular;
2582 textfield_->GetAccessibleState(&state_regular);
2583 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_regular.role);
2584 EXPECT_EQ(ASCIIToUTF16("password"), state_regular.value);
2585 EXPECT_FALSE(state_regular.HasStateFlag(ui::AX_STATE_PROTECTED));
2587 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
2588 ui::AXViewState state_protected;
2589 textfield_->GetAccessibleState(&state_protected);
2590 EXPECT_EQ(ui::AX_ROLE_TEXT_FIELD, state_protected.role);
2591 EXPECT_EQ(ASCIIToUTF16("********"), state_protected.value);
2592 EXPECT_TRUE(state_protected.HasStateFlag(ui::AX_STATE_PROTECTED));
2595 } // namespace views