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

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: Workaround mac fail 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 const content::RenderWidgetHostView* const expected_view_; 250 const content::RenderWidgetHostView* const expected_view_;
268 const size_t expected_length_; 251 const size_t expected_length_;
269 252
270 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver); 253 DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver);
271 }; 254 };
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), callback_called_(false) {
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 (callback_called_ && last_selected_text_ == expected_text_ &&
270 last_user_initiated_ == expected_user_initiated_) {
271 OnSuccess();
272 } else {
273 Wait();
274 }
285 } 275 }
286 276
287 private: 277 private:
288 void VerifyChange() { 278 void VerifyChange() {
289 if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == 279 callback_called_ = true;
290 selected_text_) { 280
281 last_selected_text_ =
282 base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText());
283 EXPECT_TRUE(tester()->GetTextSelectionUserInitiatedForView(
284 tester()->GetUpdatedView(), &last_user_initiated_));
285
286 if (last_selected_text_ == expected_text_ &&
287 last_user_initiated_ == expected_user_initiated_) {
291 OnSuccess(); 288 OnSuccess();
292 } 289 }
293 } 290 }
294 291
295 std::string selected_text_; 292 bool callback_called_;
293
294 std::string last_selected_text_;
295 std::string expected_text_;
296 bool last_user_initiated_;
Lei Zhang 2017/05/17 19:23:05 Should these bools be initialized in the ctor?
Peter Varga 2017/05/18 08:27:20 They are initialized to false this way and I don't
Lei Zhang 2017/05/18 18:13:46 Can VerifyChange() get called before the first Wai
Peter Varga 2017/05/19 08:50:01 hmm, yes it can.
297 bool expected_user_initiated_;
296 298
297 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); 299 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver);
298 }; 300 };
299 301
300 // This class monitors all the changes in TextInputState and keeps a record of 302 // 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 303 // the active views. There is no waiting and the recording process is
302 // continuous. 304 // continuous.
303 class RecordActiveViewsObserver { 305 class RecordActiveViewsObserver {
304 public: 306 public:
305 explicit RecordActiveViewsObserver(content::WebContents* web_contents) 307 explicit RecordActiveViewsObserver(content::WebContents* web_contents)
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 }; 975 };
974 976
975 for (auto* frame : frames) { 977 for (auto* frame : frames) {
976 focus_frame_and_input(frame); 978 focus_frame_and_input(frame);
977 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); 979 EXPECT_TRUE(active_contents()->IsFocusedElementEditable());
978 active_contents()->ClearFocusedElement(); 980 active_contents()->ClearFocusedElement();
979 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); 981 EXPECT_FALSE(active_contents()->IsFocusedElementEditable());
980 } 982 }
981 } 983 }
982 984
985 // The following tests verify that the TextInputManager notifies about a
986 // about text selection change event, the corresponding |user_initiated|
987 // property of TextSelection is valid, and the selection clipboard is updated
988 // according to the source of the event.
989 // See: https://crbug.com/671986
990
991 // Test text selection change event for non-user initiated cases
992 // (eg. JavaScript). Non-user initiated events should not update the selection
993 // clipboard.
994 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
995 NonUserInitiatedTextSelection) {
996 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
997 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
998 ASSERT_TRUE(!!clipboard);
Lei Zhang 2017/05/17 19:23:05 I think ASSERT_TRUE() works with the "!!"
Peter Varga 2017/05/18 08:27:20 I don't really understand what is wrong with this
Lei Zhang 2017/05/18 18:13:46 I just wanted to point out that you can omit the "
Peter Varga 2017/05/19 08:50:01 I would rather write if (ptr) :) Since I haven't f
999 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION);
1000 #endif
1001
1002 CreateIframePage("a(b, c)");
1003 std::vector<std::string> values{"node_a", "node_b", "node_c"};
1004 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}),
1005 GetFrame(IndexVector{0}),
1006 GetFrame(IndexVector{1})};
1007
1008 for (size_t i = 0; i < frames.size(); ++i)
1009 AddInputFieldToFrame(frames[i], "text", values[i], true);
1010
1011 // Test text selection from JavaScript across frames (non-user initiated).
1012 for (size_t i = 0; i < frames.size(); ++i) {
1013 // Trigger text selection.
1014 TextSelectionObserver trigger_observer(active_contents());
1015 EXPECT_TRUE(
1016 ExecuteScript(frames[i], "document.querySelector('input').select();"));
1017 trigger_observer.WaitForSelectedText(values[i], false);
1018
1019 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1020 // Non-user initiated text selection should not update the selection
1021 // clipboard. See: https://crbug.com/12392
1022 base::string16 result_text;
1023 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1024 EXPECT_TRUE(result_text.empty());
1025 #endif
1026
1027 // Clear text selection.
1028 TextSelectionObserver clear_observer(active_contents());
1029 EXPECT_TRUE(ExecuteScript(frames[i], "document.getSelection().empty();"));
1030 clear_observer.WaitForSelectedText("", false);
1031 }
1032 }
1033
1034 // Test text selection change event for user initiated cases (eg. key press)
1035 // User initiated events should update the selection clipboard where it is
1036 // supported.
1037 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
1038 UserInitiatedTextSelection) {
1039 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1040 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1041 ASSERT_TRUE(!!clipboard);
1042 clipboard->Clear(ui::CLIPBOARD_TYPE_SELECTION);
1043 #endif
1044
1045 CreateIframePage("a(b, c)");
1046 std::vector<std::string> values{"node_a", "node_b", "node_c"};
1047 std::vector<content::RenderFrameHost*> frames{GetFrame(IndexVector{}),
1048 GetFrame(IndexVector{0}),
1049 GetFrame(IndexVector{1})};
1050
1051 for (size_t i = 0; i < frames.size(); ++i)
1052 AddInputFieldToFrame(frames[i], "text", values[i], true);
1053
1054 // Test text selection by user input across frames (user initiated).
1055 for (size_t i = 0; i < frames.size(); ++i) {
1056 // Focus on input element.
1057 std::string result;
1058 std::string script =
1059 "function getInputField() {"
1060 " return document.querySelector('input');"
1061 "}"
1062 "function onInputFocus(e) {"
1063 " domAutomationController.setAutomationId(0);"
1064 " domAutomationController.send(getInputField().value);"
1065 "}"
1066 "getInputField().addEventListener('focus', onInputFocus);";
1067 EXPECT_TRUE(ExecuteScript(frames[i], script));
1068 EXPECT_TRUE(ExecuteScriptAndExtractString(
1069 frames[i], "window.focus(); document.querySelector('input').focus();",
1070 &result));
1071 EXPECT_EQ(values[i], result);
1072 EXPECT_EQ(frames[i], active_contents()->GetFocusedFrame());
1073
1074 // Press ctrl+a to select text in the input field.
1075 TextSelectionObserver trigger_observer(active_contents());
1076 #if !defined(OS_MACOSX)
1077 SimulateKeyPress(active_contents(), ui::DomKey::FromCharacter('A'),
1078 ui::DomCode::US_A, ui::VKEY_A, true, false, false, false);
1079 #else
1080 // On macOS the select all shortcut (Cmd+A) is handled by the browser via
1081 // keyboard accelerator. Thus we can't simulate key press on WebContents.
1082 // As a workaround, call the SelectAll directly as the shortcut would do.
1083 active_contents()->SelectAll();
1084 #endif
1085 trigger_observer.WaitForSelectedText(values[i], true);
1086
1087 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
1088 // User initiated text selection should update the selection clipboard.
1089 base::string16 result_text;
1090 clipboard->ReadText(ui::CLIPBOARD_TYPE_SELECTION, &result_text);
1091 EXPECT_EQ(base::ASCIIToUTF16(values[i]), result_text);
1092 #endif
1093
1094 // Press down key to clear text selection.
1095 TextSelectionObserver clear_observer(active_contents());
1096 SimulateKeyPress(active_contents(), ui::DomKey::ARROW_DOWN,
1097 ui::DomCode::ARROW_DOWN, ui::VKEY_DOWN, false, false,
1098 false, false);
1099 clear_observer.WaitForSelectedText("", true);
1100 }
1101 }
1102
983 // TODO(ekaramad): The following tests are specifically written for Aura and are 1103 // TODO(ekaramad): The following tests are specifically written for Aura and are
984 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus 1104 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus
985 // (crbug.com/602723). 1105 // (crbug.com/602723).
986 #if defined(USE_AURA) 1106 #if defined(USE_AURA)
987 // ----------------------------------------------------------------------------- 1107 // -----------------------------------------------------------------------------
988 // Input Method Observer Tests 1108 // Input Method Observer Tests
989 // 1109 //
990 // The following tests will make use of the InputMethodObserver to verify that 1110 // 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. 1111 // OOPIF pages interact properly with the InputMethod through the tab's view.
992 1112
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 1487
1368 // Closing this WebContents while we still hold on to our TestBrowserClient. 1488 // Closing this WebContents while we still hold on to our TestBrowserClient.
1369 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( 1489 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(
1370 1, TabStripModel::CLOSE_USER_GESTURE)); 1490 1, TabStripModel::CLOSE_USER_GESTURE));
1371 1491
1372 // For the cleanup of the original WebContents in tab index 0. 1492 // For the cleanup of the original WebContents in tab index 0.
1373 content::SetBrowserClientForTesting(old_browser_client); 1493 content::SetBrowserClientForTesting(old_browser_client);
1374 } 1494 }
1375 #endif // defined(MAC_OSX) 1495 #endif // defined(MAC_OSX)
1376 #endif // !defined(OS_ANDROID) 1496 #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