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

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 // On MacOSX command key is used for most of the shortcuts, so replace it with
36 // control to reduce the complexity of comparison of the results.
37 void NormalizeMetaKeyForMacOS(std::string* output) {
38 #if defined(OS_MACOSX)
39 base::ReplaceSubstringsAfterOffset(output, 0, "MetaLeft", "ControlLeft");
40 #else
41 // Avoid unused variable warning.
42 output = nullptr;
43 #endif
44 }
45
46 } // namespace
47
48 class BrowserCommandControllerInteractiveTest : public InProcessBrowserTest {
49 public:
50 BrowserCommandControllerInteractiveTest() = default;
51 ~BrowserCommandControllerInteractiveTest() override = default;
52
53 protected:
54 // Starts the test page and waits for it to be loaded.
55 void StartTestPage();
56
57 // Wait for the browser to have the expected tab count or timeout.
58 void WaitForTabCount(int tab_count) const;
59
60 // Sends a control or command + |key| shortcut to the focused window. Shift
61 // modifier will be added if |shift| is true.
62 void SendShortcut(ui::KeyboardCode key, bool shift = false);
63
64 // Sends a control or command + shift + |key| shortcut to the focused window.
65 void SendShiftShortcut(ui::KeyboardCode key);
66
67 // Sends a fullscreen shortcut to the focused window and wait for the
68 // operation to take effect.
69 void SendFullscreenShortcutAndWait();
70
71 // Sends a KeyS to the focused window to trigger JavaScript fullscreen and
72 // wait for the operation to take effect.
73 void SendJsFullscreenShortcutAndWait();
74
75 // Sends an ESC to the focused window.
76 void SendEscape();
77
78 // Sends an ESC to the focused window to exit JavaScript fullscreen and wait
79 // for the operation to take effect.
80 void SendEscapeAndWaitForExitingFullscreen();
81
82 // Sends a set of preventable shortcuts to the web page.
83 void SendShortcutsInFullscreen();
84
85 // Sends a magic KeyX to the focused window to stop the test case, receives
86 // the result and verifies if it is equal to |expected_result_|.
87 void FinishTestAndVerifyResult();
88
89 private:
90 void SetUpOnMainThread() override;
91
92 std::string expected_result_;
93
94 DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerInteractiveTest);
95 };
96
97 void BrowserCommandControllerInteractiveTest::StartTestPage() {
98 ASSERT_TRUE(embedded_test_server()->Start());
99 // Ensures the initial states.
100 ASSERT_EQ(1, browser()->tab_strip_model()->count());
101 ASSERT_EQ(0, browser()->tab_strip_model()->active_index());
102 ASSERT_EQ(1U, BrowserList::GetInstance()->size());
103 // Add a second tab for counting and focus purposes.
104 AddTabAtIndex(1, GURL("about:blank"), ui::PAGE_TRANSITION_LINK);
105 ASSERT_EQ(2, browser()->tab_strip_model()->count());
106 ASSERT_EQ(1U, BrowserList::GetInstance()->size());
107
108 ui_test_utils::NavigateToURLWithDisposition(
109 browser(),
110 embedded_test_server()->GetURL(kFullscreenKeyboardLockHTML),
111 WindowOpenDisposition::CURRENT_TAB,
112 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
113 }
114
115 void BrowserCommandControllerInteractiveTest::WaitForTabCount(
116 int tab_count) const {
117 while (browser()->tab_strip_model()->count() != tab_count)
118 content::RunAllPendingInMessageLoop();
119 }
120
121 void BrowserCommandControllerInteractiveTest::SendShortcut(
122 ui::KeyboardCode key,
123 bool shift /* = false */) {
124 #if defined(OS_MACOSX)
125 const bool control_modifier = false;
126 const bool command_modifier = true;
127 #else
128 const bool control_modifier = true;
129 const bool command_modifier = false;
130 #endif
131 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
132 key, control_modifier, shift, false, command_modifier));
133
134 expected_result_ += ui::KeycodeConverter::DomCodeToCodeString(
135 ui::UsLayoutKeyboardCodeToDomCode(key));
136 expected_result_ += " ctrl:";
137 expected_result_ += control_modifier ? "true" : "false";
138 expected_result_ += " shift:";
139 expected_result_ += shift ? "true" : "false";
140 expected_result_ += " alt:false";
141 expected_result_ += " meta:";
142 expected_result_ += command_modifier ? "true" : "false";
143 expected_result_ += '\n';
144 }
145
146 void BrowserCommandControllerInteractiveTest::SendShiftShortcut(
147 ui::KeyboardCode key) {
148 SendShortcut(key, true);
149 }
150
151 void BrowserCommandControllerInteractiveTest::SendFullscreenShortcutAndWait() {
152 content::WindowedNotificationObserver observer(
153 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
154 content::NotificationService::AllSources());
155 // Enter fullscreen.
156 #if defined(OS_MACOSX)
157 // On MACOSX, Command + Control + F is used.
158 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
159 browser(), ui::VKEY_F, true, false, false, true));
160 #elif defined(OS_CHROMEOS)
161 // A dedicated fullscreen key is used on Chrome OS, so send a fullscreen
162 // command directly instead, to avoid constructing the key press.
163 ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN));
164 #else
165 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
166 browser(), ui::VKEY_F11, false, false, false, false));
167 #endif
168
169 observer.Wait();
170 }
171
172 void
173 BrowserCommandControllerInteractiveTest::SendJsFullscreenShortcutAndWait() {
174 content::WindowedNotificationObserver observer(
175 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
176 content::NotificationService::AllSources());
177 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
178 browser(), ui::VKEY_S, false, false, false, false));
179 expected_result_ += "KeyS ctrl:false shift:false alt:false meta:false\n";
180 observer.Wait();
181 }
182
183 void BrowserCommandControllerInteractiveTest::SendEscape() {
184 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
185 browser(), ui::VKEY_ESCAPE, false, false, false, false));
186 expected_result_ += "Escape ctrl:false shift:false alt:false meta:false\n";
187 }
188
189 void BrowserCommandControllerInteractiveTest
190 ::SendEscapeAndWaitForExitingFullscreen() {
191 content::WindowedNotificationObserver observer(
192 chrome::NOTIFICATION_FULLSCREEN_CHANGED,
193 content::NotificationService::AllSources());
194 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
195 browser(), ui::VKEY_ESCAPE, false, false, false, false));
196 observer.Wait();
197 }
198
199 void BrowserCommandControllerInteractiveTest::SendShortcutsInFullscreen() {
200 const auto initial_active_index = browser()->tab_strip_model()->active_index() ;
201 const auto initial_tab_count = browser()->tab_strip_model()->count();
202 const auto initial_browser_count = BrowserList::GetInstance()->size();
203 // The tab should not be closed.
204 SendShortcut(ui::VKEY_W);
205 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
206 // The window should not be closed.
207 SendShiftShortcut(ui::VKEY_W);
208 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
209 // TODO(zijiehe): ChromeOS incorrectly handles these;
210 // see http://crbug.com/737307.
211 #if !defined(OS_CHROMEOS)
212 // A new tab should not be created.
213 SendShortcut(ui::VKEY_T);
214 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
215 // A new window should not be created.
216 SendShortcut(ui::VKEY_N);
217 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
218 // A new incognito window should not be created.
219 SendShiftShortcut(ui::VKEY_N);
220 ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size());
221 // Last closed tab should not be restored.
222 SendShiftShortcut(ui::VKEY_T);
223 ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count());
224 #endif
225 // Browser should not switch to the next tab.
226 SendShortcut(ui::VKEY_TAB);
227 ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index());
228 // Browser should not switch to the previous tab.
229 SendShiftShortcut(ui::VKEY_TAB);
230 ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index());
231 }
232
233 void BrowserCommandControllerInteractiveTest::FinishTestAndVerifyResult() {
234 // Magic KeyX to stop the test.
235 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(),
236 ui::VKEY_X, false, false, false, false));
237 expected_result_ += "KeyX ctrl:false shift:false alt:false meta:false";
238 std::string result;
239 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
240 browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(),
241 "getKeyEventReport();",
242 &result));
243 NormalizeMetaKeyForMacOS(&result);
244 NormalizeMetaKeyForMacOS(&expected_result_);
245 base::TrimWhitespaceASCII(result, base::TRIM_ALL, &result);
246 ASSERT_EQ(expected_result_, result);
247 }
248
249 void BrowserCommandControllerInteractiveTest::SetUpOnMainThread() {
250 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
251 }
252
253 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
254 ShortcutsShouldTakeEffectInWindowMode) {
255 ASSERT_EQ(1, browser()->tab_strip_model()->count());
256 SendShortcut(ui::VKEY_T);
257 WaitForTabCount(2);
258 ASSERT_EQ(2, browser()->tab_strip_model()->count());
259 SendShortcut(ui::VKEY_T);
260 WaitForTabCount(3);
261 ASSERT_EQ(3, browser()->tab_strip_model()->count());
262 SendShortcut(ui::VKEY_W);
263 WaitForTabCount(2);
264 ASSERT_EQ(2, browser()->tab_strip_model()->count());
265 SendShortcut(ui::VKEY_W);
266 WaitForTabCount(1);
267 ASSERT_EQ(1, browser()->tab_strip_model()->count());
268 SendFullscreenShortcutAndWait();
269 ASSERT_TRUE(browser()->
270 exclusive_access_manager()->
271 fullscreen_controller()->
272 IsFullscreenForBrowser());
273 }
274
275 IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest,
276 UnpreservedShortcutsShouldBePreventable) {
277 StartTestPage();
278
279 // The browser print function should be blocked by the web page.
280 SendShortcut(ui::VKEY_P);
281 // The system print function should be blocked by the web page.
282 SendShiftShortcut(ui::VKEY_P);
283 FinishTestAndVerifyResult();
284 }
285
286 #if defined(OS_MACOSX)
287 // TODO(zijiehe): Figure out why this test crashes on Mac OSX. The suspicious
288 // command is "SendFullscreenShortcutAndWait()". See, http://crbug.com/738949.
289 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
290 DISABLED_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
291 #else
292 #define MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen \
293 KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen
294 #endif
295 IN_PROC_BROWSER_TEST_F(
296 BrowserCommandControllerInteractiveTest,
297 MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen) {
298 StartTestPage();
299
300 SendFullscreenShortcutAndWait();
301 SendShortcutsInFullscreen();
302 // Current page should not exit browser fullscreen mode.
303 SendEscape();
304
305 FinishTestAndVerifyResult();
306 }
307
308 IN_PROC_BROWSER_TEST_F(
309 BrowserCommandControllerInteractiveTest,
310 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForEsc) {
311 StartTestPage();
312
313 SendJsFullscreenShortcutAndWait();
314 SendShortcutsInFullscreen();
315 // Current page should exit HTML fullscreen mode.
316 SendEscapeAndWaitForExitingFullscreen();
317
318 FinishTestAndVerifyResult();
319 }
320
321 IN_PROC_BROWSER_TEST_F(
322 BrowserCommandControllerInteractiveTest,
323 KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForF11) {
324 StartTestPage();
325
326 SendJsFullscreenShortcutAndWait();
327 SendShortcutsInFullscreen();
328 // Current page should exit browser fullscreen mode.
329 SendFullscreenShortcutAndWait();
330
331 FinishTestAndVerifyResult();
332 }
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