Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "chrome/browser/chrome_content_browser_client.h" | 9 #include "chrome/browser/chrome_content_browser_client.h" |
| 10 #include "chrome/browser/ui/browser.h" | 10 #include "chrome/browser/ui/browser.h" |
| 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 12 #include "chrome/test/base/in_process_browser_test.h" | 12 #include "chrome/test/base/in_process_browser_test.h" |
| 13 #include "chrome/test/base/interactive_test_utils.h" | 13 #include "chrome/test/base/interactive_test_utils.h" |
| 14 #include "chrome/test/base/ui_test_utils.h" | 14 #include "chrome/test/base/ui_test_utils.h" |
| 15 #include "content/public/browser/content_browser_client.h" | 15 #include "content/public/browser/content_browser_client.h" |
| 16 #include "content/public/browser/render_frame_host.h" | 16 #include "content/public/browser/render_frame_host.h" |
| 17 #include "content/public/browser/render_process_host.h" | 17 #include "content/public/browser/render_process_host.h" |
| 18 #include "content/public/browser/render_widget_host_view.h" | 18 #include "content/public/browser/render_widget_host_view.h" |
| 19 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" |
| 20 #include "content/public/common/content_client.h" | 20 #include "content/public/common/content_client.h" |
| 21 #include "content/public/test/browser_test_utils.h" | 21 #include "content/public/test/browser_test_utils.h" |
| 22 #include "content/public/test/content_browser_test_utils.h" | 22 #include "content/public/test/content_browser_test_utils.h" |
| 23 #include "content/public/test/test_utils.h" | 23 #include "content/public/test/test_utils.h" |
| 24 #include "content/public/test/text_input_test_utils.h" | 24 #include "content/public/test/text_input_test_utils.h" |
| 25 #include "net/dns/mock_host_resolver.h" | 25 #include "net/dns/mock_host_resolver.h" |
| 26 #include "net/test/embedded_test_server/embedded_test_server.h" | 26 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 27 #include "ui/base/clipboard/clipboard.h" | |
| 27 #include "ui/base/ime/composition_underline.h" | 28 #include "ui/base/ime/composition_underline.h" |
| 28 #include "ui/base/ime/text_edit_commands.h" | 29 #include "ui/base/ime/text_edit_commands.h" |
| 29 #include "ui/base/ime/text_input_client.h" | 30 #include "ui/base/ime/text_input_client.h" |
| 30 #include "ui/base/ime/text_input_mode.h" | 31 #include "ui/base/ime/text_input_mode.h" |
| 31 #include "ui/base/ime/text_input_type.h" | 32 #include "ui/base/ime/text_input_type.h" |
| 33 #include "ui/base/test/ui_controls.h" | |
| 32 #include "url/gurl.h" | 34 #include "url/gurl.h" |
| 33 | 35 |
| 34 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 36 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 35 #include "ui/base/ime/linux/text_edit_command_auralinux.h" | 37 #include "ui/base/ime/linux/text_edit_command_auralinux.h" |
| 36 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" | 38 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" |
| 37 #endif | 39 #endif |
| 38 | 40 |
| 39 /////////////////////////////////////////////////////////////////////////////// | 41 /////////////////////////////////////////////////////////////////////////////// |
| 40 // TextInputManager and IME Tests | 42 // TextInputManager and IME Tests |
| 41 // | 43 // |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 const content::RenderWidgetHostView* const expected_view_; | 269 const content::RenderWidgetHostView* const expected_view_; |
| 268 const size_t expected_length_; | 270 const size_t expected_length_; |
| 269 | 271 |
| 270 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); | 272 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); |
| 271 }; | 273 }; |
| 272 | 274 |
| 273 // This class observes all the text selection updates within a WebContents. | 275 // This class observes all the text selection updates within a WebContents. |
| 274 class TextSelectionObserver : public TextInputManagerObserverBase { | 276 class TextSelectionObserver : public TextInputManagerObserverBase { |
| 275 public: | 277 public: |
| 276 explicit TextSelectionObserver(content::WebContents* web_contents) | 278 explicit TextSelectionObserver(content::WebContents* web_contents) |
| 277 : TextInputManagerObserverBase(web_contents) { | 279 : TextInputManagerObserverBase(web_contents), callback_called_(false) { |
| 278 tester()->SetOnTextSelectionChangedCallback(base::Bind( | 280 tester()->SetOnTextSelectionChangedCallback(base::Bind( |
| 279 &TextSelectionObserver::VerifyChange, base::Unretained(this))); | 281 &TextSelectionObserver::VerifyChange, base::Unretained(this))); |
| 280 } | 282 } |
| 281 | 283 |
| 282 void WaitForSelectedText(const std::string& text) { | 284 void WaitForSelectedText(const std::string& text, |
| 283 selected_text_ = text; | 285 bool user_initiated = true) { |
| 284 Wait(); | 286 expected_text_ = text; |
| 287 expected_user_initiated_ = user_initiated; | |
| 288 if (callback_called_ && last_selected_text_ == expected_text_ && | |
| 289 last_user_initiated_ == expected_user_initiated_) { | |
| 290 OnSuccess(); | |
| 291 } else { | |
| 292 Wait(); | |
| 293 } | |
| 285 } | 294 } |
| 286 | 295 |
| 287 private: | 296 private: |
| 288 void VerifyChange() { | 297 void VerifyChange() { |
| 289 if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == | 298 callback_called_ = true; |
| 290 selected_text_) { | 299 |
| 300 last_selected_text_ = | |
| 301 base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()); | |
| 302 EXPECT_TRUE(tester()->GetTextSelectionUserInitiatedForView( | |
| 303 tester()->GetUpdatedView(), &last_user_initiated_)); | |
| 304 | |
| 305 if (last_selected_text_ == expected_text_ && | |
| 306 last_user_initiated_ == expected_user_initiated_) { | |
| 291 OnSuccess(); | 307 OnSuccess(); |
| 292 } | 308 } |
| 293 } | 309 } |
| 294 | 310 |
| 295 std::string selected_text_; | 311 bool callback_called_; |
| 312 | |
| 313 std::string last_selected_text_; | |
| 314 std::string expected_text_; | |
| 315 bool last_user_initiated_; | |
| 316 bool expected_user_initiated_; | |
| 296 | 317 |
| 297 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); | 318 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); |
| 298 }; | 319 }; |
| 299 | 320 |
| 300 // This class monitors all the changes in TextInputState and keeps a record of | 321 // This class monitors all the changes in TextInputState and keeps a record of |
| 301 // the active views. There is no waiting and the recording process is | 322 // the active views. There is no waiting and the recording process is |
| 302 // continuous. | 323 // continuous. |
| 303 class RecordActiveViewsObserver { | 324 class RecordActiveViewsObserver { |
| 304 public: | 325 public: |
| 305 explicit RecordActiveViewsObserver(content::WebContents* web_contents) | 326 explicit RecordActiveViewsObserver(content::WebContents* web_contents) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 // Iteratively uses ChildFrameAt(frame, i) to get the i-th child frame | 434 // Iteratively uses ChildFrameAt(frame, i) to get the i-th child frame |
| 414 // inside frame. For example, for 'a(b(c, d(e)))', [0] returns b, and | 435 // inside frame. For example, for 'a(b(c, d(e)))', [0] returns b, and |
| 415 // [0, 1, 0] returns e; | 436 // [0, 1, 0] returns e; |
| 416 content::RenderFrameHost* GetFrame(const IndexVector& indices) { | 437 content::RenderFrameHost* GetFrame(const IndexVector& indices) { |
| 417 content::RenderFrameHost* current = active_contents()->GetMainFrame(); | 438 content::RenderFrameHost* current = active_contents()->GetMainFrame(); |
| 418 for (size_t index : indices) | 439 for (size_t index : indices) |
| 419 current = ChildFrameAt(current, index); | 440 current = ChildFrameAt(current, index); |
| 420 return current; | 441 return current; |
| 421 } | 442 } |
| 422 | 443 |
| 444 // Simulates a click on the middle of the first DOM element | |
| 445 // with the given |selector| in the given frame |rfh|. The |frame_index| | |
| 446 // parameter is used to find the child frame in the main frame and | |
| 447 // use its offset to calculate the click position. | |
| 448 void ClickFirstElementWithSelector(content::RenderFrameHost* rfh, | |
| 449 int frame_index, | |
| 450 const std::string& selector) { | |
| 451 int frame_x = 0; | |
| 452 int frame_y = 0; | |
| 453 | |
| 454 if (rfh != active_contents()->GetMainFrame()) { | |
| 455 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( | |
| 456 active_contents()->GetMainFrame(), | |
| 457 "var frames = document.querySelectorAll('iframe');" | |
| 458 "var frame = frames[" + | |
| 459 std::to_string(frame_index) + | |
| 460 "];" | |
| 461 "domAutomationController.send(Math.floor(frame.offsetLeft));", | |
| 462 &frame_x)); | |
| 463 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( | |
| 464 active_contents()->GetMainFrame(), | |
| 465 "var frames = document.querySelectorAll('iframe');" | |
| 466 "var frame = frames[" + | |
| 467 std::to_string(frame_index) + | |
| 468 "];" | |
| 469 "domAutomationController.send(Math.floor(frame.offsetTop));", | |
| 470 &frame_y)); | |
| 471 } | |
| 472 | |
| 473 int x; | |
| 474 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( | |
| 475 rfh, | |
| 476 "var bounds = document.querySelector('" + selector + | |
| 477 "').getBoundingClientRect();" | |
| 478 "domAutomationController.send(" | |
| 479 " Math.floor(bounds.left + bounds.width / 2));", | |
| 480 &x)); | |
| 481 int y; | |
| 482 ASSERT_TRUE(content::ExecuteScriptAndExtractInt( | |
| 483 rfh, | |
| 484 "var bounds = document.querySelector('" + selector + | |
| 485 "').getBoundingClientRect();" | |
| 486 "domAutomationController.send(" | |
| 487 " Math.floor(bounds.top + bounds.height / 2));", | |
| 488 &y)); | |
| 489 | |
| 490 auto content_bounds = active_contents()->GetContainerBounds(); | |
| 491 ui_controls::SendMouseMove(x + frame_x + content_bounds.x(), | |
| 492 y + frame_y + content_bounds.y()); | |
| 493 ui_controls::SendMouseClick(ui_controls::LEFT); | |
| 494 } | |
| 495 | |
| 423 private: | 496 private: |
| 424 DISALLOW_COPY_AND_ASSIGN(SitePerProcessTextInputManagerTest); | 497 DISALLOW_COPY_AND_ASSIGN(SitePerProcessTextInputManagerTest); |
| 425 }; | 498 }; |
| 426 | 499 |
| 427 // The following test loads a page with multiple nested <iframe> elements which | 500 // The following test loads a page with multiple nested <iframe> elements which |
| 428 // are in or out of process with the main frame. Then an <input> field with | 501 // are in or out of process with the main frame. Then an <input> field with |
| 429 // unique value is added to every single frame on the frame tree. The test then | 502 // unique value is added to every single frame on the frame tree. The test then |
| 430 // creates a sequence of tab presses and verifies that after each key press, the | 503 // creates a sequence of tab presses and verifies that after each key press, the |
| 431 // TextInputState.value reflects that of the focused input, i.e., the | 504 // TextInputState.value reflects that of the focused input, i.e., the |
| 432 // TextInputManager is correctly tracking TextInputState across frames. | 505 // TextInputManager is correctly tracking TextInputState across frames. |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 973 }; | 1046 }; |
| 974 | 1047 |
| 975 for (auto* frame : frames) { | 1048 for (auto* frame : frames) { |
| 976 focus_frame_and_input(frame); | 1049 focus_frame_and_input(frame); |
| 977 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); | 1050 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); |
| 978 active_contents()->ClearFocusedElement(); | 1051 active_contents()->ClearFocusedElement(); |
| 979 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); | 1052 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); |
| 980 } | 1053 } |
| 981 } | 1054 } |
| 982 | 1055 |
| 1056 // This test verifies that the TextInputManager notifies about a | |
| 1057 // text selection change event for both user and non-user (eg. JavaScript) | |
| 1058 // initiated cases. It is also tested whether TextSelection::user_initiated | |
| 1059 // is properly set. The content of the selection clipboard is also tested on | |
| 1060 // platforms where it is supported. | |
| 1061 // See: https://crbug.com/671986 | |
| 1062 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, | |
| 1063 NonUserInitiatedTextSelection) { | |
| 1064 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1065 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); | |
| 1066 EXPECT_TRUE(!!clipboard); | |
|
Lei Zhang
2017/05/10 21:06:03
ASSERT_TRUE() because if this fails, the test exec
Peter Varga
2017/05/10 21:12:36
I copied this from another clipboard test. I will
| |
| 1067 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION); | |
| 1068 #endif | |
| 1069 | |
| 1070 CreateIframePage("a(b, c)"); | |
| 1071 std::vector<std::string> values{"node_a", "node_b", "node_c"}; | |
| 1072 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}), | |
| 1073 GetFrame(IndexVector{0}), | |
| 1074 GetFrame(IndexVector{1})}; | |
| 1075 | |
| 1076 for (size_t i = 0; i < frames.size(); ++i) | |
| 1077 AddInputFieldToFrame(frames[i], "text", values[i], true); | |
| 1078 | |
| 1079 // Test text selection from JavaScript across frames (non-user initiated). | |
| 1080 for (size_t i = 0; i < frames.size(); ++i) { | |
| 1081 // Trigger text selection. | |
| 1082 TextSelectionObserver trigger_observer(active_contents()); | |
| 1083 EXPECT_TRUE( | |
| 1084 ExecuteScript(frames[i], "document.querySelector('input').select();")); | |
| 1085 trigger_observer.WaitForSelectedText(values[i], false); | |
| 1086 | |
| 1087 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1088 // Non-user initiated text selection should not update the selection | |
| 1089 // clipboard. See: https://crbug.com/12392 | |
| 1090 base::string16 result_text; | |
| 1091 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text); | |
| 1092 EXPECT_TRUE(result_text.empty()); | |
| 1093 #endif | |
| 1094 | |
| 1095 // Clear text selection. | |
| 1096 TextSelectionObserver clear_observer(active_contents()); | |
| 1097 EXPECT_TRUE(ExecuteScript(frames[i], "document.getSelection().empty();")); | |
| 1098 clear_observer.WaitForSelectedText("", false); | |
| 1099 } | |
| 1100 | |
| 1101 // Test text selection by user input across frames (user initiated). | |
| 1102 for (size_t i = 0; i < frames.size(); ++i) { | |
| 1103 // Click on element to have keyboard focus. | |
| 1104 TextInputManagerChangeObserver input_observer(active_contents()); | |
| 1105 // Index of the main frame is 0. Thus align child frame index to it (i-1). | |
| 1106 ASSERT_NO_FATAL_FAILURE( | |
| 1107 ClickFirstElementWithSelector(frames[i], i - 1, "input")); | |
| 1108 input_observer.Wait(); | |
| 1109 | |
| 1110 // Press ctrl+a to select text in the input field. | |
| 1111 TextSelectionObserver trigger_observer(active_contents()); | |
| 1112 SimulateKeyPress(active_contents(), ui::DomKey::FromCharacter('A'), | |
| 1113 ui::DomCode::US_A, ui::VKEY_A, true, false, false, false); | |
| 1114 trigger_observer.WaitForSelectedText(values[i], true); | |
| 1115 | |
| 1116 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1117 // User initiated text selection should update the selection clipboard. | |
| 1118 base::string16 result_text; | |
| 1119 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text); | |
| 1120 EXPECT_EQ(base::ASCIIToUTF16(values[i]), result_text); | |
| 1121 #endif | |
| 1122 | |
| 1123 // Click on element to clear text selection. | |
| 1124 TextSelectionObserver clear_observer(active_contents()); | |
| 1125 // Index of the main frame is 0. Thus align child frame index to it (i-1). | |
| 1126 ASSERT_NO_FATAL_FAILURE( | |
| 1127 ClickFirstElementWithSelector(frames[i], i - 1, "input")); | |
| 1128 clear_observer.WaitForSelectedText("", true); | |
| 1129 } | |
| 1130 } | |
| 1131 | |
| 983 // TODO(ekaramad): The following tests are specifically written for Aura and are | 1132 // TODO(ekaramad): The following tests are specifically written for Aura and are |
| 984 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus | 1133 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus |
| 985 // (crbug.com/602723). | 1134 // (crbug.com/602723). |
| 986 #if defined(USE_AURA) | 1135 #if defined(USE_AURA) |
| 987 // ----------------------------------------------------------------------------- | 1136 // ----------------------------------------------------------------------------- |
| 988 // Input Method Observer Tests | 1137 // Input Method Observer Tests |
| 989 // | 1138 // |
| 990 // The following tests will make use of the InputMethodObserver to verify that | 1139 // The following tests will make use of the InputMethodObserver to verify that |
| 991 // OOPIF pages interact properly with the InputMethod through the tab's view. | 1140 // OOPIF pages interact properly with the InputMethod through the tab's view. |
| 992 | 1141 |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1367 | 1516 |
| 1368 // Closing this WebContents while we still hold on to our TestBrowserClient. | 1517 // Closing this WebContents while we still hold on to our TestBrowserClient. |
| 1369 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( | 1518 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( |
| 1370 1, TabStripModel::CLOSE_USER_GESTURE)); | 1519 1, TabStripModel::CLOSE_USER_GESTURE)); |
| 1371 | 1520 |
| 1372 // For the cleanup of the original WebContents in tab index 0. | 1521 // For the cleanup of the original WebContents in tab index 0. |
| 1373 content::SetBrowserClientForTesting(old_browser_client); | 1522 content::SetBrowserClientForTesting(old_browser_client); |
| 1374 } | 1523 } |
| 1375 #endif // defined(MAC_OSX) | 1524 #endif // defined(MAC_OSX) |
| 1376 #endif // !defined(OS_ANDROID) | 1525 #endif // !defined(OS_ANDROID) |
| OLD | NEW |