1 // Copyright (c) 2012 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 "chrome/browser/ui/browser_command_controller.h"
6
7 #include "base/command_line.h"
8 #include "base/stl_util.h"
9 #include "build/branding_buildflags.h"
10 #include "build/build_config.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/command_updater.h"
14 #include "chrome/browser/prefs/incognito_mode_prefs.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/profiles/profiles_state.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/browser_window_state.h"
20 #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/test/base/browser_with_test_window_test.h"
25 #include "chrome/test/base/test_browser_window.h"
26 #include "chrome/test/base/testing_browser_process.h"
27 #include "chrome/test/base/testing_profile.h"
28 #include "chrome/test/base/testing_profile_manager.h"
29 #include "components/signin/public/base/signin_pref_names.h"
30 #include "content/public/browser/native_web_keyboard_event.h"
31 #include "ui/events/keycodes/dom/dom_code.h"
32 #include "ui/events/keycodes/keyboard_codes.h"
33
34 typedef BrowserWithTestWindowTest BrowserCommandControllerTest;
35
36 class GuestBrowserCommandControllerTest
37 : public BrowserWithTestWindowTest,
38 public testing::WithParamInterface<bool> {
39 public:
GuestBrowserCommandControllerTest()40 GuestBrowserCommandControllerTest() : is_ephemeral_(GetParam()) {
41 // Change the value if Ephemeral is not supported.
42 is_ephemeral_ &=
43 TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
44 scoped_feature_list_, is_ephemeral_);
45 }
46
is_ephemeral() const47 bool is_ephemeral() const { return is_ephemeral_; }
48
49 private:
50 bool is_ephemeral_;
51 base::test::ScopedFeatureList scoped_feature_list_;
52 };
53
TEST_F(BrowserCommandControllerTest,IsReservedCommandOrKey)54 TEST_F(BrowserCommandControllerTest, IsReservedCommandOrKey) {
55 #if defined(OS_CHROMEOS)
56 // F1-3 keys are reserved Chrome accelerators on Chrome OS.
57 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
58 IDC_BACK, content::NativeWebKeyboardEvent(
59 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_BACK,
60 ui::DomCode::BROWSER_BACK, 0))));
61 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
62 IDC_FORWARD, content::NativeWebKeyboardEvent(ui::KeyEvent(
63 ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_FORWARD,
64 ui::DomCode::BROWSER_FORWARD, 0))));
65 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
66 IDC_RELOAD, content::NativeWebKeyboardEvent(
67 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_BROWSER_REFRESH,
68 ui::DomCode::BROWSER_REFRESH, 0))));
69
70 // When there are modifier keys pressed, don't reserve.
71 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
72 IDC_RELOAD_BYPASSING_CACHE, content::NativeWebKeyboardEvent(ui::KeyEvent(
73 ui::ET_KEY_PRESSED, ui::VKEY_F3,
74 ui::DomCode::F3, ui::EF_SHIFT_DOWN))));
75 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
76 IDC_RELOAD_BYPASSING_CACHE, content::NativeWebKeyboardEvent(ui::KeyEvent(
77 ui::ET_KEY_PRESSED, ui::VKEY_F3,
78 ui::DomCode::F3, ui::EF_CONTROL_DOWN))));
79 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
80 IDC_FULLSCREEN, content::NativeWebKeyboardEvent(
81 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_F4,
82 ui::DomCode::F4, ui::EF_SHIFT_DOWN))));
83
84 // F4-10 keys are not reserved since they are Ash accelerators.
85 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
86 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
87 ui::ET_KEY_PRESSED, ui::VKEY_F4, ui::DomCode::F4, 0))));
88 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
89 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
90 ui::ET_KEY_PRESSED, ui::VKEY_F5, ui::DomCode::F5, 0))));
91 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
92 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
93 ui::ET_KEY_PRESSED, ui::VKEY_F6, ui::DomCode::F6, 0))));
94 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
95 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
96 ui::ET_KEY_PRESSED, ui::VKEY_F7, ui::DomCode::F7, 0))));
97 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
98 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
99 ui::ET_KEY_PRESSED, ui::VKEY_F8, ui::DomCode::F8, 0))));
100 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
101 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
102 ui::ET_KEY_PRESSED, ui::VKEY_F9, ui::DomCode::F9, 0))));
103 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
104 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
105 ui::ET_KEY_PRESSED, ui::VKEY_F10, ui::DomCode::F10, 0))));
106
107 // Shift+Control+Alt+F3 is also an Ash accelerator. Don't reserve it.
108 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
109 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
110 ui::ET_KEY_PRESSED, ui::VKEY_F3, ui::DomCode::F3,
111 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN))));
112 #endif // OS_CHROMEOS
113
114 #if defined(USE_AURA)
115 // Ctrl+n, Ctrl+w are reserved while Ctrl+f is not.
116
117 // The content::NativeWebKeyboardEvent constructor is available only when
118 // USE_AURA is #defined.
119 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
120 IDC_NEW_WINDOW, content::NativeWebKeyboardEvent(ui::KeyEvent(
121 ui::ET_KEY_PRESSED, ui::VKEY_N, ui::DomCode::US_N,
122 ui::EF_CONTROL_DOWN))));
123 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
124 IDC_CLOSE_TAB, content::NativeWebKeyboardEvent(ui::KeyEvent(
125 ui::ET_KEY_PRESSED, ui::VKEY_W, ui::DomCode::US_W,
126 ui::EF_CONTROL_DOWN))));
127 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
128 IDC_FIND, content::NativeWebKeyboardEvent(
129 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_F,
130 ui::DomCode::US_F, ui::EF_CONTROL_DOWN))));
131 #endif // USE_AURA
132 }
133
TEST_F(BrowserCommandControllerTest,IsReservedCommandOrKeyIsApp)134 TEST_F(BrowserCommandControllerTest, IsReservedCommandOrKeyIsApp) {
135 Browser::CreateParams params = Browser::CreateParams::CreateForApp(
136 "app",
137 /*trusted_source=*/true, browser()->window()->GetBounds(), profile(),
138 /*user_gesture=*/true);
139 params.window = browser()->window();
140 set_browser(Browser::Create(params));
141
142 ASSERT_TRUE(browser()->is_type_app());
143
144 // When is_type_app(), no keys are reserved.
145 #if defined(OS_CHROMEOS)
146 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
147 IDC_BACK, content::NativeWebKeyboardEvent(ui::KeyEvent(
148 ui::ET_KEY_PRESSED, ui::VKEY_F1, ui::DomCode::F1, 0))));
149 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
150 IDC_FORWARD, content::NativeWebKeyboardEvent(ui::KeyEvent(
151 ui::ET_KEY_PRESSED, ui::VKEY_F2, ui::DomCode::F2, 0))));
152 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
153 IDC_RELOAD, content::NativeWebKeyboardEvent(ui::KeyEvent(
154 ui::ET_KEY_PRESSED, ui::VKEY_F3, ui::DomCode::F3, 0))));
155 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
156 -1, content::NativeWebKeyboardEvent(ui::KeyEvent(
157 ui::ET_KEY_PRESSED, ui::VKEY_F4, ui::DomCode::F4, 0))));
158 #endif // OS_CHROMEOS
159
160 #if defined(USE_AURA)
161 // The content::NativeWebKeyboardEvent constructor is available only when
162 // USE_AURA is #defined.
163 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
164 IDC_NEW_WINDOW, content::NativeWebKeyboardEvent(ui::KeyEvent(
165 ui::ET_KEY_PRESSED, ui::VKEY_N, ui::DomCode::US_N,
166 ui::EF_CONTROL_DOWN))));
167 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
168 IDC_CLOSE_TAB, content::NativeWebKeyboardEvent(ui::KeyEvent(
169 ui::ET_KEY_PRESSED, ui::VKEY_W, ui::DomCode::US_W,
170 ui::EF_CONTROL_DOWN))));
171 EXPECT_FALSE(browser()->command_controller()->IsReservedCommandOrKey(
172 IDC_FIND, content::NativeWebKeyboardEvent(
173 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_F,
174 ui::DomCode::US_F, ui::EF_CONTROL_DOWN))));
175 #endif // USE_AURA
176 }
177
TEST_P(GuestBrowserCommandControllerTest,IncognitoCommands)178 TEST_P(GuestBrowserCommandControllerTest, IncognitoCommands) {
179 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
180 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS));
181 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_SIGNIN));
182
183 TestingProfile* testprofile = browser()->profile()->AsTestingProfile();
184 EXPECT_TRUE(testprofile);
185 testprofile->SetGuestSession(true);
186 chrome::BrowserCommandController ::
187 UpdateSharedCommandsForIncognitoAvailability(
188 browser()->command_controller(), testprofile);
189 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
190 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS));
191 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_SIGNIN));
192
193 testprofile->SetGuestSession(false);
194 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
195 IncognitoModePrefs::FORCED);
196 chrome::BrowserCommandController ::
197 UpdateSharedCommandsForIncognitoAvailability(
198 browser()->command_controller(), testprofile);
199 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
200 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS));
201 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_SIGNIN));
202 }
203
TEST_F(BrowserCommandControllerTest,AppFullScreen)204 TEST_F(BrowserCommandControllerTest, AppFullScreen) {
205 // Enable for tabbed browser.
206 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN));
207
208 // Enabled for app windows.
209 Browser::CreateParams params = Browser::CreateParams::CreateForApp(
210 "app",
211 /*trusted_source=*/true, browser()->window()->GetBounds(), profile(),
212 /*user_gesture=*/true);
213 params.window = browser()->window();
214 set_browser(Browser::Create(params));
215 ASSERT_TRUE(browser()->is_type_app());
216 browser()->command_controller()->FullscreenStateChanged();
217 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN));
218 }
219
TEST_F(BrowserCommandControllerTest,AvatarAcceleratorEnabledOnDesktop)220 TEST_F(BrowserCommandControllerTest, AvatarAcceleratorEnabledOnDesktop) {
221 if (!profiles::IsMultipleProfilesEnabled())
222 return;
223
224 TestingProfileManager* testing_profile_manager = profile_manager();
225 ProfileManager* profile_manager = testing_profile_manager->profile_manager();
226 chrome::BrowserCommandController command_controller(browser());
227 const CommandUpdater* command_updater = &command_controller;
228
229 bool enabled = true;
230 size_t profiles_count = 1U;
231 #if defined(OS_CHROMEOS)
232 // Chrome OS uses system tray menu to handle multi-profiles.
233 enabled = false;
234 profiles_count = 2U;
235 #endif
236
237 ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles());
238 EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU));
239
240 testing_profile_manager->CreateTestingProfile("p2");
241 profiles_count++;
242 ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles());
243 EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU));
244
245 testing_profile_manager->DeleteTestingProfile("p2");
246 profiles_count--;
247 ASSERT_EQ(profiles_count, profile_manager->GetNumberOfProfiles());
248 EXPECT_EQ(enabled, command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU));
249 }
250
TEST_F(BrowserCommandControllerTest,AvatarMenuAlwaysEnabledInIncognitoMode)251 TEST_F(BrowserCommandControllerTest, AvatarMenuAlwaysEnabledInIncognitoMode) {
252 // Set up a profile with an off the record profile.
253 TestingProfile::Builder normal_builder;
254 std::unique_ptr<TestingProfile> original_profile = normal_builder.Build();
255
256 // Create a new browser based on the off the record profile.
257 Browser::CreateParams profile_params(original_profile->GetPrimaryOTRProfile(),
258 true);
259 std::unique_ptr<Browser> otr_browser(
260 CreateBrowserWithTestWindowForParams(profile_params));
261
262 chrome::BrowserCommandController command_controller(otr_browser.get());
263 const CommandUpdater* command_updater = &command_controller;
264
265 // The avatar menu should be enabled.
266 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU));
267 // The command line is reset at the end of every test by the test suite.
268 }
269
270 //////////////////////////////////////////////////////////////////////////////
271 class BrowserCommandControllerFullscreenTest;
272
273 // A test browser window that can toggle fullscreen state.
274 class FullscreenTestBrowserWindow : public TestBrowserWindow,
275 ExclusiveAccessContext {
276 public:
FullscreenTestBrowserWindow(BrowserCommandControllerFullscreenTest * test_browser)277 FullscreenTestBrowserWindow(
278 BrowserCommandControllerFullscreenTest* test_browser)
279 : fullscreen_(false),
280 toolbar_showing_(false),
281 test_browser_(test_browser) {}
282
~FullscreenTestBrowserWindow()283 ~FullscreenTestBrowserWindow() override {}
284
285 // TestBrowserWindow overrides:
ShouldHideUIForFullscreen() const286 bool ShouldHideUIForFullscreen() const override { return fullscreen_; }
IsFullscreen() const287 bool IsFullscreen() const override { return fullscreen_; }
EnterFullscreen(const GURL & url,ExclusiveAccessBubbleType type,int64_t display_id)288 void EnterFullscreen(const GURL& url,
289 ExclusiveAccessBubbleType type,
290 int64_t display_id) override {
291 fullscreen_ = true;
292 }
ExitFullscreen()293 void ExitFullscreen() override { fullscreen_ = false; }
IsToolbarShowing() const294 bool IsToolbarShowing() const override { return toolbar_showing_; }
295
GetExclusiveAccessContext()296 ExclusiveAccessContext* GetExclusiveAccessContext() override { return this; }
297
298 // Exclusive access interface:
299 Profile* GetProfile() override;
300 content::WebContents* GetActiveWebContents() override;
UpdateExclusiveAccessExitBubbleContent(const GURL & url,ExclusiveAccessBubbleType bubble_type,ExclusiveAccessBubbleHideCallback bubble_first_hide_callback,bool force_update)301 void UpdateExclusiveAccessExitBubbleContent(
302 const GURL& url,
303 ExclusiveAccessBubbleType bubble_type,
304 ExclusiveAccessBubbleHideCallback bubble_first_hide_callback,
305 bool force_update) override {}
OnExclusiveAccessUserInput()306 void OnExclusiveAccessUserInput() override {}
CanUserExitFullscreen() const307 bool CanUserExitFullscreen() const override { return true; }
308
set_toolbar_showing(bool showing)309 void set_toolbar_showing(bool showing) { toolbar_showing_ = showing; }
310
311 private:
312 bool fullscreen_;
313 bool toolbar_showing_;
314 BrowserCommandControllerFullscreenTest* test_browser_;
315
316 DISALLOW_COPY_AND_ASSIGN(FullscreenTestBrowserWindow);
317 };
318
319 // Test that uses FullscreenTestBrowserWindow for its window.
320 class BrowserCommandControllerFullscreenTest
321 : public BrowserWithTestWindowTest,
322 public testing::WithParamInterface<bool> {
323 public:
BrowserCommandControllerFullscreenTest()324 BrowserCommandControllerFullscreenTest() {
325 TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles(
326 scoped_feature_list_, GetParam());
327 }
328 ~BrowserCommandControllerFullscreenTest() override = default;
329
GetBrowser()330 Browser* GetBrowser() { return BrowserWithTestWindowTest::browser(); }
331
332 // BrowserWithTestWindowTest overrides:
CreateBrowserWindow()333 std::unique_ptr<BrowserWindow> CreateBrowserWindow() override {
334 return std::make_unique<FullscreenTestBrowserWindow>(this);
335 }
336
337 private:
338 base::test::ScopedFeatureList scoped_feature_list_;
339 DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerFullscreenTest);
340 };
341
GetProfile()342 Profile* FullscreenTestBrowserWindow::GetProfile() {
343 return test_browser_->GetBrowser()->profile();
344 }
345
GetActiveWebContents()346 content::WebContents* FullscreenTestBrowserWindow::GetActiveWebContents() {
347 return test_browser_->GetBrowser()->tab_strip_model()->GetActiveWebContents();
348 }
349
TEST_P(BrowserCommandControllerFullscreenTest,UpdateCommandsForFullscreenMode)350 TEST_P(BrowserCommandControllerFullscreenTest,
351 UpdateCommandsForFullscreenMode) {
352 struct {
353 int command_id;
354 // Whether the command is enabled in tab mode.
355 bool enabled_in_tab;
356 // Whether the keyboard shortcut is reserved in tab mode.
357 bool reserved_in_tab;
358 // Whether the command is enabled in fullscreen mode.
359 bool enabled_in_fullscreen;
360 // Whether the keyboard shortcut is reserved in fullscreen mode.
361 bool reserved_in_fullscreen;
362 } commands[] = {
363 // 1. Most commands are disabled in fullscreen.
364 // 2. In fullscreen, only the exit fullscreen commands are reserved. All
365 // other shortcuts should be delivered to the web page. See
366 // http://crbug.com/680809.
367
368 // Command ID | tab mode | fullscreen |
369 // | enabled | reserved | enabled | reserved |
370 // clang-format off
371 { IDC_OPEN_CURRENT_URL, true, false, false, false },
372 { IDC_FOCUS_TOOLBAR, true, false, false, false },
373 { IDC_FOCUS_LOCATION, true, false, false, false },
374 { IDC_FOCUS_SEARCH, true, false, false, false },
375 { IDC_FOCUS_MENU_BAR, true, false, false, false },
376 { IDC_FOCUS_NEXT_PANE, true, false, false, false },
377 { IDC_FOCUS_PREVIOUS_PANE, true, false, false, false },
378 { IDC_FOCUS_BOOKMARKS, true, false, false, false },
379 { IDC_DEVELOPER_MENU, true, false, false, false },
380 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
381 { IDC_FEEDBACK, true, false, false, false },
382 #endif
383 { IDC_OPTIONS, true, false, false, false },
384 { IDC_IMPORT_SETTINGS, true, false, false, false },
385 { IDC_EDIT_SEARCH_ENGINES, true, false, false, false },
386 { IDC_VIEW_PASSWORDS, true, false, false, false },
387 { IDC_ABOUT, true, false, false, false },
388 { IDC_SHOW_APP_MENU, true, false, false, false },
389 { IDC_SEND_TAB_TO_SELF, true, false, false, false },
390 { IDC_SEND_TAB_TO_SELF_SINGLE_TARGET,
391 true, false, false, false },
392 { IDC_FULLSCREEN, true, false, true, true },
393 { IDC_CLOSE_TAB, true, true, true, false },
394 { IDC_CLOSE_WINDOW, true, true, true, false },
395 { IDC_NEW_INCOGNITO_WINDOW, true, true, true, false },
396 { IDC_NEW_TAB, true, true, true, false },
397 { IDC_NEW_WINDOW, true, true, true, false },
398 { IDC_SELECT_NEXT_TAB, true, true, true, false },
399 { IDC_SELECT_PREVIOUS_TAB, true, true, true, false },
400 { IDC_EXIT, true, true, true, true },
401 { IDC_SHOW_AS_TAB, false, false, false, false },
402 { IDC_SHOW_SIGNIN, true, false, true, false },
403 // clang-format on
404 };
405 const content::NativeWebKeyboardEvent key_event(
406 blink::WebInputEvent::Type::kUndefined, 0,
407 blink::WebInputEvent::GetStaticTimeStampForTests());
408 // Defaults for a tabbed browser.
409 for (size_t i = 0; i < base::size(commands); i++) {
410 SCOPED_TRACE(commands[i].command_id);
411 EXPECT_EQ(chrome::IsCommandEnabled(browser(), commands[i].command_id),
412 commands[i].enabled_in_tab);
413 EXPECT_EQ(browser()->command_controller()->IsReservedCommandOrKey(
414 commands[i].command_id, key_event),
415 commands[i].reserved_in_tab);
416 }
417
418 // Simulate going fullscreen.
419 chrome::ToggleFullscreenMode(browser());
420 ASSERT_TRUE(browser()->window()->IsFullscreen());
421 browser()->command_controller()->FullscreenStateChanged();
422
423 // By default, in fullscreen mode, the toolbar should be hidden; and all
424 // platforms behave similarly.
425 EXPECT_FALSE(window()->IsToolbarShowing());
426 for (size_t i = 0; i < base::size(commands); i++) {
427 SCOPED_TRACE(commands[i].command_id);
428 EXPECT_EQ(chrome::IsCommandEnabled(browser(), commands[i].command_id),
429 commands[i].enabled_in_fullscreen);
430 EXPECT_EQ(browser()->command_controller()->IsReservedCommandOrKey(
431 commands[i].command_id, key_event),
432 commands[i].reserved_in_fullscreen);
433 }
434
435 #if defined(OS_MAC)
436 // When the toolbar is showing, commands should be reserved as if the content
437 // were in a tab; IDC_FULLSCREEN should also be reserved.
438 static_cast<FullscreenTestBrowserWindow*>(window())->set_toolbar_showing(
439 true);
440 EXPECT_TRUE(browser()->command_controller()->IsReservedCommandOrKey(
441 IDC_FULLSCREEN, key_event));
442 for (size_t i = 0; i < base::size(commands); i++) {
443 if (commands[i].command_id != IDC_FULLSCREEN) {
444 SCOPED_TRACE(commands[i].command_id);
445 EXPECT_EQ(browser()->command_controller()->IsReservedCommandOrKey(
446 commands[i].command_id, key_event),
447 commands[i].reserved_in_tab);
448 }
449 }
450 // Return to default state.
451 static_cast<FullscreenTestBrowserWindow*>(window())->set_toolbar_showing(
452 false);
453 #endif
454
455 // Exit fullscreen.
456 chrome::ToggleFullscreenMode(browser());
457 ASSERT_FALSE(browser()->window()->IsFullscreen());
458 browser()->command_controller()->FullscreenStateChanged();
459
460 for (size_t i = 0; i < base::size(commands); i++) {
461 SCOPED_TRACE(commands[i].command_id);
462 EXPECT_EQ(chrome::IsCommandEnabled(browser(), commands[i].command_id),
463 commands[i].enabled_in_tab);
464 EXPECT_EQ(browser()->command_controller()->IsReservedCommandOrKey(
465 commands[i].command_id, key_event),
466 commands[i].reserved_in_tab);
467 }
468
469 // Guest Profiles disallow some options.
470 TestingProfile* testprofile = browser()->profile()->AsTestingProfile();
471 EXPECT_TRUE(testprofile);
472 testprofile->SetGuestSession(true);
473
474 browser()->command_controller()->FullscreenStateChanged();
475 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
476 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS));
477 }
478
479 INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
480 BrowserCommandControllerFullscreenTest,
481 /*is_ephemeral=*/testing::Bool());
482
483 // Ensure that the logic for enabling IDC_OPTIONS is consistent, regardless of
484 // the order of entering fullscreen and forced incognito modes. See
485 // http://crbug.com/694331.
TEST_P(GuestBrowserCommandControllerTest,OptionsConsistency)486 TEST_P(GuestBrowserCommandControllerTest, OptionsConsistency) {
487 TestingProfile* profile = browser()->profile()->AsTestingProfile();
488 // Setup guest session.
489 profile->SetGuestSession(true);
490 // Setup forced incognito mode.
491 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
492 IncognitoModePrefs::FORCED);
493 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
494 // Enter fullscreen.
495 browser()->command_controller()->FullscreenStateChanged();
496 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
497 // Exit fullscreen
498 browser()->command_controller()->FullscreenStateChanged();
499 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
500 // Reenter incognito mode, this should trigger
501 // UpdateSharedCommandsForIncognitoAvailability() again.
502 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
503 IncognitoModePrefs::DISABLED);
504 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
505 IncognitoModePrefs::FORCED);
506 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS));
507 }
508
TEST_F(BrowserCommandControllerTest,IncognitoModeOnSigninAllowedPrefChange)509 TEST_F(BrowserCommandControllerTest, IncognitoModeOnSigninAllowedPrefChange) {
510 // Set up a profile with an off the record profile.
511 std::unique_ptr<TestingProfile> profile1 = TestingProfile::Builder().Build();
512 Profile* profile2 = profile1->GetPrimaryOTRProfile();
513
514 EXPECT_EQ(profile2->GetOriginalProfile(), profile1.get());
515
516 // Create a new browser based on the off the record profile.
517 Browser::CreateParams profile_params(profile1->GetPrimaryOTRProfile(), true);
518 std::unique_ptr<Browser> browser2(
519 CreateBrowserWithTestWindowForParams(profile_params));
520
521 chrome::BrowserCommandController command_controller(browser2.get());
522 const CommandUpdater* command_updater = &command_controller;
523
524 // Check that the SYNC_SETUP command is updated on preference change.
525 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN));
526 profile1->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
527 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN));
528 }
529
TEST_F(BrowserCommandControllerTest,OnSigninAllowedPrefChange)530 TEST_F(BrowserCommandControllerTest, OnSigninAllowedPrefChange) {
531 chrome::BrowserCommandController command_controller(browser());
532 const CommandUpdater* command_updater = &command_controller;
533
534 // Check that the SYNC_SETUP command is updated on preference change.
535 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN));
536 profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
537 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_SIGNIN));
538 }
539
540 INSTANTIATE_TEST_SUITE_P(AllGuestTypes,
541 GuestBrowserCommandControllerTest,
542 /*is_ephemeral=*/testing::Bool());
543