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" | |
28 #include "ui/base/ime/composition_underline.h" | 27 #include "ui/base/ime/composition_underline.h" |
29 #include "ui/base/ime/text_edit_commands.h" | 28 #include "ui/base/ime/text_edit_commands.h" |
30 #include "ui/base/ime/text_input_client.h" | 29 #include "ui/base/ime/text_input_client.h" |
31 #include "ui/base/ime/text_input_mode.h" | 30 #include "ui/base/ime/text_input_mode.h" |
32 #include "ui/base/ime/text_input_type.h" | 31 #include "ui/base/ime/text_input_type.h" |
33 #include "url/gurl.h" | 32 #include "url/gurl.h" |
34 | 33 |
35 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 34 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
36 #include "ui/base/ime/linux/text_edit_command_auralinux.h" | 35 #include "ui/base/ime/linux/text_edit_command_auralinux.h" |
37 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" | 36 #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 tester()->GetTextInputType(&type) ? type : ui::TEXT_INPUT_TYPE_NONE; | 135 tester()->GetTextInputType(&type) ? type : ui::TEXT_INPUT_TYPE_NONE; |
137 if (expected_type_ == type) | 136 if (expected_type_ == type) |
138 OnSuccess(); | 137 OnSuccess(); |
139 } | 138 } |
140 | 139 |
141 const ui::TextInputType expected_type_; | 140 const ui::TextInputType expected_type_; |
142 | 141 |
143 DISALLOW_COPY_AND_ASSIGN(TextInputManagerTypeObserver); | 142 DISALLOW_COPY_AND_ASSIGN(TextInputManagerTypeObserver); |
144 }; | 143 }; |
145 | 144 |
| 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 |
146 // This class observes |TextInputState.type| for a specific RWHV. | 163 // This class observes |TextInputState.type| for a specific RWHV. |
147 class ViewTextInputTypeObserver : public TextInputManagerObserverBase { | 164 class ViewTextInputTypeObserver : public TextInputManagerObserverBase { |
148 public: | 165 public: |
149 explicit ViewTextInputTypeObserver(content::WebContents* web_contents, | 166 explicit ViewTextInputTypeObserver(content::WebContents* web_contents, |
150 content::RenderWidgetHostView* rwhv, | 167 content::RenderWidgetHostView* rwhv, |
151 ui::TextInputType expected_type) | 168 ui::TextInputType expected_type) |
152 : TextInputManagerObserverBase(web_contents), | 169 : TextInputManagerObserverBase(web_contents), |
153 web_contents_(web_contents), | 170 web_contents_(web_contents), |
154 view_(rwhv), | 171 view_(rwhv), |
155 expected_type_(expected_type) { | 172 expected_type_(expected_type) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 | 272 |
256 // This class observes all the text selection updates within a WebContents. | 273 // This class observes all the text selection updates within a WebContents. |
257 class TextSelectionObserver : public TextInputManagerObserverBase { | 274 class TextSelectionObserver : public TextInputManagerObserverBase { |
258 public: | 275 public: |
259 explicit TextSelectionObserver(content::WebContents* web_contents) | 276 explicit TextSelectionObserver(content::WebContents* web_contents) |
260 : TextInputManagerObserverBase(web_contents) { | 277 : TextInputManagerObserverBase(web_contents) { |
261 tester()->SetOnTextSelectionChangedCallback(base::Bind( | 278 tester()->SetOnTextSelectionChangedCallback(base::Bind( |
262 &TextSelectionObserver::VerifyChange, base::Unretained(this))); | 279 &TextSelectionObserver::VerifyChange, base::Unretained(this))); |
263 } | 280 } |
264 | 281 |
265 void WaitForSelectedText(const std::string& text, | 282 void WaitForSelectedText(const std::string& text) { |
266 bool user_initiated = true) { | 283 selected_text_ = text; |
267 expected_text_ = text; | 284 Wait(); |
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 } | |
276 } | 285 } |
277 | 286 |
278 private: | 287 private: |
279 void VerifyChange() { | 288 void VerifyChange() { |
280 last_selected_text_ = | 289 if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) == |
281 base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()); | 290 selected_text_) { |
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 // These optional properties are also used to verify that the last and | 295 std::string selected_text_; |
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_; | |
302 | 296 |
303 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); | 297 DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver); |
304 }; | 298 }; |
305 | 299 |
306 // This class monitors all the changes in TextInputState and keeps a record of | 300 // This class monitors all the changes in TextInputState and keeps a record of |
307 // the active views. There is no waiting and the recording process is | 301 // the active views. There is no waiting and the recording process is |
308 // continuous. | 302 // continuous. |
309 class RecordActiveViewsObserver { | 303 class RecordActiveViewsObserver { |
310 public: | 304 public: |
311 explicit RecordActiveViewsObserver(content::WebContents* web_contents) | 305 explicit RecordActiveViewsObserver(content::WebContents* web_contents) |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 }; | 973 }; |
980 | 974 |
981 for (auto* frame : frames) { | 975 for (auto* frame : frames) { |
982 focus_frame_and_input(frame); | 976 focus_frame_and_input(frame); |
983 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); | 977 EXPECT_TRUE(active_contents()->IsFocusedElementEditable()); |
984 active_contents()->ClearFocusedElement(); | 978 active_contents()->ClearFocusedElement(); |
985 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); | 979 EXPECT_FALSE(active_contents()->IsFocusedElementEditable()); |
986 } | 980 } |
987 } | 981 } |
988 | 982 |
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 | |
1107 // TODO(ekaramad): The following tests are specifically written for Aura and are | 983 // TODO(ekaramad): The following tests are specifically written for Aura and are |
1108 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus | 984 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus |
1109 // (crbug.com/602723). | 985 // (crbug.com/602723). |
1110 #if defined(USE_AURA) | 986 #if defined(USE_AURA) |
1111 // ----------------------------------------------------------------------------- | 987 // ----------------------------------------------------------------------------- |
1112 // Input Method Observer Tests | 988 // Input Method Observer Tests |
1113 // | 989 // |
1114 // The following tests will make use of the InputMethodObserver to verify that | 990 // The following tests will make use of the InputMethodObserver to verify that |
1115 // OOPIF pages interact properly with the InputMethod through the tab's view. | 991 // OOPIF pages interact properly with the InputMethod through the tab's view. |
1116 | 992 |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1491 | 1367 |
1492 // Closing this WebContents while we still hold on to our TestBrowserClient. | 1368 // Closing this WebContents while we still hold on to our TestBrowserClient. |
1493 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( | 1369 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( |
1494 1, TabStripModel::CLOSE_USER_GESTURE)); | 1370 1, TabStripModel::CLOSE_USER_GESTURE)); |
1495 | 1371 |
1496 // For the cleanup of the original WebContents in tab index 0. | 1372 // For the cleanup of the original WebContents in tab index 0. |
1497 content::SetBrowserClientForTesting(old_browser_client); | 1373 content::SetBrowserClientForTesting(old_browser_client); |
1498 } | 1374 } |
1499 #endif // defined(MAC_OSX) | 1375 #endif // defined(MAC_OSX) |
1500 #endif // !defined(OS_ANDROID) | 1376 #endif // !defined(OS_ANDROID) |
OLD | NEW |