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

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

Issue 2922773002: Add BrowserCommandController Interactive Test (Closed)
Patch Set: Resolve review comments 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/keyboard_codes.h"
24 #include "ui/events/keycodes/keyboard_code_conversion.h"
25 #include "ui/events/keycodes/dom/keycode_converter.h"
26 #include "url/gurl.h"
27
28 namespace {
29 // The html file to receive key events, prevent defaults and export all the
30 // events with "getKeyEventReport()" function. It has two magic keys: pressing
31 // "S" to enter fullscreen mode; pressing "X" to indicate the end of all the
32 // keys.
33 constexpr char kFullscreenKeyboardLockHTML[] = "/fullscreen_keyboardlock.html";
34
35 class TabCountObserver : public TabStripModelObserver {
36 public:
37 TabCountObserver(Browser* browser, int expected);
38 ~TabCountObserver() override;
39
40 private:
41 // TabStripModelObserver implementations.
42 void TabInsertedAt(TabStripModel* tab_strip_model,
43 content::WebContents* contents,
44 int index,
45 bool foreground) override;
46
47 const int expected_;
48 bool seen_ = false;
49 };
50
51 TabCountObserver::TabCountObserver(Browser* browser, int expected)
52 : expected_(expected) {
53 DCHECK(browser);
54 seen_ = (browser->tab_strip_model()->count() == expected_);
55 if (!seen_) {
56 browser->tab_strip_model()->AddObserver(this);
57 }
58 }
59 TabCountObserver::~TabCountObserver() {
60 while (!seen_) {
61 content::RunAllPendingInMessageLoop();
62 }
63 }
64
65 void TabCountObserver::TabInsertedAt(TabStripModel* tab_strip_model,
66 content::WebContents* contents,
67 int index,
68 bool foreground) {
69 if (tab_strip_model->count() == expected_) {
70 seen_ = true;
71 }
72 }
73
74 } // namespace
75
76 class BrowserCommandControllerInteractiveTest : public InProcessBrowserTest {
77 public:
78 BrowserCommandControllerInteractiveTest() = default;
79 ~BrowserCommandControllerInteractiveTest() override = default;
80
81 protected:
82 // Starts the test page and waits for it to be loaded.
83 void StartTestPage();
84
85 // Wait for the browser to have the expected tab count or timeout.
86 void WaitForTabCount(int tab_count) const;
87
88 // Sends a control or command + |key| shortcut to the focused window. Shift
89 // modifier will be added if |shift| is true.
90 void SendShortcut(ui::KeyboardCode key, bool shift = false);
91
92 // Sends a control or command + shift + |key| shortcut to the focused window.
93 void SendShiftShortcut(ui::KeyboardCode key);
94
95 // Sends a fullscreen shortcut to the focused window and wait for the
96 // operation to take effect.
97 void SendFullscreenShortcutAndWait();
98
99 // Sends a KeyS to the focused window to trigger JavaScript fullscreen and
100 // wait for the operation to take effect.
101 void SendJsFullscreenShortcutAndWait();
102
103 // Sends an ESC to the focused window.
104 void SendEscape();
105
106 // Sends an ESC to the focused window to exit JavaScript fullscreen and wait
107 // for the operation to take effect.
108 void SendEscapeAndWaitForExitingFullscreen();
109
110 // Sends a magic KeyX to the focused window to stop the test case, receives
111 // the result and verifies if it equals to |expected_result_|.
112 void FinishTestAndVerifyResult();
113
114 private:
115 std::string expected_result_;
116
117 DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerInteractiveTest);
118 };
119
120 void BrowserCommandControllerInteractiveTest::StartTestPage() {
121 ASSERT_TRUE(embedded_test_server()->Start());
122 ui_test_utils::NavigateToURLWithDisposition(
123 browser(),
124 embedded_test_server()->GetURL(kFullscreenKeyboardLockHTML),
125 WindowOpenDisposition::CURRENT_TAB,
126 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
127 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
128 }
129
130 void BrowserCommandControllerInteractiveTest::WaitForTabCount(
131 int tab_count) const {
132 while (browser()->tab_strip_model()->count() != tab_count)
133 content::RunAllPendingInMessageLoop();
134 }
135
136 void BrowserCommandControllerInteractiveTest::SendShortcut(
137 ui::KeyboardCode key,
138 bool shift /* = false */) {
139 #if defined(OS_MACOSX)
140 const bool control_modifier = false;
141 const bool command_modifier = true;
142 #else
143 const bool control_modifier = true;
144 const bool command_modifier = false;
145 #endif
146 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
147 key, control_modifier, shift, false, command_modifier));
148
149 // TODO(zijiehe): Investigate why inconsistente key event sequence is
150 // generated by Mac OSX.
151 std::string code_string = ui::KeycodeConverter::DomCodeToCodeString(
152 ui::UsLayoutKeyboardCodeToDomCode(key));
153 #if defined(OS_MACOSX)
154 if (shift) {
155 expected_result_ += "keydown ShiftLeft\n";
156 }
157 expected_result_ += "keydown ControlLeft\n";
158 expected_result_ += "keydown ";
159 expected_result_ += code_string;
160 expected_result_ += "\n";
161 expected_result_ += "keyup ControlLeft\n";
162 if (shift) {
163 expected_result_ += "keyup ShiftLeft\n";
164 }
165 #else
166 expected_result_ += "keydown ControlLeft\n";
167 if (shift) {
168 expected_result_ += "keydown ShiftLeft\n";
169 }
170 expected_result_ += "keydown ";
171 expected_result_ += code_string;
172 expected_result_ += "\n";
173 expected_result_ += "keyup ";
174 expected_result_ += code_string;
175 expected_result_ += "\n";
176 if (shift) {
177 expected_result_ += "keyup ShiftLeft\n";
178 }
179 expected_result_ += "keyup ControlLeft\n";
180 #endif
181 }
182
183 void BrowserCommandControllerInteractiveTest::SendShiftShortcut(
184 ui::KeyboardCode key) {
185 SendShortcut(key, true);
186 }
187
188 void BrowserCommandControllerInteractiveTest::SendFullscreenShortcutAndWait() {
189 content::WindowedNotificationObserver observer(
190 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
191 content::NotificationService::AllSources());
192 // Enter fullscreen.
193 #if defined(OS_MACOSX)
194 // Command + Shift + F shortcut is not registered to interactive_ui_tests, so
195 // send directly a fullscreen command instead.
196 ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN));
197 #elif defined(OS_CHROMEOS)
198 // A dedicated fullscreen key is used on Chrome OS, so send a fullscreen
199 // command directly instead, to avoid constructing the key press.
200 ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN));
201 #else
202 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
203 browser(), ui::VKEY_F11, false, false, false, false));
204 #endif
205 observer.Wait();
206 }
207
208 void
209 BrowserCommandControllerInteractiveTest::SendJsFullscreenShortcutAndWait() {
210 content::WindowedNotificationObserver observer(
211 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
212 content::NotificationService::AllSources());
213 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
214 browser(), ui::VKEY_S, false, false, false, false));
215 expected_result_ += "keydown KeyS\n";
216 expected_result_ += "keyup KeyS\n";
217 observer.Wait();
218 }
219
220 void BrowserCommandControllerInteractiveTest::SendEscape() {
221 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
222 browser(), ui::VKEY_ESCAPE, false, false, false, false));
223 expected_result_ += "keydown Escape\n";
224 expected_result_ += "keyup Escape\n";
225 }
226
227 void BrowserCommandControllerInteractiveTest
228 ::SendEscapeAndWaitForExitingFullscreen() {
229 content::WindowedNotificationObserver observer(
230 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
231 content::NotificationService::AllSources());
232 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
233 browser(), ui::VKEY_ESCAPE, false, false, false, false));
234 observer.Wait();
235 }
236
237 void BrowserCommandControllerInteractiveTest::FinishTestAndVerifyResult() {
238 // Magic KeyX to stop the test.
239 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
240 ui::VKEY_X, false, false, false, false));
241 expected_result_ += "keydown KeyX\n";
242 expected_result_ += "keyup KeyX";
243 std::string result;
244 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
245 browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
246 "getKeyEventReport();",
247 &result));
248 #if defined(OS_MACOSX)
249 // On MacOSX command key is used for most of the shortcuts, so replace it with
250 // control to reduce the complexity of comparison of the results.
251 base::ReplaceSubstringsAfterOffset(&result, 0, "MetaLeft", "ControlLeft");
252 #endif
253 base::TrimWhitespaceASCII(result, base::TRIM_ALL, &result);
254 ASSERT_EQ(result, expected_result_);
255 }
256
257 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
258 ShortcutsShouldTakeEffectInWindowMode) {
259 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
260 SendShortcut(ui::VKEY_T);
261 WaitForTabCount(2);
262 // { TabCountObserver observer(browser(), 2); }
263 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
264 SendShortcut(ui::VKEY_T);
265 WaitForTabCount(3);
266 // { TabCountObserver observer(browser(), 3); }
267 ASSERT_EQ(browser()->tab_strip_model()->count(), 3);
268 #if !defined(OS_MACOSX)
269 // Command + W is not registered to interactive_ui_tests. So the following
270 // test cases won't work on Mac OSX.
271 SendShortcut(ui::VKEY_W);
272 WaitForTabCount(2);
273 // { TabCountObserver observer(browser(), 2); }
274 ASSERT_EQ(browser()->tab_strip_model()->count(), 2);
275 SendShortcut(ui::VKEY_W);
276 WaitForTabCount(1);
277 // { TabCountObserver observer(browser(), 1); }
278 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
279 #endif
280 SendFullscreenShortcutAndWait();
281 ASSERT_TRUE(browser()->
282 exclusive_access_manager()->
283 fullscreen_controller()->
284 IsFullscreenForBrowser());
285 }
286
287 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
288 UnpreservedShortcutsShouldBePreventable) {
289 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
290 StartTestPage();
291
292 // Print.
293 SendShortcut(ui::VKEY_P);
294 // Print by using system function.
295 SendShiftShortcut(ui::VKEY_P);
296 FinishTestAndVerifyResult();
297 }
298
299 #if defined(OS_MACOSX)
300 // TODO(zijiehe): Figure out why this test crashes on Mac OSX. The suspicious
301 // command is "SendFullscreenShortcutAndWait()".
302 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
303 DISABLED_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
304 #else
305 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
306 KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
307 #endif
308 IN_PROC_BROWSER_TEST_F(
309 BrowserCommandControllerInteractiveTest,
310 MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen) {
311 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
312 StartTestPage();
313
314 SendFullscreenShortcutAndWait();
315 // The tab should not be closed.
316 SendShortcut(ui::VKEY_W);
317 // The window should not be closed.
318 SendShiftShortcut(ui::VKEY_W);
319 // TODO(zijiehe): ChromeOS incorrectly handles these;
320 // see http://crbug.com/737307.
321 #if !defined(OS_CHROMEOS)
322 // A new tab should not be created.
323 SendShortcut(ui::VKEY_T);
324 // A new window should not be created.
325 SendShortcut(ui::VKEY_N);
326 // A new incognito window should not be created.
327 SendShiftShortcut(ui::VKEY_N);
328 // Last closed tab should not be restored.
329 SendShiftShortcut(ui::VKEY_T);
330 #endif
331 // Browser should not switch to the next tab.
332 SendShortcut(ui::VKEY_TAB);
333 // Browser should not switch to the previous tab.
334 SendShiftShortcut(ui::VKEY_TAB);
335 // Current page should not exit browser fullscreen mode.
336 SendEscape();
337
338 FinishTestAndVerifyResult();
339 }
340
341 IN_PROC_BROWSER_TEST_F(
342 BrowserCommandControllerInteractiveTest,
343 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForEsc) {
344 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
345 StartTestPage();
346
347 SendJsFullscreenShortcutAndWait();
348 // The tab should not be closed.
349 SendShortcut(ui::VKEY_W);
350 // The window should not be closed.
351 SendShiftShortcut(ui::VKEY_W);
352 // TODO(zijiehe): ChromeOS incorrectly handles these;
353 // see http://crbug.com/737307.
354 #if !defined(OS_CHROMEOS)
355 // A new tab should not be created.
356 SendShortcut(ui::VKEY_T);
357 // A new window should not be created.
358 SendShortcut(ui::VKEY_N);
359 // A new incognito window should not be created.
360 SendShiftShortcut(ui::VKEY_N);
361 // Last closed tab should not be restored.
362 SendShiftShortcut(ui::VKEY_T);
363 #endif
364 // Browser should not switch to the next tab.
365 SendShortcut(ui::VKEY_TAB);
366 // Browser should not switch to the previous tab.
367 SendShiftShortcut(ui::VKEY_TAB);
368 // Current page should exit HTML fullscreen mode.
369 SendEscapeAndWaitForExitingFullscreen();
370
371 FinishTestAndVerifyResult();
372 }
373
374 IN_PROC_BROWSER_TEST_F(
375 BrowserCommandControllerInteractiveTest,
376 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForF11) {
377 ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
378 StartTestPage();
379
380 SendJsFullscreenShortcutAndWait();
381 // The tab should not be closed.
382 SendShortcut(ui::VKEY_W);
383 // The window should not be closed.
384 SendShiftShortcut(ui::VKEY_W);
385 // TODO(zijiehe): ChromeOS incorrectly handles these;
386 // see http://crbug.com/737307.
387 #if !defined(OS_CHROMEOS)
388 // A new tab should not be created.
389 SendShortcut(ui::VKEY_T);
390 // A new window should not be created.
391 SendShortcut(ui::VKEY_N);
392 // A new incognito window should not be created.
393 SendShiftShortcut(ui::VKEY_N);
394 // Last closed tab should not be restored.
395 SendShiftShortcut(ui::VKEY_T);
396 #endif
397 // Browser should not switch to the next tab.
398 SendShortcut(ui::VKEY_TAB);
399 // Browser should not switch to the previous tab.
400 SendShiftShortcut(ui::VKEY_TAB);
401 // Current page should exit browser fullscreen mode.
402 SendFullscreenShortcutAndWait();
403
404 FinishTestAndVerifyResult();
405 }
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