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.
4
5 #include "ui/views/controls/textfield/textfield.h"
6
7 #include <set>
8 #include <string>
9 #include <vector>
10
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/base/clipboard/clipboard.h"
16 #include "ui/base/clipboard/scoped_clipboard_writer.h"
17 #include "ui/base/dragdrop/drag_drop_types.h"
18 #include "ui/base/ime/text_input_client.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/ui_base_switches.h"
21 #include "ui/base/ui_base_switches_util.h"
22 #include "ui/events/event.h"
23 #include "ui/events/keycodes/keyboard_codes.h"
24 #include "ui/gfx/render_text.h"
25 #include "ui/strings/grit/ui_strings.h"
26 #include "ui/views/controls/textfield/textfield_controller.h"
27 #include "ui/views/controls/textfield/textfield_model.h"
28 #include "ui/views/controls/textfield/textfield_test_api.h"
29 #include "ui/views/focus/focus_manager.h"
30 #include "ui/views/ime/mock_input_method.h"
31 #include "ui/views/test/test_views_delegate.h"
32 #include "ui/views/test/views_test_base.h"
33 #include "ui/views/widget/widget.h"
34 #include "url/gurl.h"
35
36 #if defined(OS_WIN)
37 #include "base/win/windows_version.h"
38 #endif
39
40 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
41 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
42 #endif
43
44 #if defined(USE_X11)
45 #include "ui/events/event_utils.h"
46 #endif
47
48 using base::ASCIIToUTF16;
49 using base::UTF8ToUTF16;
50 using base::WideToUTF16;
51
52 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
53
54 namespace {
55
56 const base::char16 kHebrewLetterSamekh = 0x05E1;
57
58 // A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
59 class TestTextfield : public views::Textfield {
60 public:
TestTextfield()61 TestTextfield()
62 : Textfield(),
63 key_handled_(false),
64 key_received_(false),
65 weak_ptr_factory_(this) {}
66
OnKeyPressed(const ui::KeyEvent & e)67 virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
68 key_received_ = true;
69
70 // Since OnKeyPressed() might destroy |this|, get a weak pointer and
71 // verify it isn't null before writing the bool value to key_handled_.
72 base::WeakPtr<TestTextfield> textfield(weak_ptr_factory_.GetWeakPtr());
73 bool key = views::Textfield::OnKeyPressed(e);
74
75 if (!textfield)
76 return key;
77
78 key_handled_ = key;
79
80 return key_handled_;
81 }
82
OnKeyReleased(const ui::KeyEvent & e)83 virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
84 key_received_ = true;
85 key_handled_ = views::Textfield::OnKeyReleased(e);
86 return key_handled_;
87 }
88
key_handled() const89 bool key_handled() const { return key_handled_; }
key_received() const90 bool key_received() const { return key_received_; }
91
clear()92 void clear() { key_received_ = key_handled_ = false; }
93
94 private:
95 bool key_handled_;
96 bool key_received_;
97
98 base::WeakPtrFactory<TestTextfield> weak_ptr_factory_;
99
100 DISALLOW_COPY_AND_ASSIGN(TestTextfield);
101 };
102
103 // Convenience to make constructing a GestureEvent simpler.
104 class GestureEventForTest : public ui::GestureEvent {
105 public:
GestureEventForTest(int x,int y,ui::GestureEventDetails details)106 GestureEventForTest(int x, int y, ui::GestureEventDetails details)
107 : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
108
109 private:
110 DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
111 };
112
113 // This controller will happily destroy the target textfield passed on
114 // construction when a key event is triggered.
115 class TextfieldDestroyerController : public views::TextfieldController {
116 public:
TextfieldDestroyerController(views::Textfield * target)117 explicit TextfieldDestroyerController(views::Textfield* target)
118 : target_(target) {
119 target_->set_controller(this);
120 }
121
target()122 views::Textfield* target() { return target_.get(); }
123
124 // views::TextfieldController:
HandleKeyEvent(views::Textfield * sender,const ui::KeyEvent & key_event)125 virtual bool HandleKeyEvent(views::Textfield* sender,
126 const ui::KeyEvent& key_event) OVERRIDE {
127 target_.reset();
128 return false;
129 }
130
131 private:
132 scoped_ptr<views::Textfield> target_;
133 };
134
GetClipboardText(ui::ClipboardType type)135 base::string16 GetClipboardText(ui::ClipboardType type) {
136 base::string16 text;
137 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
138 return text;
139 }
140
SetClipboardText(ui::ClipboardType type,const std::string & text)141 void SetClipboardText(ui::ClipboardType type, const std::string& text) {
142 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text));
143 }
144
145 } // namespace
146
147 namespace views {
148
149 class TextfieldTest : public ViewsTestBase, public TextfieldController {
150 public:
TextfieldTest()151 TextfieldTest()
152 : widget_(NULL),
153 textfield_(NULL),
154 model_(NULL),
155 input_method_(NULL),
156 on_before_user_action_(0),
157 on_after_user_action_(0),
158 copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
159 }
160
161 // ::testing::Test:
SetUp()162 virtual void SetUp() {
163 ViewsTestBase::SetUp();
164 }
165
TearDown()166 virtual void TearDown() {
167 if (widget_)
168 widget_->Close();
169 ViewsTestBase::TearDown();
170 }
171
GetAndResetCopiedToClipboard()172 ui::ClipboardType GetAndResetCopiedToClipboard() {
173 ui::ClipboardType clipboard_type = copied_to_clipboard_;
174 copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
175 return clipboard_type;
176 }
177
178 // TextfieldController:
ContentsChanged(Textfield * sender,const base::string16 & new_contents)179 virtual void ContentsChanged(Textfield* sender,
180 const base::string16& new_contents) OVERRIDE {
181 // Paste calls TextfieldController::ContentsChanged() explicitly even if the
182 // paste action did not change the content. So |new_contents| may match
183 // |last_contents_|. For more info, see http://crbug.com/79002
184 last_contents_ = new_contents;
185 }
186
OnBeforeUserAction(Textfield * sender)187 virtual void OnBeforeUserAction(Textfield* sender) OVERRIDE {
188 ++on_before_user_action_;
189 }
190
OnAfterUserAction(Textfield * sender)191 virtual void OnAfterUserAction(Textfield* sender) OVERRIDE {
192 ++on_after_user_action_;
193 }
194
OnAfterCutOrCopy(ui::ClipboardType clipboard_type)195 virtual void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) OVERRIDE {
196 copied_to_clipboard_ = clipboard_type;
197 }
198
InitTextfield()199 void InitTextfield() {
200 InitTextfields(1);
201 }
202
InitTextfields(int count)203 void InitTextfields(int count) {
204 ASSERT_FALSE(textfield_);
205 textfield_ = new TestTextfield();
206 textfield_->set_controller(this);
207 widget_ = new Widget();
208 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
209 params.bounds = gfx::Rect(100, 100, 100, 100);
210 widget_->Init(params);
211 View* container = new View();
212 widget_->SetContentsView(container);
213 container->AddChildView(textfield_);
214 textfield_->SetBoundsRect(params.bounds);
215 textfield_->set_id(1);
216 test_api_.reset(new TextfieldTestApi(textfield_));
217
218 for (int i = 1; i < count; i++) {
219 Textfield* textfield = new Textfield();
220 container->AddChildView(textfield);
221 textfield->set_id(i + 1);
222 }
223
224 model_ = test_api_->model();
225 model_->ClearEditHistory();
226
227 input_method_ = new MockInputMethod();
228 widget_->ReplaceInputMethod(input_method_);
229
230 // Activate the widget and focus the textfield for input handling.
231 widget_->Activate();
232 textfield_->RequestFocus();
233 }
234
GetContextMenuModel()235 ui::MenuModel* GetContextMenuModel() {
236 test_api_->UpdateContextMenu();
237 return test_api_->context_menu_contents();
238 }
239
240 protected:
SendKeyEvent(ui::KeyboardCode key_code,bool alt,bool shift,bool control,bool caps_lock)241 void SendKeyEvent(ui::KeyboardCode key_code,
242 bool alt,
243 bool shift,
244 bool control,
245 bool caps_lock) {
246 int flags = (alt ? ui::EF_ALT_DOWN : 0) |
247 (shift ? ui::EF_SHIFT_DOWN : 0) |
248 (control ? ui::EF_CONTROL_DOWN : 0) |
249 (caps_lock ? ui::EF_CAPS_LOCK_DOWN : 0);
250 ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags);
251 input_method_->DispatchKeyEvent(event);
252 }
253
SendKeyEvent(ui::KeyboardCode key_code,bool shift,bool control)254 void SendKeyEvent(ui::KeyboardCode key_code, bool shift, bool control) {
255 SendKeyEvent(key_code, false, shift, control, false);
256 }
257
SendKeyEvent(ui::KeyboardCode key_code)258 void SendKeyEvent(ui::KeyboardCode key_code) {
259 SendKeyEvent(key_code, false, false);
260 }
261
SendKeyEvent(base::char16 ch)262 void SendKeyEvent(base::char16 ch) {
263 if (ch < 0x80) {
264 ui::KeyboardCode code =
265 ch == ' ' ? ui::VKEY_SPACE :
266 static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a');
267 SendKeyEvent(code);
268 } else {
269 ui::KeyEvent event(ch, ui::VKEY_UNKNOWN, ui::EF_NONE);
270 input_method_->DispatchKeyEvent(event);
271 }
272 }
273
GetFocusedView()274 View* GetFocusedView() {
275 return widget_->GetFocusManager()->GetFocusedView();
276 }
277
GetCursorPositionX(int cursor_pos)278 int GetCursorPositionX(int cursor_pos) {
279 return test_api_->GetRenderText()->GetCursorBounds(
280 gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), false).x();
281 }
282
283 // Get the current cursor bounds.
GetCursorBounds()284 gfx::Rect GetCursorBounds() {
285 return test_api_->GetRenderText()->GetUpdatedCursorBounds();
286 }
287
288 // Get the cursor bounds of |sel|.
GetCursorBounds(const gfx::SelectionModel & sel)289 gfx::Rect GetCursorBounds(const gfx::SelectionModel& sel) {
290 return test_api_->GetRenderText()->GetCursorBounds(sel, true);
291 }
292
GetDisplayRect()293 gfx::Rect GetDisplayRect() {
294 return test_api_->GetRenderText()->display_rect();
295 }
296
297 // Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
298 // y-axis is in the middle of |bound|'s vertical range.
MouseClick(const gfx::Rect bound,int x_offset)299 void MouseClick(const gfx::Rect bound, int x_offset) {
300 gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
301 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
302 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
303 textfield_->OnMousePressed(click);
304 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point,
305 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
306 textfield_->OnMouseReleased(release);
307 }
308
309 // This is to avoid double/triple click.
NonClientMouseClick()310 void NonClientMouseClick() {
311 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
312 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
313 ui::EF_LEFT_MOUSE_BUTTON);
314 textfield_->OnMousePressed(click);
315 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
316 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
317 ui::EF_LEFT_MOUSE_BUTTON);
318 textfield_->OnMouseReleased(release);
319 }
320
321 // Simulates a complete tap.
Tap(const gfx::Point & point)322 void Tap(const gfx::Point& point) {
323 GestureEventForTest begin(
324 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
325 textfield_->OnGestureEvent(&begin);
326
327 GestureEventForTest tap_down(
328 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
329 textfield_->OnGestureEvent(&tap_down);
330
331 GestureEventForTest show_press(
332 point.x(),
333 point.y(),
334 ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
335 textfield_->OnGestureEvent(&show_press);
336
337 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
338 tap_details.set_tap_count(1);
339 GestureEventForTest tap(point.x(), point.y(), tap_details);
340 textfield_->OnGestureEvent(&tap);
341
342 GestureEventForTest end(
343 point.x(), point.y(), ui::GestureEventDetails(ui::ET_GESTURE_END));
344 textfield_->OnGestureEvent(&end);
345 }
346
VerifyTextfieldContextMenuContents(bool textfield_has_selection,bool can_undo,ui::MenuModel * menu)347 void VerifyTextfieldContextMenuContents(bool textfield_has_selection,
348 bool can_undo,
349 ui::MenuModel* menu) {
350 EXPECT_EQ(can_undo, menu->IsEnabledAt(0 /* UNDO */));
351 EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */));
352 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */));
353 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */));
354 EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
355 menu->IsEnabledAt(4 /* PASTE */));
356 EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */));
357 EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */));
358 EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */));
359 }
360
361 // We need widget to populate wrapper class.
362 Widget* widget_;
363
364 TestTextfield* textfield_;
365 scoped_ptr<TextfieldTestApi> test_api_;
366 TextfieldModel* model_;
367
368 // The string from Controller::ContentsChanged callback.
369 base::string16 last_contents_;
370
371 // For testing input method related behaviors.
372 MockInputMethod* input_method_;
373
374 // Indicates how many times OnBeforeUserAction() is called.
375 int on_before_user_action_;
376
377 // Indicates how many times OnAfterUserAction() is called.
378 int on_after_user_action_;
379
380 private:
381 ui::ClipboardType copied_to_clipboard_;
382
383 DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
384 };
385
TEST_F(TextfieldTest,ModelChangesTest)386 TEST_F(TextfieldTest, ModelChangesTest) {
387 InitTextfield();
388
389 // TextfieldController::ContentsChanged() shouldn't be called when changing
390 // text programmatically.
391 last_contents_.clear();
392 textfield_->SetText(ASCIIToUTF16("this is"));
393
394 EXPECT_STR_EQ("this is", model_->text());
395 EXPECT_STR_EQ("this is", textfield_->text());
396 EXPECT_TRUE(last_contents_.empty());
397
398 textfield_->AppendText(ASCIIToUTF16(" a test"));
399 EXPECT_STR_EQ("this is a test", model_->text());
400 EXPECT_STR_EQ("this is a test", textfield_->text());
401 EXPECT_TRUE(last_contents_.empty());
402
403 EXPECT_EQ(base::string16(), textfield_->GetSelectedText());
404 textfield_->SelectAll(false);
405 EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText());
406 EXPECT_TRUE(last_contents_.empty());
407 }
408
TEST_F(TextfieldTest,KeyTest)409 TEST_F(TextfieldTest, KeyTest) {
410 InitTextfield();
411 // Event flags: key, alt, shift, ctrl, caps-lock.
412 SendKeyEvent(ui::VKEY_T, false, true, false, false);
413 SendKeyEvent(ui::VKEY_E, false, false, false, false);
414 SendKeyEvent(ui::VKEY_X, false, true, false, true);
415 SendKeyEvent(ui::VKEY_T, false, false, false, true);
416 SendKeyEvent(ui::VKEY_1, false, true, false, false);
417 SendKeyEvent(ui::VKEY_1, false, false, false, false);
418 SendKeyEvent(ui::VKEY_1, false, true, false, true);
419 SendKeyEvent(ui::VKEY_1, false, false, false, true);
420 EXPECT_STR_EQ("TexT!1!1", textfield_->text());
421 }
422
TEST_F(TextfieldTest,ControlAndSelectTest)423 TEST_F(TextfieldTest, ControlAndSelectTest) {
424 // Insert a test string in a textfield.
425 InitTextfield();
426 textfield_->SetText(ASCIIToUTF16("one two three"));
427 SendKeyEvent(ui::VKEY_HOME, false /* shift */, false /* control */);
428 SendKeyEvent(ui::VKEY_RIGHT, true, false);
429 SendKeyEvent(ui::VKEY_RIGHT, true, false);
430 SendKeyEvent(ui::VKEY_RIGHT, true, false);
431
432 EXPECT_STR_EQ("one", textfield_->GetSelectedText());
433
434 // Test word select.
435 SendKeyEvent(ui::VKEY_RIGHT, true, true);
436 EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
437 SendKeyEvent(ui::VKEY_RIGHT, true, true);
438 EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
439 SendKeyEvent(ui::VKEY_LEFT, true, true);
440 EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
441 SendKeyEvent(ui::VKEY_LEFT, true, true);
442 EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
443
444 // Replace the selected text.
445 SendKeyEvent(ui::VKEY_Z, true, false);
446 SendKeyEvent(ui::VKEY_E, true, false);
447 SendKeyEvent(ui::VKEY_R, true, false);
448 SendKeyEvent(ui::VKEY_O, true, false);
449 SendKeyEvent(ui::VKEY_SPACE, false, false);
450 EXPECT_STR_EQ("ZERO two three", textfield_->text());
451
452 SendKeyEvent(ui::VKEY_END, true, false);
453 EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
454 SendKeyEvent(ui::VKEY_HOME, true, false);
455 EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
456 }
457
TEST_F(TextfieldTest,InsertionDeletionTest)458 TEST_F(TextfieldTest, InsertionDeletionTest) {
459 // Insert a test string in a textfield.
460 InitTextfield();
461 for (size_t i = 0; i < 10; i++)
462 SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
463 EXPECT_STR_EQ("abcdefghij", textfield_->text());
464
465 // Test the delete and backspace keys.
466 textfield_->SelectRange(gfx::Range(5));
467 for (int i = 0; i < 3; i++)
468 SendKeyEvent(ui::VKEY_BACK);
469 EXPECT_STR_EQ("abfghij", textfield_->text());
470 for (int i = 0; i < 3; i++)
471 SendKeyEvent(ui::VKEY_DELETE);
472 EXPECT_STR_EQ("abij", textfield_->text());
473
474 // Select all and replace with "k".
475 textfield_->SelectAll(false);
476 SendKeyEvent(ui::VKEY_K);
477 EXPECT_STR_EQ("k", textfield_->text());
478
479 // Delete the previous word from cursor.
480 textfield_->SetText(ASCIIToUTF16("one two three four"));
481 SendKeyEvent(ui::VKEY_END);
482 SendKeyEvent(ui::VKEY_BACK, false, false, true, false);
483 EXPECT_STR_EQ("one two three ", textfield_->text());
484
485 // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
486 SendKeyEvent(ui::VKEY_LEFT, false, false, true, false);
487 SendKeyEvent(ui::VKEY_BACK, false, true, true, false);
488 #if defined(OS_LINUX)
489 EXPECT_STR_EQ("three ", textfield_->text());
490 #else
491 EXPECT_STR_EQ("one three ", textfield_->text());
492 #endif
493
494 // Delete the next word from cursor.
495 textfield_->SetText(ASCIIToUTF16("one two three four"));
496 SendKeyEvent(ui::VKEY_HOME);
497 SendKeyEvent(ui::VKEY_DELETE, false, false, true, false);
498 EXPECT_STR_EQ(" two three four", textfield_->text());
499
500 // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
501 SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false);
502 SendKeyEvent(ui::VKEY_DELETE, false, true, true, false);
503 #if defined(OS_LINUX)
504 EXPECT_STR_EQ(" two", textfield_->text());
505 #else
506 EXPECT_STR_EQ(" two four", textfield_->text());
507 #endif
508 }
509
TEST_F(TextfieldTest,PasswordTest)510 TEST_F(TextfieldTest, PasswordTest) {
511 InitTextfield();
512 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
513 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
514 EXPECT_TRUE(textfield_->enabled());
515 EXPECT_TRUE(textfield_->IsFocusable());
516
517 last_contents_.clear();
518 textfield_->SetText(ASCIIToUTF16("password"));
519 // Ensure text() and the callback returns the actual text instead of "*".
520 EXPECT_STR_EQ("password", textfield_->text());
521 EXPECT_TRUE(last_contents_.empty());
522 model_->SelectAll(false);
523 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
524
525 // Cut and copy should be disabled.
526 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
527 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
528 SendKeyEvent(ui::VKEY_X, false, true);
529 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
530 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
531 SendKeyEvent(ui::VKEY_C, false, true);
532 SendKeyEvent(ui::VKEY_INSERT, false, true);
533 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
534 EXPECT_STR_EQ("password", textfield_->text());
535 // [Shift]+[Delete] should just delete without copying text to the clipboard.
536 textfield_->SelectAll(false);
537 SendKeyEvent(ui::VKEY_DELETE, true, false);
538
539 // Paste should work normally.
540 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
541 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
542 SendKeyEvent(ui::VKEY_V, false, true);
543 SendKeyEvent(ui::VKEY_INSERT, true, false);
544 EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
545 EXPECT_STR_EQ("foofoofoo", textfield_->text());
546 }
547
TEST_F(TextfieldTest,TextInputType)548 TEST_F(TextfieldTest, TextInputType) {
549 InitTextfield();
550
551 // Defaults to TEXT
552 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
553
554 // And can be set.
555 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
556 EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
557 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
558 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
559
560 // Readonly textfields have type NONE
561 textfield_->SetReadOnly(true);
562 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
563
564 textfield_->SetReadOnly(false);
565 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
566
567 // As do disabled textfields
568 textfield_->SetEnabled(false);
569 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
570
571 textfield_->SetEnabled(true);
572 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
573 }
574
TEST_F(TextfieldTest,OnKeyPress)575 TEST_F(TextfieldTest, OnKeyPress) {
576 InitTextfield();
577
578 // Character keys are handled by the input method.
579 SendKeyEvent(ui::VKEY_A);
580 EXPECT_TRUE(textfield_->key_received());
581 EXPECT_FALSE(textfield_->key_handled());
582 textfield_->clear();
583
584 // Arrow keys and home/end are handled by the textfield.
585 SendKeyEvent(ui::VKEY_LEFT);
586 EXPECT_TRUE(textfield_->key_received());
587 EXPECT_TRUE(textfield_->key_handled());
588 textfield_->clear();
589
590 SendKeyEvent(ui::VKEY_RIGHT);
591 EXPECT_TRUE(textfield_->key_received());
592 EXPECT_TRUE(textfield_->key_handled());
593 textfield_->clear();
594
595 SendKeyEvent(ui::VKEY_HOME);
596 EXPECT_TRUE(textfield_->key_received());
597 EXPECT_TRUE(textfield_->key_handled());
598 textfield_->clear();
599
600 SendKeyEvent(ui::VKEY_END);
601 EXPECT_TRUE(textfield_->key_received());
602 EXPECT_TRUE(textfield_->key_handled());
603 textfield_->clear();
604
605 // F24, up/down key won't be handled.
606 SendKeyEvent(ui::VKEY_F24);
607 EXPECT_TRUE(textfield_->key_received());
608 EXPECT_FALSE(textfield_->key_handled());
609 textfield_->clear();
610
611 SendKeyEvent(ui::VKEY_UP);
612 EXPECT_TRUE(textfield_->key_received());
613 EXPECT_FALSE(textfield_->key_handled());
614 textfield_->clear();
615
616 SendKeyEvent(ui::VKEY_DOWN);
617 EXPECT_TRUE(textfield_->key_received());
618 EXPECT_FALSE(textfield_->key_handled());
619 textfield_->clear();
620 }
621
622 // Tests that default key bindings are handled even with a delegate installed.
TEST_F(TextfieldTest,OnKeyPressBinding)623 TEST_F(TextfieldTest, OnKeyPressBinding) {
624 InitTextfield();
625
626 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
627 // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
628 class TestDelegate : public ui::TextEditKeyBindingsDelegateAuraLinux {
629 public:
630 TestDelegate() {}
631 virtual ~TestDelegate() {}
632
633 virtual bool MatchEvent(
634 const ui::Event& event,
635 std::vector<ui::TextEditCommandAuraLinux>* commands) OVERRIDE {
636 return false;
637 }
638
639 private:
640 DISALLOW_COPY_AND_ASSIGN(TestDelegate);
641 };
642
643 TestDelegate delegate;
644 ui::SetTextEditKeyBindingsDelegate(&delegate);
645 #endif
646
647 SendKeyEvent(ui::VKEY_A, false, false);
648 EXPECT_STR_EQ("a", textfield_->text());
649 textfield_->clear();
650
651 // Undo/Redo command keys are handled by the textfield.
652 SendKeyEvent(ui::VKEY_Z, false, true);
653 EXPECT_TRUE(textfield_->key_received());
654 EXPECT_TRUE(textfield_->key_handled());
655 EXPECT_TRUE(textfield_->text().empty());
656 textfield_->clear();
657
658 SendKeyEvent(ui::VKEY_Z, true, true);
659 EXPECT_TRUE(textfield_->key_received());
660 EXPECT_TRUE(textfield_->key_handled());
661 EXPECT_STR_EQ("a", textfield_->text());
662 textfield_->clear();
663
664 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
665 ui::SetTextEditKeyBindingsDelegate(NULL);
666 #endif
667 }
668
TEST_F(TextfieldTest,CursorMovement)669 TEST_F(TextfieldTest, CursorMovement) {
670 InitTextfield();
671
672 // Test with trailing whitespace.
673 textfield_->SetText(ASCIIToUTF16("one two hre "));
674
675 // Send the cursor at the end.
676 SendKeyEvent(ui::VKEY_END);
677
678 // Ctrl+Left should move the cursor just before the last word.
679 SendKeyEvent(ui::VKEY_LEFT, false, true);
680 SendKeyEvent(ui::VKEY_T);
681 EXPECT_STR_EQ("one two thre ", textfield_->text());
682 EXPECT_STR_EQ("one two thre ", last_contents_);
683
684 // Ctrl+Right should move the cursor to the end of the last word.
685 SendKeyEvent(ui::VKEY_RIGHT, false, true);
686 SendKeyEvent(ui::VKEY_E);
687 EXPECT_STR_EQ("one two three ", textfield_->text());
688 EXPECT_STR_EQ("one two three ", last_contents_);
689
690 // Ctrl+Right again should move the cursor to the end.
691 SendKeyEvent(ui::VKEY_RIGHT, false, true);
692 SendKeyEvent(ui::VKEY_BACK);
693 EXPECT_STR_EQ("one two three", textfield_->text());
694 EXPECT_STR_EQ("one two three", last_contents_);
695
696 // Test with leading whitespace.
697 textfield_->SetText(ASCIIToUTF16(" ne two"));
698
699 // Send the cursor at the beginning.
700 SendKeyEvent(ui::VKEY_HOME);
701
702 // Ctrl+Right, then Ctrl+Left should move the cursor to the beginning of the
703 // first word.
704 SendKeyEvent(ui::VKEY_RIGHT, false, true);
705 SendKeyEvent(ui::VKEY_LEFT, false, true);
706 SendKeyEvent(ui::VKEY_O);
707 EXPECT_STR_EQ(" one two", textfield_->text());
708 EXPECT_STR_EQ(" one two", last_contents_);
709
710 // Ctrl+Left to move the cursor to the beginning of the first word.
711 SendKeyEvent(ui::VKEY_LEFT, false, true);
712 // Ctrl+Left again should move the cursor back to the very beginning.
713 SendKeyEvent(ui::VKEY_LEFT, false, true);
714 SendKeyEvent(ui::VKEY_DELETE);
715 EXPECT_STR_EQ("one two", textfield_->text());
716 EXPECT_STR_EQ("one two", last_contents_);
717 }
718
TEST_F(TextfieldTest,FocusTraversalTest)719 TEST_F(TextfieldTest, FocusTraversalTest) {
720 InitTextfields(3);
721 textfield_->RequestFocus();
722
723 EXPECT_EQ(1, GetFocusedView()->id());
724 widget_->GetFocusManager()->AdvanceFocus(false);
725 EXPECT_EQ(2, GetFocusedView()->id());
726 widget_->GetFocusManager()->AdvanceFocus(false);
727 EXPECT_EQ(3, GetFocusedView()->id());
728 // Cycle back to the first textfield.
729 widget_->GetFocusManager()->AdvanceFocus(false);
730 EXPECT_EQ(1, GetFocusedView()->id());
731
732 widget_->GetFocusManager()->AdvanceFocus(true);
733 EXPECT_EQ(3, GetFocusedView()->id());
734 widget_->GetFocusManager()->AdvanceFocus(true);
735 EXPECT_EQ(2, GetFocusedView()->id());
736 widget_->GetFocusManager()->AdvanceFocus(true);
737 EXPECT_EQ(1, GetFocusedView()->id());
738 // Cycle back to the last textfield.
739 widget_->GetFocusManager()->AdvanceFocus(true);
740 EXPECT_EQ(3, GetFocusedView()->id());
741
742 // Request focus should still work.
743 textfield_->RequestFocus();
744 EXPECT_EQ(1, GetFocusedView()->id());
745
746 // Test if clicking on textfield view sets the focus.
747 widget_->GetFocusManager()->AdvanceFocus(true);
748 EXPECT_EQ(3, GetFocusedView()->id());
749 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
750 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
751 textfield_->OnMousePressed(click);
752 EXPECT_EQ(1, GetFocusedView()->id());
753 }
754
TEST_F(TextfieldTest,ContextMenuDisplayTest)755 TEST_F(TextfieldTest, ContextMenuDisplayTest) {
756 InitTextfield();
757 EXPECT_TRUE(textfield_->context_menu_controller());
758 textfield_->SetText(ASCIIToUTF16("hello world"));
759 ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
760 textfield_->ClearEditHistory();
761 EXPECT_TRUE(GetContextMenuModel());
762 VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
763
764 textfield_->SelectAll(false);
765 VerifyTextfieldContextMenuContents(true, false, GetContextMenuModel());
766
767 SendKeyEvent(ui::VKEY_T);
768 VerifyTextfieldContextMenuContents(false, true, GetContextMenuModel());
769
770 textfield_->SelectAll(false);
771 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
772
773 // Exercise the "paste enabled?" check in the verifier.
774 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
775 VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
776 }
777
TEST_F(TextfieldTest,DoubleAndTripleClickTest)778 TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
779 InitTextfield();
780 textfield_->SetText(ASCIIToUTF16("hello world"));
781 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
782 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
783 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
784 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
785 ui::MouseEvent double_click(
786 ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
787 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
788 ui::EF_LEFT_MOUSE_BUTTON);
789
790 // Test for double click.
791 textfield_->OnMousePressed(click);
792 textfield_->OnMouseReleased(release);
793 EXPECT_TRUE(textfield_->GetSelectedText().empty());
794 textfield_->OnMousePressed(double_click);
795 textfield_->OnMouseReleased(release);
796 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
797
798 // Test for triple click.
799 textfield_->OnMousePressed(click);
800 textfield_->OnMouseReleased(release);
801 EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
802
803 // Another click should reset back to double click.
804 textfield_->OnMousePressed(click);
805 textfield_->OnMouseReleased(release);
806 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
807 }
808
TEST_F(TextfieldTest,DragToSelect)809 TEST_F(TextfieldTest, DragToSelect) {
810 InitTextfield();
811 textfield_->SetText(ASCIIToUTF16("hello world"));
812 const int kStart = GetCursorPositionX(5);
813 const int kEnd = 500;
814 gfx::Point start_point(kStart, 0);
815 gfx::Point end_point(kEnd, 0);
816 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point,
817 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
818 ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point,
819 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
820 ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(),
821 ui::EF_LEFT_MOUSE_BUTTON, 0);
822 ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point,
823 ui::EF_LEFT_MOUSE_BUTTON, 0);
824 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point,
825 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
826 textfield_->OnMousePressed(click_a);
827 EXPECT_TRUE(textfield_->GetSelectedText().empty());
828 // Check that dragging left selects the beginning of the string.
829 textfield_->OnMouseDragged(drag_left);
830 base::string16 text_left = textfield_->GetSelectedText();
831 EXPECT_STR_EQ("hello", text_left);
832 // Check that dragging right selects the rest of the string.
833 textfield_->OnMouseDragged(drag_right);
834 base::string16 text_right = textfield_->GetSelectedText();
835 EXPECT_STR_EQ(" world", text_right);
836 // Check that releasing in the same location does not alter the selection.
837 textfield_->OnMouseReleased(release);
838 EXPECT_EQ(text_right, textfield_->GetSelectedText());
839 // Check that dragging from beyond the text length works too.
840 textfield_->OnMousePressed(click_b);
841 textfield_->OnMouseDragged(drag_left);
842 textfield_->OnMouseReleased(release);
843 EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText());
844 }
845
846 #if defined(OS_WIN)
TEST_F(TextfieldTest,DragAndDrop_AcceptDrop)847 TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
848 InitTextfield();
849 textfield_->SetText(ASCIIToUTF16("hello world"));
850
851 ui::OSExchangeData data;
852 base::string16 string(ASCIIToUTF16("string "));
853 data.SetString(string);
854 int formats = 0;
855 std::set<OSExchangeData::CustomFormat> custom_formats;
856
857 // Ensure that disabled textfields do not accept drops.
858 textfield_->SetEnabled(false);
859 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
860 EXPECT_EQ(0, formats);
861 EXPECT_TRUE(custom_formats.empty());
862 EXPECT_FALSE(textfield_->CanDrop(data));
863 textfield_->SetEnabled(true);
864
865 // Ensure that read-only textfields do not accept drops.
866 textfield_->SetReadOnly(true);
867 EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
868 EXPECT_EQ(0, formats);
869 EXPECT_TRUE(custom_formats.empty());
870 EXPECT_FALSE(textfield_->CanDrop(data));
871 textfield_->SetReadOnly(false);
872
873 // Ensure that enabled and editable textfields do accept drops.
874 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
875 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
876 EXPECT_TRUE(custom_formats.empty());
877 EXPECT_TRUE(textfield_->CanDrop(data));
878 gfx::Point drop_point(GetCursorPositionX(6), 0);
879 ui::DropTargetEvent drop(data, drop_point, drop_point,
880 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE);
881 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
882 textfield_->OnDragUpdated(drop));
883 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_->OnPerformDrop(drop));
884 EXPECT_STR_EQ("hello string world", textfield_->text());
885
886 // Ensure that textfields do not accept non-OSExchangeData::STRING types.
887 ui::OSExchangeData bad_data;
888 bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
889 ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType();
890 bad_data.SetPickledData(fmt, Pickle());
891 bad_data.SetFileContents(base::FilePath(L"x"), "x");
892 bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
893 ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL);
894 bad_data.SetDownloadFileInfo(download);
895 EXPECT_FALSE(textfield_->CanDrop(bad_data));
896 }
897 #endif
898
TEST_F(TextfieldTest,DragAndDrop_InitiateDrag)899 TEST_F(TextfieldTest, DragAndDrop_InitiateDrag) {
900 InitTextfield();
901 textfield_->SetText(ASCIIToUTF16("hello string world"));
902
903 // Ensure the textfield will provide selected text for drag data.
904 base::string16 string;
905 ui::OSExchangeData data;
906 const gfx::Range kStringRange(6, 12);
907 textfield_->SelectRange(kStringRange);
908 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
909 textfield_->WriteDragDataForView(NULL, kStringPoint, &data);
910 EXPECT_TRUE(data.GetString(&string));
911 EXPECT_EQ(textfield_->GetSelectedText(), string);
912
913 // Ensure that disabled textfields do not support drag operations.
914 textfield_->SetEnabled(false);
915 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
916 textfield_->GetDragOperationsForView(NULL, kStringPoint));
917 textfield_->SetEnabled(true);
918 // Ensure that textfields without selections do not support drag operations.
919 textfield_->ClearSelection();
920 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
921 textfield_->GetDragOperationsForView(NULL, kStringPoint));
922 textfield_->SelectRange(kStringRange);
923 // Ensure that password textfields do not support drag operations.
924 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
925 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
926 textfield_->GetDragOperationsForView(NULL, kStringPoint));
927 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
928 // Ensure that textfields only initiate drag operations inside the selection.
929 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint,
930 ui::EF_LEFT_MOUSE_BUTTON,
931 ui::EF_LEFT_MOUSE_BUTTON);
932 textfield_->OnMousePressed(press_event);
933 EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
934 textfield_->GetDragOperationsForView(NULL, gfx::Point()));
935 EXPECT_FALSE(textfield_->CanStartDragForView(NULL, gfx::Point(),
936 gfx::Point()));
937 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY,
938 textfield_->GetDragOperationsForView(NULL, kStringPoint));
939 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
940 gfx::Point()));
941 // Ensure that textfields support local moves.
942 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
943 textfield_->GetDragOperationsForView(textfield_, kStringPoint));
944 }
945
TEST_F(TextfieldTest,DragAndDrop_ToTheRight)946 TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
947 InitTextfield();
948 textfield_->SetText(ASCIIToUTF16("hello world"));
949
950 base::string16 string;
951 ui::OSExchangeData data;
952 int formats = 0;
953 int operations = 0;
954 std::set<OSExchangeData::CustomFormat> custom_formats;
955
956 // Start dragging "ello".
957 textfield_->SelectRange(gfx::Range(1, 5));
958 gfx::Point point(GetCursorPositionX(3), 0);
959 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
960 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
961 textfield_->OnMousePressed(click_a);
962 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
963 gfx::Point()));
964 operations = textfield_->GetDragOperationsForView(textfield_,
965 click_a.location());
966 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
967 operations);
968 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
969 EXPECT_TRUE(data.GetString(&string));
970 EXPECT_EQ(textfield_->GetSelectedText(), string);
971 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
972 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
973 EXPECT_TRUE(custom_formats.empty());
974
975 // Drop "ello" after "w".
976 const gfx::Point kDropPoint(GetCursorPositionX(7), 0);
977 EXPECT_TRUE(textfield_->CanDrop(data));
978 ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
979 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
980 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
981 EXPECT_STR_EQ("h welloorld", textfield_->text());
982 textfield_->OnDragDone();
983
984 // Undo/Redo the drag&drop change.
985 SendKeyEvent(ui::VKEY_Z, false, true);
986 EXPECT_STR_EQ("hello world", textfield_->text());
987 SendKeyEvent(ui::VKEY_Z, false, true);
988 EXPECT_STR_EQ("", textfield_->text());
989 SendKeyEvent(ui::VKEY_Z, false, true);
990 EXPECT_STR_EQ("", textfield_->text());
991 SendKeyEvent(ui::VKEY_Y, false, true);
992 EXPECT_STR_EQ("hello world", textfield_->text());
993 SendKeyEvent(ui::VKEY_Y, false, true);
994 EXPECT_STR_EQ("h welloorld", textfield_->text());
995 SendKeyEvent(ui::VKEY_Y, false, true);
996 EXPECT_STR_EQ("h welloorld", textfield_->text());
997 }
998
TEST_F(TextfieldTest,DragAndDrop_ToTheLeft)999 TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
1000 InitTextfield();
1001 textfield_->SetText(ASCIIToUTF16("hello world"));
1002
1003 base::string16 string;
1004 ui::OSExchangeData data;
1005 int formats = 0;
1006 int operations = 0;
1007 std::set<OSExchangeData::CustomFormat> custom_formats;
1008
1009 // Start dragging " worl".
1010 textfield_->SelectRange(gfx::Range(5, 10));
1011 gfx::Point point(GetCursorPositionX(7), 0);
1012 ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
1013 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1014 textfield_->OnMousePressed(click_a);
1015 EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
1016 gfx::Point()));
1017 operations = textfield_->GetDragOperationsForView(textfield_,
1018 click_a.location());
1019 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
1020 operations);
1021 textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
1022 EXPECT_TRUE(data.GetString(&string));
1023 EXPECT_EQ(textfield_->GetSelectedText(), string);
1024 EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
1025 EXPECT_EQ(ui::OSExchangeData::STRING, formats);
1026 EXPECT_TRUE(custom_formats.empty());
1027
1028 // Drop " worl" after "h".
1029 EXPECT_TRUE(textfield_->CanDrop(data));
1030 gfx::Point drop_point(GetCursorPositionX(1), 0);
1031 ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
1032 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
1033 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
1034 EXPECT_STR_EQ("h worlellod", textfield_->text());
1035 textfield_->OnDragDone();
1036
1037 // Undo/Redo the drag&drop change.
1038 SendKeyEvent(ui::VKEY_Z, false, true);
1039 EXPECT_STR_EQ("hello world", textfield_->text());
1040 SendKeyEvent(ui::VKEY_Z, false, true);
1041 EXPECT_STR_EQ("", textfield_->text());
1042 SendKeyEvent(ui::VKEY_Z, false, true);
1043 EXPECT_STR_EQ("", textfield_->text());
1044 SendKeyEvent(ui::VKEY_Y, false, true);
1045 EXPECT_STR_EQ("hello world", textfield_->text());
1046 SendKeyEvent(ui::VKEY_Y, false, true);
1047 EXPECT_STR_EQ("h worlellod", textfield_->text());
1048 SendKeyEvent(ui::VKEY_Y, false, true);
1049 EXPECT_STR_EQ("h worlellod", textfield_->text());
1050 }
1051
TEST_F(TextfieldTest,DragAndDrop_Canceled)1052 TEST_F(TextfieldTest, DragAndDrop_Canceled) {
1053 InitTextfield();
1054 textfield_->SetText(ASCIIToUTF16("hello world"));
1055
1056 // Start dragging "worl".
1057 textfield_->SelectRange(gfx::Range(6, 10));
1058 gfx::Point point(GetCursorPositionX(8), 0);
1059 ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
1060 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1061 textfield_->OnMousePressed(click);
1062 ui::OSExchangeData data;
1063 textfield_->WriteDragDataForView(NULL, click.location(), &data);
1064 EXPECT_TRUE(textfield_->CanDrop(data));
1065 // Drag the text over somewhere valid, outside the current selection.
1066 gfx::Point drop_point(GetCursorPositionX(2), 0);
1067 ui::DropTargetEvent drop(data, drop_point, drop_point,
1068 ui::DragDropTypes::DRAG_MOVE);
1069 EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop));
1070 // "Cancel" the drag, via move and release over the selection, and OnDragDone.
1071 gfx::Point drag_point(GetCursorPositionX(9), 0);
1072 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point,
1073 ui::EF_LEFT_MOUSE_BUTTON, 0);
1074 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point,
1075 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1076 textfield_->OnMouseDragged(drag);
1077 textfield_->OnMouseReleased(release);
1078 textfield_->OnDragDone();
1079 EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text());
1080 }
1081
TEST_F(TextfieldTest,ReadOnlyTest)1082 TEST_F(TextfieldTest, ReadOnlyTest) {
1083 InitTextfield();
1084 textfield_->SetText(ASCIIToUTF16("read only"));
1085 textfield_->SetReadOnly(true);
1086 EXPECT_TRUE(textfield_->enabled());
1087 EXPECT_TRUE(textfield_->IsFocusable());
1088
1089 SendKeyEvent(ui::VKEY_HOME);
1090 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1091 SendKeyEvent(ui::VKEY_END);
1092 EXPECT_EQ(9U, textfield_->GetCursorPosition());
1093
1094 SendKeyEvent(ui::VKEY_LEFT, false, false);
1095 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1096 SendKeyEvent(ui::VKEY_LEFT, false, true);
1097 EXPECT_EQ(5U, textfield_->GetCursorPosition());
1098 SendKeyEvent(ui::VKEY_LEFT, true, true);
1099 EXPECT_EQ(0U, textfield_->GetCursorPosition());
1100 EXPECT_STR_EQ("read ", textfield_->GetSelectedText());
1101 textfield_->SelectAll(false);
1102 EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
1103
1104 // Cut should be disabled.
1105 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1106 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1107 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1108 SendKeyEvent(ui::VKEY_X, false, true);
1109 SendKeyEvent(ui::VKEY_DELETE, true, false);
1110 EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1111 EXPECT_STR_EQ("read only", textfield_->text());
1112
1113 // Paste should be disabled.
1114 EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1115 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1116 SendKeyEvent(ui::VKEY_V, false, true);
1117 SendKeyEvent(ui::VKEY_INSERT, true, false);
1118 EXPECT_STR_EQ("read only", textfield_->text());
1119
1120 // Copy should work normally.
1121 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1122 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1123 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1124 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1125 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1126 SendKeyEvent(ui::VKEY_C, false, true);
1127 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1128 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
1129 SendKeyEvent(ui::VKEY_INSERT, false, true);
1130 EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1131
1132 // SetText should work even in read only mode.
1133 textfield_->SetText(ASCIIToUTF16(" four five six "));
1134 EXPECT_STR_EQ(" four five six ", textfield_->text());
1135
1136 textfield_->SelectAll(false);
1137 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1138
1139 // Text field is unmodifiable and selection shouldn't change.
1140 SendKeyEvent(ui::VKEY_DELETE);
1141 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1142 SendKeyEvent(ui::VKEY_BACK);
1143 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1144 SendKeyEvent(ui::VKEY_T);
1145 EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
1146 }
1147
TEST_F(TextfieldTest,TextInputClientTest)1148 TEST_F(TextfieldTest, TextInputClientTest) {
1149 InitTextfield();
1150 ui::TextInputClient* client = textfield_->GetTextInputClient();
1151 EXPECT_TRUE(client);
1152 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType());
1153
1154 textfield_->SetText(ASCIIToUTF16("0123456789"));
1155 gfx::Range range;
1156 EXPECT_TRUE(client->GetTextRange(&range));
1157 EXPECT_EQ(0U, range.start());
1158 EXPECT_EQ(10U, range.end());
1159
1160 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4)));
1161 EXPECT_TRUE(client->GetSelectionRange(&range));
1162 EXPECT_EQ(gfx::Range(1, 4), range);
1163
1164 base::string16 substring;
1165 EXPECT_TRUE(client->GetTextFromRange(range, &substring));
1166 EXPECT_STR_EQ("123", substring);
1167
1168 EXPECT_TRUE(client->DeleteRange(range));
1169 EXPECT_STR_EQ("0456789", textfield_->text());
1170
1171 ui::CompositionText composition;
1172 composition.text = UTF8ToUTF16("321");
1173 // Set composition through input method.
1174 input_method_->Clear();
1175 input_method_->SetCompositionTextForNextKey(composition);
1176 textfield_->clear();
1177
1178 on_before_user_action_ = on_after_user_action_ = 0;
1179 SendKeyEvent(ui::VKEY_A);
1180 EXPECT_TRUE(textfield_->key_received());
1181 EXPECT_FALSE(textfield_->key_handled());
1182 EXPECT_TRUE(client->HasCompositionText());
1183 EXPECT_TRUE(client->GetCompositionTextRange(&range));
1184 EXPECT_STR_EQ("0321456789", textfield_->text());
1185 EXPECT_EQ(gfx::Range(1, 4), range);
1186 EXPECT_EQ(1, on_before_user_action_);
1187 EXPECT_EQ(1, on_after_user_action_);
1188
1189 input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
1190 on_before_user_action_ = on_after_user_action_ = 0;
1191 textfield_->clear();
1192 SendKeyEvent(ui::VKEY_A);
1193 EXPECT_TRUE(textfield_->key_received());
1194 EXPECT_FALSE(textfield_->key_handled());
1195 EXPECT_FALSE(client->HasCompositionText());
1196 EXPECT_FALSE(input_method_->cancel_composition_called());
1197 EXPECT_STR_EQ("0123456789", textfield_->text());
1198 EXPECT_EQ(1, on_before_user_action_);
1199 EXPECT_EQ(1, on_after_user_action_);
1200
1201 input_method_->Clear();
1202 input_method_->SetCompositionTextForNextKey(composition);
1203 textfield_->clear();
1204 SendKeyEvent(ui::VKEY_A);
1205 EXPECT_TRUE(client->HasCompositionText());
1206 EXPECT_STR_EQ("0123321456789", textfield_->text());
1207
1208 on_before_user_action_ = on_after_user_action_ = 0;
1209 textfield_->clear();
1210 SendKeyEvent(ui::VKEY_RIGHT);
1211 EXPECT_FALSE(client->HasCompositionText());
1212 EXPECT_TRUE(input_method_->cancel_composition_called());
1213 EXPECT_TRUE(textfield_->key_received());
1214 EXPECT_TRUE(textfield_->key_handled());
1215 EXPECT_STR_EQ("0123321456789", textfield_->text());
1216 EXPECT_EQ(8U, textfield_->GetCursorPosition());
1217 EXPECT_EQ(1, on_before_user_action_);
1218 EXPECT_EQ(1, on_after_user_action_);
1219
1220 textfield_->clear();
1221 textfield_->SetText(ASCIIToUTF16("0123456789"));
1222 EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5)));
1223 client->ExtendSelectionAndDelete(4, 2);
1224 EXPECT_STR_EQ("0789", textfield_->text());
1225
1226 // On{Before,After}UserAction should be called by whatever user action
1227 // triggers clearing or setting a selection if appropriate.
1228 on_before_user_action_ = on_after_user_action_ = 0;
1229 textfield_->clear();
1230 textfield_->ClearSelection();
1231 textfield_->SelectAll(false);
1232 EXPECT_EQ(0, on_before_user_action_);
1233 EXPECT_EQ(0, on_after_user_action_);
1234
1235 input_method_->Clear();
1236 textfield_->SetReadOnly(true);
1237 EXPECT_TRUE(input_method_->text_input_type_changed());
1238 EXPECT_FALSE(textfield_->GetTextInputClient());
1239
1240 textfield_->SetReadOnly(false);
1241 input_method_->Clear();
1242 textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1243 EXPECT_TRUE(input_method_->text_input_type_changed());
1244 EXPECT_TRUE(textfield_->GetTextInputClient());
1245 }
1246
TEST_F(TextfieldTest,UndoRedoTest)1247 TEST_F(TextfieldTest, UndoRedoTest) {
1248 InitTextfield();
1249 SendKeyEvent(ui::VKEY_A);
1250 EXPECT_STR_EQ("a", textfield_->text());
1251 SendKeyEvent(ui::VKEY_Z, false, true);
1252 EXPECT_STR_EQ("", textfield_->text());
1253 SendKeyEvent(ui::VKEY_Z, false, true);
1254 EXPECT_STR_EQ("", textfield_->text());
1255 SendKeyEvent(ui::VKEY_Y, false, true);
1256 EXPECT_STR_EQ("a", textfield_->text());
1257 SendKeyEvent(ui::VKEY_Y, false, true);
1258 EXPECT_STR_EQ("a", textfield_->text());
1259
1260 // AppendText
1261 textfield_->AppendText(ASCIIToUTF16("b"));
1262 last_contents_.clear(); // AppendText doesn't call ContentsChanged.
1263 EXPECT_STR_EQ("ab", textfield_->text());
1264 SendKeyEvent(ui::VKEY_Z, false, true);
1265 EXPECT_STR_EQ("a", textfield_->text());
1266 SendKeyEvent(ui::VKEY_Y, false, true);
1267 EXPECT_STR_EQ("ab", textfield_->text());
1268
1269 // SetText
1270 SendKeyEvent(ui::VKEY_C);
1271 // Undo'ing append moves the cursor to the end for now.
1272 // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
1273 EXPECT_STR_EQ("abc", textfield_->text());
1274 textfield_->SetText(ASCIIToUTF16("abc"));
1275 EXPECT_STR_EQ("abc", textfield_->text());
1276 SendKeyEvent(ui::VKEY_Z, false, true);
1277 EXPECT_STR_EQ("ab", textfield_->text());
1278 SendKeyEvent(ui::VKEY_Y, false, true);
1279 EXPECT_STR_EQ("abc", textfield_->text());
1280 SendKeyEvent(ui::VKEY_Y, false, true);
1281 EXPECT_STR_EQ("abc", textfield_->text());
1282 textfield_->SetText(ASCIIToUTF16("123"));
1283 textfield_->SetText(ASCIIToUTF16("123"));
1284 EXPECT_STR_EQ("123", textfield_->text());
1285 SendKeyEvent(ui::VKEY_END, false, false);
1286 SendKeyEvent(ui::VKEY_4, false, false);
1287 EXPECT_STR_EQ("1234", textfield_->text());
1288 last_contents_.clear();
1289 SendKeyEvent(ui::VKEY_Z, false, true);
1290 EXPECT_STR_EQ("123", textfield_->text());
1291 SendKeyEvent(ui::VKEY_Z, false, true);
1292 // the insert edit "c" and set edit "123" are merged to single edit,
1293 // so text becomes "ab" after undo.
1294 EXPECT_STR_EQ("ab", textfield_->text());
1295 SendKeyEvent(ui::VKEY_Z, false, true);
1296 EXPECT_STR_EQ("a", textfield_->text());
1297 SendKeyEvent(ui::VKEY_Y, false, true);
1298 EXPECT_STR_EQ("ab", textfield_->text());
1299 SendKeyEvent(ui::VKEY_Y, false, true);
1300 EXPECT_STR_EQ("123", textfield_->text());
1301 SendKeyEvent(ui::VKEY_Y, false, true);
1302 EXPECT_STR_EQ("1234", textfield_->text());
1303
1304 // Undoing to the same text shouldn't call ContentsChanged.
1305 SendKeyEvent(ui::VKEY_A, false, true); // select all
1306 SendKeyEvent(ui::VKEY_A);
1307 EXPECT_STR_EQ("a", textfield_->text());
1308 SendKeyEvent(ui::VKEY_B);
1309 SendKeyEvent(ui::VKEY_C);
1310 EXPECT_STR_EQ("abc", textfield_->text());
1311 SendKeyEvent(ui::VKEY_Z, false, true);
1312 EXPECT_STR_EQ("1234", textfield_->text());
1313 SendKeyEvent(ui::VKEY_Y, false, true);
1314 EXPECT_STR_EQ("abc", textfield_->text());
1315
1316 // Delete/Backspace
1317 SendKeyEvent(ui::VKEY_BACK);
1318 EXPECT_STR_EQ("ab", textfield_->text());
1319 SendKeyEvent(ui::VKEY_HOME);
1320 SendKeyEvent(ui::VKEY_DELETE);
1321 EXPECT_STR_EQ("b", textfield_->text());
1322 SendKeyEvent(ui::VKEY_A, false, true);
1323 SendKeyEvent(ui::VKEY_DELETE);
1324 EXPECT_STR_EQ("", textfield_->text());
1325 SendKeyEvent(ui::VKEY_Z, false, true);
1326 EXPECT_STR_EQ("b", textfield_->text());
1327 SendKeyEvent(ui::VKEY_Z, false, true);
1328 EXPECT_STR_EQ("ab", textfield_->text());
1329 SendKeyEvent(ui::VKEY_Z, false, true);
1330 EXPECT_STR_EQ("abc", textfield_->text());
1331 SendKeyEvent(ui::VKEY_Y, false, true);
1332 EXPECT_STR_EQ("ab", textfield_->text());
1333 SendKeyEvent(ui::VKEY_Y, false, true);
1334 EXPECT_STR_EQ("b", textfield_->text());
1335 SendKeyEvent(ui::VKEY_Y, false, true);
1336 EXPECT_STR_EQ("", textfield_->text());
1337 SendKeyEvent(ui::VKEY_Y, false, true);
1338 EXPECT_STR_EQ("", textfield_->text());
1339 }
1340
TEST_F(TextfieldTest,CutCopyPaste)1341 TEST_F(TextfieldTest, CutCopyPaste) {
1342 InitTextfield();
1343
1344 // Ensure IDS_APP_CUT cuts.
1345 textfield_->SetText(ASCIIToUTF16("123"));
1346 textfield_->SelectAll(false);
1347 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
1348 textfield_->ExecuteCommand(IDS_APP_CUT, 0);
1349 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1350 EXPECT_STR_EQ("", textfield_->text());
1351 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1352
1353 // Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
1354 textfield_->SetText(ASCIIToUTF16("456"));
1355 textfield_->SelectAll(false);
1356 SendKeyEvent(ui::VKEY_X, true, false, true, false);
1357 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1358 EXPECT_STR_EQ("456", textfield_->text());
1359 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1360 SendKeyEvent(ui::VKEY_X, false, true);
1361 EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1362 EXPECT_STR_EQ("", textfield_->text());
1363 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1364
1365 // Ensure [Shift]+[Delete] cuts.
1366 textfield_->SetText(ASCIIToUTF16("123"));
1367 textfield_->SelectAll(false);
1368 SendKeyEvent(ui::VKEY_DELETE, true, false);
1369 EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1370 EXPECT_STR_EQ("", textfield_->text());
1371 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1372
1373 // Ensure IDS_APP_COPY copies.
1374 textfield_->SetText(ASCIIToUTF16("789"));
1375 textfield_->SelectAll(false);
1376 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
1377 textfield_->ExecuteCommand(IDS_APP_COPY, 0);
1378 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1379 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1380
1381 // Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
1382 textfield_->SetText(ASCIIToUTF16("012"));
1383 textfield_->SelectAll(false);
1384 SendKeyEvent(ui::VKEY_C, true, false, true, false);
1385 EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1386 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1387 SendKeyEvent(ui::VKEY_C, false, true);
1388 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1389 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1390
1391 // Ensure [Ctrl]+[Insert] copies.
1392 textfield_->SetText(ASCIIToUTF16("345"));
1393 textfield_->SelectAll(false);
1394 SendKeyEvent(ui::VKEY_INSERT, false, true);
1395 EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1396 EXPECT_STR_EQ("345", textfield_->text());
1397 EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
1398
1399 // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
1400 // also ensure that [Ctrl]+[Alt]+[V] does nothing.
1401 SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
1402 textfield_->SetText(base::string16());
1403 EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
1404 textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
1405 EXPECT_STR_EQ("abc", textfield_->text());
1406 SendKeyEvent(ui::VKEY_V, false, true);
1407 EXPECT_STR_EQ("abcabc", textfield_->text());
1408 SendKeyEvent(ui::VKEY_INSERT, true, false);
1409 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1410 SendKeyEvent(ui::VKEY_V, true, false, true, false);
1411 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1412
1413 // Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
1414 textfield_->SelectAll(false);
1415 SendKeyEvent(ui::VKEY_INSERT, true, true);
1416 EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
1417 EXPECT_STR_EQ("abcabcabc", textfield_->text());
1418 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1419 }
1420
TEST_F(TextfieldTest,OvertypeMode)1421 TEST_F(TextfieldTest, OvertypeMode) {
1422 InitTextfield();
1423 // Overtype mode should be disabled (no-op [Insert]).
1424 textfield_->SetText(ASCIIToUTF16("2"));
1425 SendKeyEvent(ui::VKEY_HOME);
1426 SendKeyEvent(ui::VKEY_INSERT);
1427 SendKeyEvent(ui::VKEY_1, false, false);
1428 EXPECT_STR_EQ("12", textfield_->text());
1429 }
1430
TEST_F(TextfieldTest,TextCursorDisplayTest)1431 TEST_F(TextfieldTest, TextCursorDisplayTest) {
1432 InitTextfield();
1433 // LTR-RTL string in LTR context.
1434 SendKeyEvent('a');
1435 EXPECT_STR_EQ("a", textfield_->text());
1436 int x = GetCursorBounds().x();
1437 int prev_x = x;
1438
1439 SendKeyEvent('b');
1440 EXPECT_STR_EQ("ab", textfield_->text());
1441 x = GetCursorBounds().x();
1442 EXPECT_LT(prev_x, x);
1443 prev_x = x;
1444
1445 SendKeyEvent(0x05E1);
1446 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1447 x = GetCursorBounds().x();
1448 EXPECT_EQ(prev_x, x);
1449
1450 SendKeyEvent(0x05E2);
1451 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1452 x = GetCursorBounds().x();
1453 EXPECT_EQ(prev_x, x);
1454
1455 // Clear text.
1456 SendKeyEvent(ui::VKEY_A, false, true);
1457 SendKeyEvent('\n');
1458
1459 // RTL-LTR string in LTR context.
1460 SendKeyEvent(0x05E1);
1461 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1462 x = GetCursorBounds().x();
1463 EXPECT_EQ(GetDisplayRect().x(), x);
1464 prev_x = x;
1465
1466 SendKeyEvent(0x05E2);
1467 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1468 x = GetCursorBounds().x();
1469 EXPECT_EQ(prev_x, x);
1470
1471 SendKeyEvent('a');
1472 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1473 x = GetCursorBounds().x();
1474 EXPECT_LT(prev_x, x);
1475 prev_x = x;
1476
1477 SendKeyEvent('b');
1478 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1479 x = GetCursorBounds().x();
1480 EXPECT_LT(prev_x, x);
1481 }
1482
TEST_F(TextfieldTest,TextCursorDisplayInRTLTest)1483 TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
1484 std::string locale = l10n_util::GetApplicationLocale("");
1485 base::i18n::SetICUDefaultLocale("he");
1486
1487 InitTextfield();
1488 // LTR-RTL string in RTL context.
1489 SendKeyEvent('a');
1490 EXPECT_STR_EQ("a", textfield_->text());
1491 int x = GetCursorBounds().x();
1492 EXPECT_EQ(GetDisplayRect().right() - 1, x);
1493 int prev_x = x;
1494
1495 SendKeyEvent('b');
1496 EXPECT_STR_EQ("ab", textfield_->text());
1497 x = GetCursorBounds().x();
1498 EXPECT_EQ(prev_x, x);
1499
1500 SendKeyEvent(0x05E1);
1501 EXPECT_EQ(WideToUTF16(L"ab\x05E1"), textfield_->text());
1502 x = GetCursorBounds().x();
1503 EXPECT_GT(prev_x, x);
1504 prev_x = x;
1505
1506 SendKeyEvent(0x05E2);
1507 EXPECT_EQ(WideToUTF16(L"ab\x05E1\x5E2"), textfield_->text());
1508 x = GetCursorBounds().x();
1509 EXPECT_GT(prev_x, x);
1510
1511 SendKeyEvent(ui::VKEY_A, false, true);
1512 SendKeyEvent('\n');
1513
1514 // RTL-LTR string in RTL context.
1515 SendKeyEvent(0x05E1);
1516 EXPECT_EQ(WideToUTF16(L"\x05E1"), textfield_->text());
1517 x = GetCursorBounds().x();
1518 prev_x = x;
1519
1520 SendKeyEvent(0x05E2);
1521 EXPECT_EQ(WideToUTF16(L"\x05E1\x05E2"), textfield_->text());
1522 x = GetCursorBounds().x();
1523 EXPECT_GT(prev_x, x);
1524 prev_x = x;
1525
1526 SendKeyEvent('a');
1527 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"a"), textfield_->text());
1528 x = GetCursorBounds().x();
1529 EXPECT_EQ(prev_x, x);
1530 prev_x = x;
1531
1532 SendKeyEvent('b');
1533 EXPECT_EQ(WideToUTF16(L"\x05E1\x5E2" L"ab"), textfield_->text());
1534 x = GetCursorBounds().x();
1535 EXPECT_EQ(prev_x, x);
1536
1537 // Reset locale.
1538 base::i18n::SetICUDefaultLocale(locale);
1539 }
1540
TEST_F(TextfieldTest,HitInsideTextAreaTest)1541 TEST_F(TextfieldTest, HitInsideTextAreaTest) {
1542 InitTextfield();
1543 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1544 std::vector<gfx::Rect> cursor_bounds;
1545
1546 // Save each cursor bound.
1547 gfx::SelectionModel sel(0, gfx::CURSOR_FORWARD);
1548 cursor_bounds.push_back(GetCursorBounds(sel));
1549
1550 sel = gfx::SelectionModel(1, gfx::CURSOR_BACKWARD);
1551 gfx::Rect bound = GetCursorBounds(sel);
1552 sel = gfx::SelectionModel(1, gfx::CURSOR_FORWARD);
1553 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1554 cursor_bounds.push_back(bound);
1555
1556 // Check that a cursor at the end of the Latin portion of the text is at the
1557 // same position as a cursor placed at the end of the RTL Hebrew portion.
1558 sel = gfx::SelectionModel(2, gfx::CURSOR_BACKWARD);
1559 bound = GetCursorBounds(sel);
1560 sel = gfx::SelectionModel(4, gfx::CURSOR_BACKWARD);
1561 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1562 cursor_bounds.push_back(bound);
1563
1564 sel = gfx::SelectionModel(3, gfx::CURSOR_BACKWARD);
1565 bound = GetCursorBounds(sel);
1566 sel = gfx::SelectionModel(3, gfx::CURSOR_FORWARD);
1567 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1568 cursor_bounds.push_back(bound);
1569
1570 sel = gfx::SelectionModel(2, gfx::CURSOR_FORWARD);
1571 bound = GetCursorBounds(sel);
1572 sel = gfx::SelectionModel(4, gfx::CURSOR_FORWARD);
1573 EXPECT_EQ(bound.x(), GetCursorBounds(sel).x());
1574 cursor_bounds.push_back(bound);
1575
1576 // Expected cursor position when clicking left and right of each character.
1577 size_t cursor_pos_expected[] = {0, 1, 1, 2, 4, 3, 3, 2};
1578
1579 int index = 0;
1580 for (int i = 0; i < static_cast<int>(cursor_bounds.size() - 1); ++i) {
1581 int half_width = (cursor_bounds[i + 1].x() - cursor_bounds[i].x()) / 2;
1582 MouseClick(cursor_bounds[i], half_width / 2);
1583 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1584
1585 // To avoid trigger double click. Not using sleep() since it takes longer
1586 // for the test to run if using sleep().
1587 NonClientMouseClick();
1588
1589 MouseClick(cursor_bounds[i + 1], - (half_width / 2));
1590 EXPECT_EQ(cursor_pos_expected[index++], textfield_->GetCursorPosition());
1591
1592 NonClientMouseClick();
1593 }
1594 }
1595
TEST_F(TextfieldTest,HitOutsideTextAreaTest)1596 TEST_F(TextfieldTest, HitOutsideTextAreaTest) {
1597 InitTextfield();
1598
1599 // LTR-RTL string in LTR context.
1600 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1601
1602 SendKeyEvent(ui::VKEY_HOME);
1603 gfx::Rect bound = GetCursorBounds();
1604 MouseClick(bound, -10);
1605 EXPECT_EQ(bound, GetCursorBounds());
1606
1607 SendKeyEvent(ui::VKEY_END);
1608 bound = GetCursorBounds();
1609 MouseClick(bound, 10);
1610 EXPECT_EQ(bound, GetCursorBounds());
1611
1612 NonClientMouseClick();
1613
1614 // RTL-LTR string in LTR context.
1615 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
1616
1617 SendKeyEvent(ui::VKEY_HOME);
1618 bound = GetCursorBounds();
1619 MouseClick(bound, 10);
1620 EXPECT_EQ(bound, GetCursorBounds());
1621
1622 SendKeyEvent(ui::VKEY_END);
1623 bound = GetCursorBounds();
1624 MouseClick(bound, -10);
1625 EXPECT_EQ(bound, GetCursorBounds());
1626 }
1627
TEST_F(TextfieldTest,HitOutsideTextAreaInRTLTest)1628 TEST_F(TextfieldTest, HitOutsideTextAreaInRTLTest) {
1629 std::string locale = l10n_util::GetApplicationLocale("");
1630 base::i18n::SetICUDefaultLocale("he");
1631
1632 InitTextfield();
1633
1634 // RTL-LTR string in RTL context.
1635 textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
1636 SendKeyEvent(ui::VKEY_HOME);
1637 gfx::Rect bound = GetCursorBounds();
1638 MouseClick(bound, 10);
1639 EXPECT_EQ(bound, GetCursorBounds());
1640
1641 SendKeyEvent(ui::VKEY_END);
1642 bound = GetCursorBounds();
1643 MouseClick(bound, -10);
1644 EXPECT_EQ(bound, GetCursorBounds());
1645
1646 NonClientMouseClick();
1647
1648 // LTR-RTL string in RTL context.
1649 textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
1650 SendKeyEvent(ui::VKEY_HOME);
1651 bound = GetCursorBounds();
1652 MouseClick(bound, -10);
1653 EXPECT_EQ(bound, GetCursorBounds());
1654
1655 SendKeyEvent(ui::VKEY_END);
1656 bound = GetCursorBounds();
1657 MouseClick(bound, 10);
1658 EXPECT_EQ(bound, GetCursorBounds());
1659
1660 // Reset locale.
1661 base::i18n::SetICUDefaultLocale(locale);
1662 }
1663
TEST_F(TextfieldTest,OverflowTest)1664 TEST_F(TextfieldTest, OverflowTest) {
1665 InitTextfield();
1666
1667 base::string16 str;
1668 for (int i = 0; i < 500; ++i)
1669 SendKeyEvent('a');
1670 SendKeyEvent(kHebrewLetterSamekh);
1671 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1672
1673 // Test mouse pointing.
1674 MouseClick(GetCursorBounds(), -1);
1675 EXPECT_EQ(500U, textfield_->GetCursorPosition());
1676
1677 // Clear text.
1678 SendKeyEvent(ui::VKEY_A, false, true);
1679 SendKeyEvent('\n');
1680
1681 for (int i = 0; i < 500; ++i)
1682 SendKeyEvent(kHebrewLetterSamekh);
1683 SendKeyEvent('a');
1684 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1685
1686 MouseClick(GetCursorBounds(), -1);
1687 EXPECT_EQ(501U, textfield_->GetCursorPosition());
1688 }
1689
TEST_F(TextfieldTest,OverflowInRTLTest)1690 TEST_F(TextfieldTest, OverflowInRTLTest) {
1691 std::string locale = l10n_util::GetApplicationLocale("");
1692 base::i18n::SetICUDefaultLocale("he");
1693
1694 InitTextfield();
1695
1696 base::string16 str;
1697 for (int i = 0; i < 500; ++i)
1698 SendKeyEvent('a');
1699 SendKeyEvent(kHebrewLetterSamekh);
1700 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1701
1702 MouseClick(GetCursorBounds(), 1);
1703 EXPECT_EQ(501U, textfield_->GetCursorPosition());
1704
1705 // Clear text.
1706 SendKeyEvent(ui::VKEY_A, false, true);
1707 SendKeyEvent('\n');
1708
1709 for (int i = 0; i < 500; ++i)
1710 SendKeyEvent(kHebrewLetterSamekh);
1711 SendKeyEvent('a');
1712 EXPECT_TRUE(GetDisplayRect().Contains(GetCursorBounds()));
1713
1714 MouseClick(GetCursorBounds(), 1);
1715 EXPECT_EQ(500U, textfield_->GetCursorPosition());
1716
1717 // Reset locale.
1718 base::i18n::SetICUDefaultLocale(locale);
1719 }
1720
TEST_F(TextfieldTest,GetCompositionCharacterBoundsTest)1721 TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) {
1722 InitTextfield();
1723 ui::CompositionText composition;
1724 composition.text = UTF8ToUTF16("abc123");
1725 const uint32 char_count = static_cast<uint32>(composition.text.length());
1726 ui::TextInputClient* client = textfield_->GetTextInputClient();
1727
1728 // Compare the composition character bounds with surrounding cursor bounds.
1729 for (uint32 i = 0; i < char_count; ++i) {
1730 composition.selection = gfx::Range(i);
1731 client->SetCompositionText(composition);
1732 gfx::Point cursor_origin = GetCursorBounds().origin();
1733 views::View::ConvertPointToScreen(textfield_, &cursor_origin);
1734
1735 composition.selection = gfx::Range(i + 1);
1736 client->SetCompositionText(composition);
1737 gfx::Point next_cursor_bottom_left = GetCursorBounds().bottom_left();
1738 views::View::ConvertPointToScreen(textfield_, &next_cursor_bottom_left);
1739
1740 gfx::Rect character;
1741 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &character));
1742 EXPECT_EQ(character.origin(), cursor_origin) << " i=" << i;
1743 EXPECT_EQ(character.bottom_right(), next_cursor_bottom_left) << " i=" << i;
1744 }
1745
1746 // Return false if the index is out of range.
1747 gfx::Rect rect;
1748 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count, &rect));
1749 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 1, &rect));
1750 EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect));
1751 }
1752
TEST_F(TextfieldTest,GetCompositionCharacterBounds_ComplexText)1753 TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
1754 InitTextfield();
1755
1756 const base::char16 kUtf16Chars[] = {
1757 // U+0020 SPACE
1758 0x0020,
1759 // U+1F408 (CAT) as surrogate pair
1760 0xd83d, 0xdc08,
1761 // U+5642 as Ideographic Variation Sequences
1762 0x5642, 0xDB40, 0xDD00,
1763 // U+260E (BLACK TELEPHONE) as Emoji Variation Sequences
1764 0x260E, 0xFE0F,
1765 // U+0020 SPACE
1766 0x0020,
1767 };
1768 const size_t kUtf16CharsCount = arraysize(kUtf16Chars);
1769
1770 ui::CompositionText composition;
1771 composition.text.assign(kUtf16Chars, kUtf16Chars + kUtf16CharsCount);
1772 ui::TextInputClient* client = textfield_->GetTextInputClient();
1773 client->SetCompositionText(composition);
1774
1775 // Make sure GetCompositionCharacterBounds never fails for index.
1776 gfx::Rect rects[kUtf16CharsCount];
1777 gfx::Rect prev_cursor = GetCursorBounds();
1778 for (uint32 i = 0; i < kUtf16CharsCount; ++i)
1779 EXPECT_TRUE(client->GetCompositionCharacterBounds(i, &rects[i]));
1780
1781 // Here we might expect the following results but it actually depends on how
1782 // Uniscribe or HarfBuzz treats them with given font.
1783 // - rects[1] == rects[2]
1784 // - rects[3] == rects[4] == rects[5]
1785 // - rects[6] == rects[7]
1786 }
1787
1788 // The word we select by double clicking should remain selected regardless of
1789 // where we drag the mouse afterwards without releasing the left button.
TEST_F(TextfieldTest,KeepInitiallySelectedWord)1790 TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
1791 InitTextfield();
1792
1793 textfield_->SetText(ASCIIToUTF16("abc def ghi"));
1794
1795 textfield_->SelectRange(gfx::Range(5, 5));
1796 const gfx::Rect middle_cursor = GetCursorBounds();
1797 textfield_->SelectRange(gfx::Range(0, 0));
1798 const gfx::Point beginning = GetCursorBounds().origin();
1799
1800 // Double click, but do not release the left button.
1801 MouseClick(middle_cursor, 0);
1802 const gfx::Point middle(middle_cursor.x(),
1803 middle_cursor.y() + middle_cursor.height() / 2);
1804 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle,
1805 ui::EF_LEFT_MOUSE_BUTTON,
1806 ui::EF_LEFT_MOUSE_BUTTON);
1807 textfield_->OnMousePressed(press_event);
1808 EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange());
1809
1810 // Drag the mouse to the beginning of the textfield.
1811 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning,
1812 ui::EF_LEFT_MOUSE_BUTTON, 0);
1813 textfield_->OnMouseDragged(drag_event);
1814 EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
1815 }
1816
1817 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1818 // flaky: http://crbug.com/396477
TEST_F(TextfieldTest,DISABLED_SelectionClipboard)1819 TEST_F(TextfieldTest, DISABLED_SelectionClipboard) {
1820 InitTextfield();
1821 textfield_->SetText(ASCIIToUTF16("0123"));
1822 gfx::Point point_1(GetCursorPositionX(1), 0);
1823 gfx::Point point_2(GetCursorPositionX(2), 0);
1824 gfx::Point point_3(GetCursorPositionX(3), 0);
1825 gfx::Point point_4(GetCursorPositionX(4), 0);
1826
1827 // Text selected by the mouse should be placed on the selection clipboard.
1828 ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
1829 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1830 textfield_->OnMousePressed(press);
1831 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
1832 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1833 textfield_->OnMouseDragged(drag);
1834 ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
1835 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1836 textfield_->OnMouseReleased(release);
1837 EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
1838 EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1839
1840 // Select-all should update the selection clipboard.
1841 SendKeyEvent(ui::VKEY_A, false, true);
1842 EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
1843 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1844 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1845
1846 // Shift-click selection modifications should update the clipboard.
1847 NonClientMouseClick();
1848 ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
1849 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1850 press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
1851 #if defined(USE_X11)
1852 ui::UpdateX11EventForFlags(&press_2);
1853 #endif
1854 textfield_->OnMousePressed(press_2);
1855 ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
1856 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1857 textfield_->OnMouseReleased(release_2);
1858 EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
1859 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1860 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1861
1862 // Shift-Left/Right should update the selection clipboard.
1863 SendKeyEvent(ui::VKEY_RIGHT, true, false);
1864 EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1865 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1866 SendKeyEvent(ui::VKEY_LEFT, true, false);
1867 EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1868 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1869 SendKeyEvent(ui::VKEY_RIGHT, true, true);
1870 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1871 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1872
1873 // Moving the cursor without a selection should not change the clipboard.
1874 SendKeyEvent(ui::VKEY_LEFT, false, false);
1875 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
1876 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1877 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1878
1879 // Middle clicking should paste at the mouse (not cursor) location.
1880 ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
1881 ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON);
1882 textfield_->OnMousePressed(middle);
1883 EXPECT_STR_EQ("01230123", textfield_->text());
1884 EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
1885 EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1886
1887 // Middle click pasting should adjust trailing cursors.
1888 textfield_->SelectRange(gfx::Range(5, 5));
1889 textfield_->OnMousePressed(middle);
1890 EXPECT_STR_EQ("012301230123", textfield_->text());
1891 EXPECT_EQ(gfx::Range(9, 9), textfield_->GetSelectedRange());
1892
1893 // Middle click pasting should adjust trailing selections.
1894 textfield_->SelectRange(gfx::Range(7, 9));
1895 textfield_->OnMousePressed(middle);
1896 EXPECT_STR_EQ("0123012301230123", textfield_->text());
1897 EXPECT_EQ(gfx::Range(11, 13), textfield_->GetSelectedRange());
1898
1899 // Middle clicking in the selection should clear the clipboard and selection.
1900 textfield_->SelectRange(gfx::Range(2, 6));
1901 textfield_->OnMousePressed(middle);
1902 EXPECT_STR_EQ("0123012301230123", textfield_->text());
1903 EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
1904 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
1905
1906 // Double and triple clicking should update the clipboard contents.
1907 textfield_->SetText(ASCIIToUTF16("ab cd ef"));
1908 gfx::Point word(GetCursorPositionX(4), 0);
1909 ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
1910 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1911 textfield_->OnMousePressed(press_word);
1912 ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
1913 ui::EF_LEFT_MOUSE_BUTTON,
1914 ui::EF_LEFT_MOUSE_BUTTON);
1915 textfield_->OnMouseReleased(release_word);
1916 ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
1917 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
1918 ui::EF_LEFT_MOUSE_BUTTON);
1919 textfield_->OnMousePressed(double_click);
1920 textfield_->OnMouseReleased(release_word);
1921 EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
1922 EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1923 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1924 textfield_->OnMousePressed(press_word);
1925 textfield_->OnMouseReleased(release_word);
1926 EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
1927 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1928 EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
1929
1930 // Selecting a range of text without any user interaction should not change
1931 // the clipboard content.
1932 textfield_->SelectRange(gfx::Range(0, 3));
1933 EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
1934 EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1935 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1936
1937 SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
1938 textfield_->SelectAll(false);
1939 EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
1940 EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
1941 }
1942 #endif
1943
1944 // Touch selection and dragging currently only works for chromeos.
1945 #if defined(OS_CHROMEOS)
TEST_F(TextfieldTest,TouchSelectionAndDraggingTest)1946 TEST_F(TextfieldTest, TouchSelectionAndDraggingTest) {
1947 InitTextfield();
1948 textfield_->SetText(ASCIIToUTF16("hello world"));
1949 EXPECT_FALSE(test_api_->touch_selection_controller());
1950 const int x = GetCursorPositionX(2);
1951 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
1952
1953 // Tapping on the textfield should turn on the TouchSelectionController.
1954 ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
1955 tap_details.set_tap_count(1);
1956 GestureEventForTest tap(x, 0, tap_details);
1957 textfield_->OnGestureEvent(&tap);
1958 EXPECT_TRUE(test_api_->touch_selection_controller());
1959
1960 // Un-focusing the textfield should reset the TouchSelectionController
1961 textfield_->GetFocusManager()->ClearFocus();
1962 EXPECT_FALSE(test_api_->touch_selection_controller());
1963 textfield_->RequestFocus();
1964
1965 // With touch editing enabled, long press should not show context menu.
1966 // Instead, select word and invoke TouchSelectionController.
1967 GestureEventForTest long_press_1(
1968 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
1969 textfield_->OnGestureEvent(&long_press_1);
1970 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1971 EXPECT_TRUE(test_api_->touch_selection_controller());
1972 EXPECT_TRUE(long_press_1.handled());
1973
1974 // With touch drag drop enabled, long pressing in the selected region should
1975 // start a drag and remove TouchSelectionController.
1976 ASSERT_TRUE(switches::IsTouchDragDropEnabled());
1977 GestureEventForTest long_press_2(
1978 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
1979 textfield_->OnGestureEvent(&long_press_2);
1980 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1981 EXPECT_FALSE(test_api_->touch_selection_controller());
1982 EXPECT_FALSE(long_press_2.handled());
1983
1984 // After disabling touch drag drop, long pressing again in the selection
1985 // region should not do anything.
1986 CommandLine::ForCurrentProcess()->AppendSwitch(
1987 switches::kDisableTouchDragDrop);
1988 ASSERT_FALSE(switches::IsTouchDragDropEnabled());
1989 GestureEventForTest long_press_3(
1990 x, 0, ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
1991 textfield_->OnGestureEvent(&long_press_3);
1992 EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
1993 EXPECT_FALSE(test_api_->touch_selection_controller());
1994 EXPECT_FALSE(long_press_3.handled());
1995 }
1996 #endif
1997
TEST_F(TextfieldTest,TouchSelectionInUnfocusableTextfield)1998 TEST_F(TextfieldTest, TouchSelectionInUnfocusableTextfield) {
1999 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
2000
2001 InitTextfield();
2002 textfield_->SetText(ASCIIToUTF16("hello world"));
2003 gfx::Point touch_point(GetCursorPositionX(2), 0);
2004
2005 // Disable textfield and tap on it. Touch text selection should not get
2006 // activated.
2007 textfield_->SetEnabled(false);
2008 Tap(touch_point);
2009 EXPECT_FALSE(test_api_->touch_selection_controller());
2010 textfield_->SetEnabled(true);
2011
2012 // Make textfield unfocusable and tap on it. Touch text selection should not
2013 // get activated.
2014 textfield_->SetFocusable(false);
2015 Tap(touch_point);
2016 EXPECT_FALSE(textfield_->HasFocus());
2017 EXPECT_FALSE(test_api_->touch_selection_controller());
2018 textfield_->SetFocusable(true);
2019 }
2020
2021 // Long_Press gesture in Textfield can initiate a drag and drop now.
TEST_F(TextfieldTest,TestLongPressInitiatesDragDrop)2022 TEST_F(TextfieldTest, TestLongPressInitiatesDragDrop) {
2023 InitTextfield();
2024 textfield_->SetText(ASCIIToUTF16("Hello string world"));
2025
2026 // Ensure the textfield will provide selected text for drag data.
2027 textfield_->SelectRange(gfx::Range(6, 12));
2028 const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
2029
2030 // Enable touch-drag-drop to make long press effective.
2031 CommandLine::ForCurrentProcess()->AppendSwitch(
2032 switches::kEnableTouchDragDrop);
2033
2034 // Create a long press event in the selected region should start a drag.
2035 GestureEventForTest long_press(
2036 kStringPoint.x(),
2037 kStringPoint.y(),
2038 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
2039 textfield_->OnGestureEvent(&long_press);
2040 EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
2041 kStringPoint));
2042 }
2043
TEST_F(TextfieldTest,GetTextfieldBaseline_FontFallbackTest)2044 TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
2045 InitTextfield();
2046 textfield_->SetText(UTF8ToUTF16("abc"));
2047 const int old_baseline = textfield_->GetBaseline();
2048
2049 // Set text which may fall back to a font which has taller baseline than
2050 // the default font.
2051 textfield_->SetText(UTF8ToUTF16("\xE0\xB9\x91"));
2052 const int new_baseline = textfield_->GetBaseline();
2053
2054 // Regardless of the text, the baseline must be the same.
2055 EXPECT_EQ(new_baseline, old_baseline);
2056 }
2057
2058 // Tests that a textfield view can be destroyed from OnKeyEvent() on its
2059 // controller and it does not crash.
TEST_F(TextfieldTest,DestroyingTextfieldFromOnKeyEvent)2060 TEST_F(TextfieldTest, DestroyingTextfieldFromOnKeyEvent) {
2061 InitTextfield();
2062
2063 // The controller assumes ownership of the textfield.
2064 TextfieldDestroyerController controller(textfield_);
2065 EXPECT_TRUE(controller.target());
2066
2067 // Send a key to trigger OnKeyEvent().
2068 SendKeyEvent('X');
2069
2070 EXPECT_FALSE(controller.target());
2071 }
2072
2073 } // namespace views
2074