Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc

Issue 2856093003: Update TextSelection for non-user initiated events (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
32 #include "url/gurl.h" 33 #include "url/gurl.h"
33 34
34 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 35 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
35 #include "ui/base/ime/linux/text_edit_command_auralinux.h" 36 #include "ui/base/ime/linux/text_edit_command_auralinux.h"
36 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" 37 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h"
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 const content::RenderWidgetHostView* const expected_view_; 268 const content::RenderWidgetHostView* const expected_view_;
268 const size_t expected_length_; 269 const size_t expected_length_;
269 270
270 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); 271 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver);
271 }; 272 };
272 273
273 // This class observes all the text selection updates within a WebContents. 274 // This class observes all the text selection updates within a WebContents.
274 class TextSelectionObserver : public TextInputManagerObserverBase { 275 class TextSelectionObserver : public TextInputManagerObserverBase {
275 public: 276 public:
276 explicit TextSelectionObserver(content::WebContents* web_contents) 277 explicit TextSelectionObserver(content::WebContents* web_contents)
277 : TextInputManagerObserverBase(web_contents) { 278 : TextInputManagerObserverBase(web_contents), callback_called_(false) {
nasko 2017/05/04 16:10:24 Has this CL been run through "git cl format"?
Peter Varga 2017/05/04 16:33:45 Yes it has been. Actually the script put this two
278 tester()->SetOnTextSelectionChangedCallback(base::Bind( 279 tester()->SetOnTextSelectionChangedCallback(base::Bind(
279 &TextSelectionObserver::VerifyChange, base::Unretained(this))); 280 &TextSelectionObserver::VerifyChange, base::Unretained(this)));
280 } 281 }
281 282
282 void WaitForSelectedText(const std::string& text) { 283 void WaitForSelectedText(const std::string& text,
283 selected_text_ = text; 284 bool user_initiated = true) {
284 Wait(); 285 expected_text_ = text;
286 expected_user_initiated_ = user_initiated;
287 if (callback_called_ && last_selected_text_ == expected_text_ &&
288 last_user_initiated_ == expected_user_initiated_) {
289 OnSuccess();
290 } else {
291 Wait();
292 }
285 } 293 }
286 294
287 private: 295 private:
288 void VerifyChange() { 296 void VerifyChange() {
289 if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == 297 callback_called_ = true;
290 selected_text_) { 298
299 last_selected_text_ =
300 base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText());
301 EXPECT_TRUE(tester()->GetTextSelectionUserInitiatedForView(
302 tester()->GetUpdatedView(), &last_user_initiated_));
303
304 if (last_selected_text_ == expected_text_ &&
305 last_user_initiated_ == expected_user_initiated_) {
291 OnSuccess(); 306 OnSuccess();
292 } 307 }
293 } 308 }
294 309
295 std::string selected_text_; 310 bool callback_called_;
311
312 std::string last_selected_text_;
313 std::string expected_text_;
314 bool last_user_initiated_;
315 bool expected_user_initiated_;
296 316
297 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); 317 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver);
298 }; 318 };
299 319
300 // This class monitors all the changes in TextInputState and keeps a record of 320 // 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 321 // the active views. There is no waiting and the recording process is
302 // continuous. 322 // continuous.
303 class RecordActiveViewsObserver { 323 class RecordActiveViewsObserver {
304 public: 324 public:
305 explicit RecordActiveViewsObserver(content::WebContents* web_contents) 325 explicit RecordActiveViewsObserver(content::WebContents* web_contents)
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 // Iteratively uses ChildFrameAt(frame, i) to get the i-th child frame 433 // 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 434 // inside frame. For example, for 'a(b(c, d(e)))', [0] returns b, and
415 // [0, 1, 0] returns e; 435 // [0, 1, 0] returns e;
416 content::RenderFrameHost* GetFrame(const IndexVector& indices) { 436 content::RenderFrameHost* GetFrame(const IndexVector& indices) {
417 content::RenderFrameHost* current = active_contents()->GetMainFrame(); 437 content::RenderFrameHost* current = active_contents()->GetMainFrame();
418 for (size_t index : indices) 438 for (size_t index : indices)
419 current = ChildFrameAt(current, index); 439 current = ChildFrameAt(current, index);
420 return current; 440 return current;
421 } 441 }
422 442
443 // Simulates a click on the middle of the first DOM element
444 // with the given |selector|.
445 void ClickFirstElementWithSelector(const std::string& selector) {
446 int x;
447 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
448 active_contents(),
449 "var bounds = document.querySelector('" + selector +
450 "').getBoundingClientRect();"
451 "domAutomationController.send("
452 " Math.floor(bounds.left + bounds.width / 2));",
453 &x));
454 int y;
455 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
456 active_contents(),
457 "var bounds = document.querySelector('" + selector +
458 "').getBoundingClientRect();"
459 "domAutomationController.send("
460 " Math.floor(bounds.top + bounds.height / 2));",
461 &y));
462 content::SimulateMouseClickAt(active_contents(), 0,
463 blink::WebMouseEvent::Button::kLeft,
464 gfx::Point(x, y));
465 }
466
423 private: 467 private:
424 DISALLOW_COPY_AND_ASSIGN(SitePerProcessTextInputManagerTest); 468 DISALLOW_COPY_AND_ASSIGN(SitePerProcessTextInputManagerTest);
425 }; 469 };
426 470
427 // The following test loads a page with multiple nested <iframe> elements which 471 // 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 472 // 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 473 // 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 474 // 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 475 // TextInputState.value reflects that of the focused input, i.e., the
432 // TextInputManager is correctly tracking TextInputState across frames. 476 // TextInputManager is correctly tracking TextInputState across frames.
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 }; 1017 };
974 1018
975 for (auto* frame : frames) { 1019 for (auto* frame : frames) {
976 focus_frame_and_input(frame); 1020 focus_frame_and_input(frame);
977 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); 1021 EXPECT_TRUE(active_contents()->IsFocusedElementEditable());
978 active_contents()->ClearFocusedElement(); 1022 active_contents()->ClearFocusedElement();
979 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); 1023 EXPECT_FALSE(active_contents()->IsFocusedElementEditable());
980 } 1024 }
981 } 1025 }
982 1026
1027 // This test verifies that the TextInputManager notifies about a
1028 // text selection change event for both user and non-user (eg. JavaScript)
1029 // initiated cases. It is also tested whether TextSelection::user_initiated
1030 // is properly set. The content of the selection clipboard is also tested on
1031 // platforms where it is supported.
1032 // See: https://crbug.com/671986
1033 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
1034 NonUserInitiatedTextSelection) {
1035 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1036 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1037 EXPECT_TRUE(!!clipboard);
1038 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION);
1039 #endif
1040
1041 CreateIframePage("a()");
EhsanK 2017/05/04 00:16:31 I think the test belongs to somewhere else but I l
Peter Varga 2017/05/04 07:30:39 I agree with that this file is probably not the be
nasko 2017/05/04 16:10:24 Why not extend the test to cover actual OOPIFs? Th
Peter Varga 2017/05/04 16:33:45 Because I'm not sure how to test OOPIF. Any hint/s
EhsanK 2017/05/08 16:56:25 Some suggestions: You could start by reusing some
Peter Varga 2017/05/09 06:42:29 Thank you for the suggestions. I did something sim
EhsanK 2017/05/09 15:16:16 Acknowledged.
1042
1043 content::RenderFrameHost* frame = GetFrame(IndexVector{});
1044 AddInputFieldToFrame(frame, "text", "Chromium", true);
1045
1046 // Trigger text selection from JavaScript
1047 {
1048 TextSelectionObserver observer(active_contents());
1049 EXPECT_TRUE(
1050 ExecuteScript(frame, "document.querySelector('input').select();"));
1051 observer.WaitForSelectedText("Chromium", false);
1052 }
1053
1054 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1055 // Non-user initiated text selection should not update the selection
1056 // clipboard. See: https://crbug.com/12392
1057 base::string16 result_text;
1058 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1059 EXPECT_TRUE(result_text.empty());
1060 #endif
1061
1062 // Clear text selecton from JavaScript
1063 {
1064 TextSelectionObserver observer(active_contents());
1065 EXPECT_TRUE(ExecuteScript(frame, "document.getSelection().empty();"));
1066 observer.WaitForSelectedText("", false);
1067 }
1068
1069 // Trigger text selection by user input
1070 {
1071 TextSelectionObserver observer(active_contents());
1072 // Click on element to have keyboard focus
1073 ASSERT_NO_FATAL_FAILURE(ClickFirstElementWithSelector("input"));
1074 // Press ctrl+a to select text in the input field
1075 SimulateKeyPress(active_contents(), ui::DomKey::FromCharacter('A'),
1076 ui::DomCode::US_A, ui::VKEY_A, true, false, false, false);
1077 observer.WaitForSelectedText("Chromium", true);
1078 }
1079
1080 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1081 // User initiated text selection should update the selection clipboard
1082 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1083 EXPECT_EQ(base::ASCIIToUTF16("Chromium"), result_text);
1084 #endif
1085
1086 // Clear text selection by user input
1087 {
1088 TextSelectionObserver observer(active_contents());
1089 // Click on element to clear text selection
1090 ASSERT_NO_FATAL_FAILURE(ClickFirstElementWithSelector("input"));
1091 observer.WaitForSelectedText("", true);
1092 }
1093
1094 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1095 // Empty selection should not clear the selection clipboard
1096 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1097 EXPECT_EQ(base::ASCIIToUTF16("Chromium"), result_text);
1098 #endif
1099 }
1100
983 // TODO(ekaramad): The following tests are specifically written for Aura and are 1101 // TODO(ekaramad): The following tests are specifically written for Aura and are
984 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus 1102 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus
985 // (crbug.com/602723). 1103 // (crbug.com/602723).
986 #if defined(USE_AURA) 1104 #if defined(USE_AURA)
987 // ----------------------------------------------------------------------------- 1105 // -----------------------------------------------------------------------------
988 // Input Method Observer Tests 1106 // Input Method Observer Tests
989 // 1107 //
990 // The following tests will make use of the InputMethodObserver to verify that 1108 // 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. 1109 // OOPIF pages interact properly with the InputMethod through the tab's view.
992 1110
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 1485
1368 // Closing this WebContents while we still hold on to our TestBrowserClient. 1486 // Closing this WebContents while we still hold on to our TestBrowserClient.
1369 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( 1487 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(
1370 1, TabStripModel::CLOSE_USER_GESTURE)); 1488 1, TabStripModel::CLOSE_USER_GESTURE));
1371 1489
1372 // For the cleanup of the original WebContents in tab index 0. 1490 // For the cleanup of the original WebContents in tab index 0.
1373 content::SetBrowserClientForTesting(old_browser_client); 1491 content::SetBrowserClientForTesting(old_browser_client);
1374 } 1492 }
1375 #endif // defined(MAC_OSX) 1493 #endif // defined(MAC_OSX)
1376 #endif // !defined(OS_ANDROID) 1494 #endif // !defined(OS_ANDROID)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698