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

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: Update TextSelection for non-user initiated events 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
« no previous file with comments | « AUTHORS ('k') | content/browser/frame_host/render_frame_host_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 tester()->GetTextInputType(&type) ? type : ui::TEXT_INPUT_TYPE_NONE; 136 tester()->GetTextInputType(&type) ? type : ui::TEXT_INPUT_TYPE_NONE;
136 if (expected_type_ == type) 137 if (expected_type_ == type)
137 OnSuccess(); 138 OnSuccess();
138 } 139 }
139 140
140 const ui::TextInputType expected_type_; 141 const ui::TextInputType expected_type_;
141 142
142 DISALLOW_COPY_AND_ASSIGN(TextInputManagerTypeObserver); 143 DISALLOW_COPY_AND_ASSIGN(TextInputManagerTypeObserver);
143 }; 144 };
144 145
145 // This class observes TextInputManager for the first change in TextInputState.
146 class TextInputManagerChangeObserver : public TextInputManagerObserverBase {
147 public:
148 explicit TextInputManagerChangeObserver(content::WebContents* web_contents)
149 : TextInputManagerObserverBase(web_contents) {
150 tester()->SetUpdateTextInputStateCalledCallback(base::Bind(
151 &TextInputManagerChangeObserver::VerifyChange, base::Unretained(this)));
152 }
153
154 private:
155 void VerifyChange() {
156 if (tester()->IsTextInputStateChanged())
157 OnSuccess();
158 }
159
160 DISALLOW_COPY_AND_ASSIGN(TextInputManagerChangeObserver);
161 };
162
163 // This class observes |TextInputState.type| for a specific RWHV. 146 // This class observes |TextInputState.type| for a specific RWHV.
164 class ViewTextInputTypeObserver : public TextInputManagerObserverBase { 147 class ViewTextInputTypeObserver : public TextInputManagerObserverBase {
165 public: 148 public:
166 explicit ViewTextInputTypeObserver(content::WebContents* web_contents, 149 explicit ViewTextInputTypeObserver(content::WebContents* web_contents,
167 content::RenderWidgetHostView* rwhv, 150 content::RenderWidgetHostView* rwhv,
168 ui::TextInputType expected_type) 151 ui::TextInputType expected_type)
169 : TextInputManagerObserverBase(web_contents), 152 : TextInputManagerObserverBase(web_contents),
170 web_contents_(web_contents), 153 web_contents_(web_contents),
171 view_(rwhv), 154 view_(rwhv),
172 expected_type_(expected_type) { 155 expected_type_(expected_type) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 255
273 // This class observes all the text selection updates within a WebContents. 256 // This class observes all the text selection updates within a WebContents.
274 class TextSelectionObserver : public TextInputManagerObserverBase { 257 class TextSelectionObserver : public TextInputManagerObserverBase {
275 public: 258 public:
276 explicit TextSelectionObserver(content::WebContents* web_contents) 259 explicit TextSelectionObserver(content::WebContents* web_contents)
277 : TextInputManagerObserverBase(web_contents) { 260 : TextInputManagerObserverBase(web_contents) {
278 tester()->SetOnTextSelectionChangedCallback(base::Bind( 261 tester()->SetOnTextSelectionChangedCallback(base::Bind(
279 &TextSelectionObserver::VerifyChange, base::Unretained(this))); 262 &TextSelectionObserver::VerifyChange, base::Unretained(this)));
280 } 263 }
281 264
282 void WaitForSelectedText(const std::string& text) { 265 void WaitForSelectedText(const std::string& text,
283 selected_text_ = text; 266 bool user_initiated = true) {
284 Wait(); 267 expected_text_ = text;
268 expected_user_initiated_ = user_initiated;
269 if (last_selected_text_.has_value() &&
270 last_selected_text_ == expected_text_ &&
271 last_user_initiated_ == expected_user_initiated_) {
272 OnSuccess();
273 } else {
274 Wait();
275 }
285 } 276 }
286 277
287 private: 278 private:
288 void VerifyChange() { 279 void VerifyChange() {
289 if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == 280 last_selected_text_ =
290 selected_text_) { 281 base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText());
282 EXPECT_TRUE(tester()->GetTextSelectionUserInitiatedForView(
283 tester()->GetUpdatedView(), &last_user_initiated_));
284
285 // Check whether the expected values are already set.
286 if (!expected_text_.has_value())
287 return;
288
289 if (last_selected_text_ == expected_text_ &&
290 last_user_initiated_ == expected_user_initiated_) {
291 OnSuccess(); 291 OnSuccess();
292 } 292 }
293 } 293 }
294 294
295 std::string selected_text_; 295 // These optional properties are also used to verify that the last and
296 // expected properties are set.
297 base::Optional<std::string> last_selected_text_;
298 base::Optional<std::string> expected_text_;
299
300 bool last_user_initiated_;
301 bool expected_user_initiated_;
296 302
297 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); 303 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver);
298 }; 304 };
299 305
300 // This class monitors all the changes in TextInputState and keeps a record of 306 // 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 307 // the active views. There is no waiting and the recording process is
302 // continuous. 308 // continuous.
303 class RecordActiveViewsObserver { 309 class RecordActiveViewsObserver {
304 public: 310 public:
305 explicit RecordActiveViewsObserver(content::WebContents* web_contents) 311 explicit RecordActiveViewsObserver(content::WebContents* web_contents)
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 }; 979 };
974 980
975 for (auto* frame : frames) { 981 for (auto* frame : frames) {
976 focus_frame_and_input(frame); 982 focus_frame_and_input(frame);
977 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); 983 EXPECT_TRUE(active_contents()->IsFocusedElementEditable());
978 active_contents()->ClearFocusedElement(); 984 active_contents()->ClearFocusedElement();
979 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); 985 EXPECT_FALSE(active_contents()->IsFocusedElementEditable());
980 } 986 }
981 } 987 }
982 988
989 // The following tests verify that the TextInputManager notifies about a
990 // text selection change event, the corresponding |user_initiated| property
991 // of TextSelection is valid, and the selection clipboard is updated
992 // according to the source of the event.
993 // See: https://crbug.com/671986
994
995 // Test text selection change event for non-user initiated cases
996 // (eg. JavaScript). Non-user initiated events should not update the selection
997 // clipboard.
998 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
999 NonUserInitiatedTextSelection) {
1000 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1001 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1002 ASSERT_TRUE(clipboard);
1003 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION);
1004 #endif
1005
1006 CreateIframePage("a(b, c)");
1007 std::vector<std::string> values{"node_a", "node_b", "node_c"};
1008 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}),
1009 GetFrame(IndexVector{0}),
1010 GetFrame(IndexVector{1})};
1011
1012 for (size_t i = 0; i < frames.size(); ++i)
1013 AddInputFieldToFrame(frames[i], "text", values[i], true);
1014
1015 // Test text selection from JavaScript across frames (non-user initiated).
1016 for (size_t i = 0; i < frames.size(); ++i) {
1017 // Trigger text selection.
1018 TextSelectionObserver trigger_observer(active_contents());
1019 EXPECT_TRUE(
1020 ExecuteScript(frames[i], "document.querySelector('input').select();"));
1021 trigger_observer.WaitForSelectedText(values[i], false);
1022
1023 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1024 // Non-user initiated text selection should not update the selection
1025 // clipboard. See: https://crbug.com/12392
1026 base::string16 result_text;
1027 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1028 EXPECT_TRUE(result_text.empty());
1029 #endif
1030
1031 // Clear text selection.
1032 TextSelectionObserver clear_observer(active_contents());
1033 EXPECT_TRUE(ExecuteScript(frames[i], "document.getSelection().empty();"));
1034 clear_observer.WaitForSelectedText("", false);
1035 }
1036 }
1037
1038 // Test text selection change event for user initiated cases (eg. key press)
1039 // User initiated events should update the selection clipboard where it is
1040 // supported.
1041 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
1042 UserInitiatedTextSelection) {
1043 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1044 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1045 ASSERT_TRUE(clipboard);
1046 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION);
1047 #endif
1048
1049 CreateIframePage("a(b, c)");
1050 std::vector<std::string> values{"node_a", "node_b", "node_c"};
1051 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}),
1052 GetFrame(IndexVector{0}),
1053 GetFrame(IndexVector{1})};
1054
1055 for (size_t i = 0; i < frames.size(); ++i)
1056 AddInputFieldToFrame(frames[i], "text", values[i], true);
1057
1058 // Test text selection by user input across frames (user initiated).
1059 for (size_t i = 0; i < frames.size(); ++i) {
1060 // Focus on input element.
1061 std::string result;
1062 std::string script =
1063 "function getInputField() {"
1064 " return document.querySelector('input');"
1065 "}"
1066 "function onInputFocus(e) {"
1067 " domAutomationController.setAutomationId(0);"
1068 " domAutomationController.send(getInputField().value);"
1069 "}"
1070 "getInputField().addEventListener('focus', onInputFocus);";
1071 EXPECT_TRUE(ExecuteScript(frames[i], script));
1072 EXPECT_TRUE(ExecuteScriptAndExtractString(
1073 frames[i], "window.focus(); document.querySelector('input').focus();",
1074 &result));
1075 EXPECT_EQ(values[i], result);
1076 EXPECT_EQ(frames[i], active_contents()->GetFocusedFrame());
1077
1078 // Press ctrl+a to select text in the input field.
1079 TextSelectionObserver trigger_observer(active_contents());
1080 #if !defined(OS_MACOSX)
1081 SimulateKeyPress(active_contents(), ui::DomKey::FromCharacter('A'),
1082 ui::DomCode::US_A, ui::VKEY_A, true, false, false, false);
1083 #else
1084 // On macOS the select all shortcut (Cmd+A) is handled by the browser via
1085 // keyboard accelerator. Thus we can't simulate key press on WebContents.
1086 // As a workaround, call the SelectAll directly as the shortcut would do.
1087 active_contents()->SelectAll();
1088 #endif
1089 trigger_observer.WaitForSelectedText(values[i], true);
1090
1091 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1092 // User initiated text selection should update the selection clipboard.
1093 base::string16 result_text;
1094 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1095 EXPECT_EQ(base::ASCIIToUTF16(values[i]), result_text);
1096 #endif
1097
1098 // Press down key to clear text selection.
1099 TextSelectionObserver clear_observer(active_contents());
1100 SimulateKeyPress(active_contents(), ui::DomKey::ARROW_DOWN,
1101 ui::DomCode::ARROW_DOWN, ui::VKEY_DOWN, false, false,
1102 false, false);
1103 clear_observer.WaitForSelectedText("", true);
1104 }
1105 }
1106
983 // TODO(ekaramad): The following tests are specifically written for Aura and are 1107 // TODO(ekaramad): The following tests are specifically written for Aura and are
984 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus 1108 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus
985 // (crbug.com/602723). 1109 // (crbug.com/602723).
986 #if defined(USE_AURA) 1110 #if defined(USE_AURA)
987 // ----------------------------------------------------------------------------- 1111 // -----------------------------------------------------------------------------
988 // Input Method Observer Tests 1112 // Input Method Observer Tests
989 // 1113 //
990 // The following tests will make use of the InputMethodObserver to verify that 1114 // 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. 1115 // OOPIF pages interact properly with the InputMethod through the tab's view.
992 1116
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 1491
1368 // Closing this WebContents while we still hold on to our TestBrowserClient. 1492 // Closing this WebContents while we still hold on to our TestBrowserClient.
1369 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( 1493 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(
1370 1, TabStripModel::CLOSE_USER_GESTURE)); 1494 1, TabStripModel::CLOSE_USER_GESTURE));
1371 1495
1372 // For the cleanup of the original WebContents in tab index 0. 1496 // For the cleanup of the original WebContents in tab index 0.
1373 content::SetBrowserClientForTesting(old_browser_client); 1497 content::SetBrowserClientForTesting(old_browser_client);
1374 } 1498 }
1375 #endif // defined(MAC_OSX) 1499 #endif // defined(MAC_OSX)
1376 #endif // !defined(OS_ANDROID) 1500 #endif // !defined(OS_ANDROID)
OLDNEW
« no previous file with comments | « AUTHORS ('k') | content/browser/frame_host/render_frame_host_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698