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