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

Side by Side Diff: chrome/browser/ui/browser_command_controller_interactive_browsertest.cc

Issue 2922773002: Add BrowserCommandController Interactive Test (Closed)
Patch Set: Update getKeyEventReport() logic Created 3 years, 5 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 | « no previous file | chrome/test/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6 #include <string>
7
8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/string_util.h"
11 #include "build/build_config.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/interactive_test_utils.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/public/test/test_utils.h"
23 #include "ui/events/keycodes/dom/keycode_converter.h"
24 #include "ui/events/keycodes/keyboard_code_conversion.h"
25 #include "ui/events/keycodes/keyboard_codes.h"
26 #include "url/gurl.h"
27 #include "url/url_constants.h"
28
29 #if defined(OS_MACOSX)
30 #include "base/mac/mac_util.h"
31 #endif
32
33 namespace {
34 // The html file to receive key events, prevent defaults and export all the
35 // events with "getKeyEventReport()" function. It has two magic keys: pressing
36 // "S" to enter fullscreen mode; pressing "X" to indicate the end of all the
37 // keys.
38 constexpr char kFullscreenKeyboardLockHTML[] = "/fullscreen_keyboardlock.html";
39
40 // On MacOSX command key is used for most of the shortcuts, so replace it with
41 // control to reduce the complexity of comparison of the results.
42 void NormalizeMetaKeyForMacOS(std::string* output) {
43 #if defined(OS_MACOSX)
44 base::ReplaceSubstringsAfterOffset(output, 0, "MetaLeft", "ControlLeft");
45 #else
46 // Avoid unused variable warning.
47 output = nullptr;
sky 2017/07/13 20:33:25 Are you sure this is really necessary?
Hzj_jie 2017/07/13 23:05:11 My fault, removed.
48 #endif
49 }
50
51 } // namespace
52
53 class BrowserCommandControllerInteractiveTest : public InProcessBrowserTest {
54 public:
55 BrowserCommandControllerInteractiveTest() = default;
56 ~BrowserCommandControllerInteractiveTest() override = default;
57
58 protected:
59 // Starts the test page and waits for it to be loaded.
60 void StartTestPage();
61
62 // Wait for the browser to have the expected tab count or timeout.
63 void WaitForTabCount(int tab_count) const;
64
65 // Sends a control or command + |key| shortcut to the focused window. Shift
66 // modifier will be added if |shift| is true.
67 void SendShortcut(ui::KeyboardCode key, bool shift = false);
68
69 // Sends a control or command + shift + |key| shortcut to the focused window.
70 void SendShiftShortcut(ui::KeyboardCode key);
71
72 // Sends a fullscreen shortcut to the focused window and wait for the
73 // operation to take effect.
74 void SendFullscreenShortcutAndWait();
75
76 // Sends a KeyS to the focused window to trigger JavaScript fullscreen and
77 // wait for the operation to take effect.
78 void SendJsFullscreenShortcutAndWait();
79
80 // Sends an ESC to the focused window.
81 void SendEscape();
82
83 // Sends an ESC to the focused window to exit JavaScript fullscreen and wait
84 // for the operation to take effect.
85 void SendEscapeAndWaitForExitingFullscreen();
86
87 // Sends a set of preventable shortcuts to the web page.
88 void SendShortcutsInFullscreen();
89
90 // Sends a magic KeyX to the focused window to stop the test case, receives
91 // the result and verifies if it is equal to |expected_result_|.
92 void FinishTestAndVerifyResult();
93
94 private:
95 void SetUpOnMainThread() override;
96
97 std::string expected_result_;
sky 2017/07/13 20:33:25 Please add a comment.
Hzj_jie 2017/07/13 23:05:11 Done.
98
99 DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerInteractiveTest);
100 };
101
102 void BrowserCommandControllerInteractiveTest::StartTestPage() {
sky 2017/07/13 20:33:25 You need to wrap all calls to this in ASSERT_NO_FA
Hzj_jie 2017/07/13 23:05:11 Done.
103 ASSERT_TRUE(embedded_test_server()->Start());
104 // Ensures the initial states.
105 ASSERT_EQ(1, browser()->tab_strip_model()->count());
106 ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
107 ASSERT_EQ(1U, BrowserList::GetInstance()->size());
108 // Add a second tab for counting and focus purposes.
109 AddTabAtIndex(1, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK);
110 ASSERT_EQ(2, browser()->tab_strip_model()->count());
111 ASSERT_EQ(1U, BrowserList::GetInstance()->size());
112
113 ui_test_utils::NavigateToURLWithDisposition(
114 browser(), embedded_test_server()->GetURL(kFullscreenKeyboardLockHTML),
115 WindowOpenDisposition::CURRENT_TAB,
116 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
117 }
118
119 void BrowserCommandControllerInteractiveTest::WaitForTabCount(
sky 2017/07/13 20:33:26 Why do you need the wait here? AFAICT you wait for
Hzj_jie 2017/07/13 23:05:11 Done.
120 int tab_count) const {
121 while (browser()->tab_strip_model()->count() != tab_count)
122 content::RunAllPendingInMessageLoop();
123 }
124
125 void BrowserCommandControllerInteractiveTest::SendShortcut(
sky 2017/07/13 20:33:25 Similar comment about ASSERT_NO_FATAL_FAILURE.
Hzj_jie 2017/07/13 23:05:11 Done.
126 ui::KeyboardCode key,
127 bool shift /* = false */) {
128 #if defined(OS_MACOSX)
129 const bool control_modifier = false;
130 const bool command_modifier = true;
131 #else
132 const bool control_modifier = true;
133 const bool command_modifier = false;
134 #endif
135 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, control_modifier,
136 shift, false, command_modifier));
137
138 expected_result_ += ui::KeycodeConverter::DomCodeToCodeString(
139 ui::UsLayoutKeyboardCodeToDomCode(key));
140 expected_result_ += " ctrl:";
141 expected_result_ += control_modifier ? "true" : "false";
142 expected_result_ += " shift:";
143 expected_result_ += shift ? "true" : "false";
144 expected_result_ += " alt:false";
145 expected_result_ += " meta:";
146 expected_result_ += command_modifier ? "true" : "false";
147 expected_result_ += '\n';
148 }
149
150 void BrowserCommandControllerInteractiveTest::SendShiftShortcut(
151 ui::KeyboardCode key) {
152 SendShortcut(key, true);
153 }
154
155 void BrowserCommandControllerInteractiveTest::SendFullscreenShortcutAndWait() {
156 content::WindowedNotificationObserver observer(
157 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
158 content::NotificationService::AllSources());
159 // Enter fullscreen.
sky 2017/07/13 20:33:25 fix indentation.
Hzj_jie 2017/07/13 23:05:11 It's triple weird, this is done by git cl format.
160 #if defined(OS_MACOSX)
161 // On MACOSX, Command + Control + F is used.
162 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_F, true,
163 false, false, true));
164 #elif defined(OS_CHROMEOS)
165 // A dedicated fullscreen key is used on Chrome OS, so send a fullscreen
166 // command directly instead, to avoid constructing the key press.
167 ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN));
168 #else
169 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_F11, false,
sky 2017/07/13 20:33:25 Similar comment here about the need to wait.
Hzj_jie 2017/07/13 23:05:11 At least on Mac OSX, entering and exiting fullscre
sky 2017/07/14 00:03:37 Ok, please add a comment to that effect then.
Hzj_jie 2017/07/14 00:24:51 Done.
170 false, false, false));
171 #endif
172
173 observer.Wait();
174 }
175
176 void BrowserCommandControllerInteractiveTest::
177 SendJsFullscreenShortcutAndWait() {
178 content::WindowedNotificationObserver observer(
179 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
180 content::NotificationService::AllSources());
181 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_S, false,
182 false, false, false));
183 expected_result_ += "KeyS ctrl:false shift:false alt:false meta:false\n";
184 observer.Wait();
185 }
186
187 void BrowserCommandControllerInteractiveTest::SendEscape() {
188 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false,
189 false, false, false));
190 expected_result_ += "Escape ctrl:false shift:false alt:false meta:false\n";
191 }
192
193 void BrowserCommandControllerInteractiveTest ::
194 SendEscapeAndWaitForExitingFullscreen() {
195 content::WindowedNotificationObserver observer(
196 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
197 content::NotificationService::AllSources());
198 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false,
199 false, false, false));
200 observer.Wait();
201 }
202
203 void BrowserCommandControllerInteractiveTest::SendShortcutsInFullscreen() {
204 const int initial_active_index = browser()->tab_strip_model()->active_index();
205 const int initial_tab_count = browser()->tab_strip_model()->count();
206 const size_t initial_browser_count = BrowserList::GetInstance()->size();
207 // The tab should not be closed.
208 SendShortcut(ui::VKEY_W);
209 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
210 // The window should not be closed.
211 SendShiftShortcut(ui::VKEY_W);
212 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
213 // TODO(zijiehe): ChromeOS incorrectly handles these;
sky 2017/07/13 20:33:26 fix indentation.
Hzj_jie 2017/07/13 23:05:11 Done.
214 // see http://crbug.com/737307.
215 #if !defined(OS_CHROMEOS)
216 // A new tab should not be created.
217 SendShortcut(ui::VKEY_T);
218 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
219 // A new window should not be created.
220 SendShortcut(ui::VKEY_N);
221 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
222 // A new incognito window should not be created.
223 SendShiftShortcut(ui::VKEY_N);
224 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
225 // Last closed tab should not be restored.
226 SendShiftShortcut(ui::VKEY_T);
227 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
228 #endif
229 // Browser should not switch to the next tab.
230 SendShortcut(ui::VKEY_TAB);
231 ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index());
232 // Browser should not switch to the previous tab.
233 SendShiftShortcut(ui::VKEY_TAB);
234 ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index());
235 }
236
237 void BrowserCommandControllerInteractiveTest::FinishTestAndVerifyResult() {
238 // Magic KeyX to stop the test.
239 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_X, false,
sky 2017/07/13 20:33:25 Why is this necessary?
Hzj_jie 2017/07/13 23:05:11 If my understanding is correct, the keys are sent
sky 2017/07/14 00:03:37 Pleaes add a better comment (the current comment i
Hzj_jie 2017/07/14 00:24:51 Done.
240 false, false, false));
241 expected_result_ += "KeyX ctrl:false shift:false alt:false meta:false";
242 std::string result;
243 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
244 browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
245 "getKeyEventReport();", &result));
246 NormalizeMetaKeyForMacOS(&result);
247 NormalizeMetaKeyForMacOS(&expected_result_);
248 base::TrimWhitespaceASCII(result, base::TRIM_ALL, &result);
249 ASSERT_EQ(expected_result_, result);
250 }
251
252 void BrowserCommandControllerInteractiveTest::SetUpOnMainThread() {
253 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
254 }
255
256 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
257 ShortcutsShouldTakeEffectInWindowMode) {
258 ASSERT_EQ(1, browser()->tab_strip_model()->count());
259 SendShortcut(ui::VKEY_T);
260 WaitForTabCount(2);
261 ASSERT_EQ(2, browser()->tab_strip_model()->count());
262 SendShortcut(ui::VKEY_T);
263 WaitForTabCount(3);
264 ASSERT_EQ(3, browser()->tab_strip_model()->count());
265 SendShortcut(ui::VKEY_W);
266 WaitForTabCount(2);
267 ASSERT_EQ(2, browser()->tab_strip_model()->count());
268 SendShortcut(ui::VKEY_W);
269 WaitForTabCount(1);
270 ASSERT_EQ(1, browser()->tab_strip_model()->count());
271 SendFullscreenShortcutAndWait();
272 ASSERT_TRUE(browser()
273 ->exclusive_access_manager()
274 ->fullscreen_controller()
275 ->IsFullscreenForBrowser());
276 }
277
278 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
279 UnpreservedShortcutsShouldBePreventable) {
280 StartTestPage();
281
282 // The browser print function should be blocked by the web page.
283 SendShortcut(ui::VKEY_P);
284 // The system print function should be blocked by the web page.
285 SendShiftShortcut(ui::VKEY_P);
286 FinishTestAndVerifyResult();
287 }
288
289 #if defined(OS_MACOSX)
290 // TODO(zijiehe): Figure out why this test crashes on Mac OSX. The suspicious
291 // command is "SendFullscreenShortcutAndWait()". See, http://crbug.com/738949.
292 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
293 DISABLED_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
294 #else
295 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
296 KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
297 #endif
298 IN_PROC_BROWSER_TEST_F(
299 BrowserCommandControllerInteractiveTest,
300 MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen) {
301 StartTestPage();
302
303 SendFullscreenShortcutAndWait();
304 SendShortcutsInFullscreen();
305 // Current page should not exit browser fullscreen mode.
306 SendEscape();
307
308 FinishTestAndVerifyResult();
309 }
310
311 IN_PROC_BROWSER_TEST_F(
312 BrowserCommandControllerInteractiveTest,
313 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForEsc) {
314 StartTestPage();
315
316 SendJsFullscreenShortcutAndWait();
317 SendShortcutsInFullscreen();
318 // Current page should exit HTML fullscreen mode.
319 SendEscapeAndWaitForExitingFullscreen();
320
321 FinishTestAndVerifyResult();
322 }
323
324 IN_PROC_BROWSER_TEST_F(
325 BrowserCommandControllerInteractiveTest,
326 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForF11) {
327 StartTestPage();
328
329 SendJsFullscreenShortcutAndWait();
330 SendShortcutsInFullscreen();
331 #if defined(OS_MACOSX)
332 // On 10.9 or earlier, sending the exit fullscreen shortcut will crash the
333 // binary. See http://crbug.com/740250.
334 if (base::mac::IsAtLeastOS10_10()) {
335 // Current page should exit browser fullscreen mode.
336 SendFullscreenShortcutAndWait();
337 }
338 #else
339 // Current page should exit browser fullscreen mode.
340 SendFullscreenShortcutAndWait();
341 #endif
342
343 FinishTestAndVerifyResult();
344 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698