blob: b6e62abef7d9ad3cc2a11111b18e06ef0d4e9744 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_navigation_observer.h"
#include "ui/views/buildflags.h"
#include "ui/views/test/ax_event_counter.h"
#if BUILDFLAG(IS_MAC)
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_commands_mac.h"
#include "chrome/test/base/interactive_test_utils.h"
#endif
using views::FocusManager;
namespace {
class BrowserViewTest : public InProcessBrowserTest {
public:
BrowserViewTest() : ax_observer_(views::AXEventManager::Get()) {}
~BrowserViewTest() override = default;
BrowserViewTest(const BrowserViewTest&) = delete;
BrowserViewTest& operator=(const BrowserViewTest&) = delete;
void SetUpOnMainThread() override {
#if BUILDFLAG(IS_MAC)
// Set the preference to true so we expect to see the top view in
// fullscreen mode.
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetBoolean(prefs::kShowFullscreenToolbar, true);
// Ensure that the browser window is activated. BrowserView::Show calls
// into BridgedNativeWidgetImpl::SetVisibilityState and makeKeyAndOrderFront
// there somehow does not change the window's key status on bot.
ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
#endif
}
protected:
views::test::AXEventCounter ax_observer_;
};
} // namespace
IN_PROC_BROWSER_TEST_F(BrowserViewTest, FullscreenClearsFocus) {
BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
LocationBarView* location_bar_view = browser_view->GetLocationBarView();
FocusManager* focus_manager = browser_view->GetFocusManager();
// Focus starts in the location bar or one of its children.
EXPECT_TRUE(location_bar_view->Contains(focus_manager->GetFocusedView()));
FullscreenNotificationObserver fullscreen_observer(browser());
// Enter into fullscreen mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
EXPECT_TRUE(browser_view->IsFullscreen());
// Focus is released from the location bar.
EXPECT_FALSE(location_bar_view->Contains(focus_manager->GetFocusedView()));
}
// Test whether the top view including toolbar and tab strip shows up or hides
// correctly in browser fullscreen mode.
IN_PROC_BROWSER_TEST_F(BrowserViewTest, BrowserFullscreenShowTopView) {
BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
// The top view should always show up in regular mode.
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->GetTabStripVisible());
{
FullscreenNotificationObserver fullscreen_observer(browser());
// Enter into fullscreen mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
EXPECT_TRUE(browser_view->IsFullscreen());
bool top_view_in_browser_fullscreen = false;
#if BUILDFLAG(IS_MAC)
// The top view should show up by default.
EXPECT_TRUE(browser_view->GetTabStripVisible());
// The 'Always Show Bookmarks Bar' should be enabled.
EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR));
{
FullscreenNotificationObserver fullscreen_observer(browser());
// Return back to normal mode and toggle to not show the top view in full
// screen mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
EXPECT_FALSE(browser_view->IsFullscreen());
chrome::ToggleFullscreenToolbar(browser());
{
FullscreenNotificationObserver fullscreen_observer(browser());
// While back to fullscreen mode, the top view no longer shows up.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
EXPECT_TRUE(browser_view->IsFullscreen());
EXPECT_FALSE(browser_view->GetTabStripVisible());
// The 'Always Show Bookmarks Bar' should be disabled.
EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR));
// Test toggling toolbar while being in fullscreen mode.
chrome::ToggleFullscreenToolbar(browser());
EXPECT_TRUE(browser_view->IsFullscreen());
top_view_in_browser_fullscreen = true;
#else
// In immersive fullscreen mode, the top view should show up; otherwise, it
// always hides.
if (browser_view->immersive_mode_controller()->IsEnabled())
top_view_in_browser_fullscreen = true;
#endif
EXPECT_EQ(top_view_in_browser_fullscreen, browser_view->GetTabStripVisible());
// The 'Always Show Bookmarks Bar' should be enabled if top view is shown.
EXPECT_EQ(top_view_in_browser_fullscreen,
chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR));
// Enter into tab fullscreen mode from browser fullscreen mode.
FullscreenController* controller =
browser()->exclusive_access_manager()->fullscreen_controller();
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
controller->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame());
EXPECT_TRUE(browser_view->IsFullscreen());
bool top_view_in_tab_fullscreen =
browser_view->immersive_mode_controller()->IsEnabled() ? true : false;
EXPECT_EQ(top_view_in_tab_fullscreen, browser_view->GetTabStripVisible());
// The 'Always Show Bookmarks Bar' should be disabled in tab fullscreen mode.
EXPECT_EQ(top_view_in_tab_fullscreen,
chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR));
// Return back to browser fullscreen mode.
content::NativeWebKeyboardEvent event(
blink::WebInputEvent::Type::kKeyDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
event.windows_key_code = ui::VKEY_ESCAPE;
browser()->exclusive_access_manager()->HandleUserKeyEvent(event);
EXPECT_TRUE(browser_view->IsFullscreen());
EXPECT_EQ(top_view_in_browser_fullscreen, browser_view->GetTabStripVisible());
// This makes sure that the layout was updated accordingly.
EXPECT_EQ(top_view_in_browser_fullscreen,
browser_view->tabstrip()->GetVisible());
EXPECT_EQ(top_view_in_browser_fullscreen,
chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR));
// Adding `FullscreenNotificationObserver` will make the TESTs on Lacros fail
// determinately, which should have been a no-op.
// TODO(crbug.com/1351971): Repair this defect.
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
{
FullscreenNotificationObserver fullscreen_observer(browser());
// Return to regular mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
#else
// Return to regular mode.
chrome::ToggleFullscreenMode(browser());
#endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->GetTabStripVisible());
}
// Test whether the top view including toolbar and tab strip appears or hides
// correctly in tab fullscreen mode.
IN_PROC_BROWSER_TEST_F(BrowserViewTest, TabFullscreenShowTopView) {
BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
// The top view should always show up in regular mode.
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->GetTabStripVisible());
// Enter into tab fullscreen mode.
FullscreenController* controller =
browser()->exclusive_access_manager()->fullscreen_controller();
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
controller->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame());
EXPECT_TRUE(browser_view->IsFullscreen());
// The top view should not show up.
EXPECT_FALSE(browser_view->GetTabStripVisible());
// After exiting the fullscreen mode, the top view should show up again.
controller->ExitFullscreenModeForTab(web_contents);
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->GetTabStripVisible());
}
// Test whether bookmark bar shows up or hides correctly for fullscreen modes.
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_FullscreenShowBookmarkBar DISABLED_FullscreenShowBookmarkBar
#else
#define MAYBE_FullscreenShowBookmarkBar FullscreenShowBookmarkBar
#endif
IN_PROC_BROWSER_TEST_F(BrowserViewTest, MAYBE_FullscreenShowBookmarkBar) {
BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
// If the bookmark bar is not showing, enable showing it so that we can check
// its state.
if (!browser_view->IsBookmarkBarVisible())
chrome::ToggleBookmarkBar(browser());
#if BUILDFLAG(IS_MAC)
// Disable showing toolbar in fullscreen mode to make its behavior similar to
// other platforms.
chrome::ToggleFullscreenToolbar(browser());
#endif
ASSERT_TRUE(AddTabAtIndex(0, GURL("about:blank"), ui::PAGE_TRANSITION_TYPED));
// Now the bookmark bar should show up in regular mode.
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->IsBookmarkBarVisible());
{
FullscreenNotificationObserver fullscreen_observer(browser());
// Enter into fullscreen mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
EXPECT_TRUE(browser_view->IsFullscreen());
if (browser_view->immersive_mode_controller()->IsEnabled())
EXPECT_TRUE(browser_view->IsBookmarkBarVisible());
else
EXPECT_FALSE(browser_view->IsBookmarkBarVisible());
#if BUILDFLAG(IS_MAC)
// Test toggling toolbar state in fullscreen mode would also affect bookmark
// bar state.
chrome::ToggleFullscreenToolbar(browser());
EXPECT_TRUE(browser_view->GetTabStripVisible());
EXPECT_TRUE(browser_view->IsBookmarkBarVisible());
chrome::ToggleFullscreenToolbar(browser());
EXPECT_FALSE(browser_view->GetTabStripVisible());
EXPECT_FALSE(browser_view->IsBookmarkBarVisible());
#endif
// Adding `FullscreenNotificationObserver` will make the TESTs on Lacros fail
// determinately, which should have been a no-op.
// TODO(crbug.com/1351971): Repair this defect.
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
{
FullscreenNotificationObserver fullscreen_observer(browser());
// Exit from fullscreen mode.
chrome::ToggleFullscreenMode(browser());
fullscreen_observer.Wait();
}
#else
// Exit from fullscreen mode.
chrome::ToggleFullscreenMode(browser());
#endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
EXPECT_FALSE(browser_view->IsFullscreen());
EXPECT_TRUE(browser_view->GetTabStripVisible());
EXPECT_TRUE(browser_view->IsBookmarkBarVisible());
}
// TODO(crbug.com/897177): Only Aura platforms use the WindowActivated
// accessibility event. We need to harmonize the firing of accessibility events
// between platforms.
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
IN_PROC_BROWSER_TEST_F(BrowserViewTest, WindowActivatedAccessibleEvent) {
// Wait for window activated event from the first browser window.
// This event is asynchronous, it is emitted as a response to a system window
// event. It is possible that we haven't received it yet when we run this test
// and we need to explicitly wait for it.
if (ax_observer_.GetCount(ax::mojom::Event::kWindowActivated) == 0)
ax_observer_.WaitForEvent(ax::mojom::Event::kWindowActivated);
ASSERT_EQ(1, ax_observer_.GetCount(ax::mojom::Event::kWindowActivated));
// Create a new browser window and wait for event again.
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::NEW_WINDOW,
ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER);
if (ax_observer_.GetCount(ax::mojom::Event::kWindowActivated) == 1)
ax_observer_.WaitForEvent(ax::mojom::Event::kWindowActivated);
ASSERT_EQ(2, ax_observer_.GetCount(ax::mojom::Event::kWindowActivated));
}
#endif
// Class for BrowserView unit tests for the loading animation feature.
// Creates a Browser with a |features_list| where
// kStopLoadingAnimationForHiddenWindow is enabled before setting GPU thread.
class BrowserViewTestWithStopLoadingAnimationForHiddenWindow
: public BrowserViewTest {
public:
BrowserViewTestWithStopLoadingAnimationForHiddenWindow() {
feature_list_.InitAndEnableFeature(
features::kStopLoadingAnimationForHiddenWindow);
}
BrowserViewTestWithStopLoadingAnimationForHiddenWindow(
const BrowserViewTestWithStopLoadingAnimationForHiddenWindow&) = delete;
BrowserViewTestWithStopLoadingAnimationForHiddenWindow& operator=(
const BrowserViewTestWithStopLoadingAnimationForHiddenWindow&) = delete;
protected:
BrowserView* browser_view() {
return BrowserView::GetBrowserViewForBrowser(browser());
}
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(BrowserViewTestWithStopLoadingAnimationForHiddenWindow,
LoadingAnimationChangeOnMinimizeAndRestore) {
auto* contents = browser()->tab_strip_model()->GetActiveWebContents();
content::TestNavigationObserver navigation_watcher(
contents, 1, content::MessageLoopRunner::QuitMode::DEFERRED);
// Navigate without blocking.
const GURL test_url = ui_test_utils::GetTestUrl(
base::FilePath(base::FilePath::kCurrentDirectory),
base::FilePath(FILE_PATH_LITERAL("title2.html")));
contents->GetController().LoadURL(test_url, content::Referrer(),
ui::PAGE_TRANSITION_LINK, std::string());
{
base::RunLoop run_loop;
browser_view()->SetLoadingAnimationStateChangeClosureForTesting(
run_loop.QuitClosure());
// Loading animation is not rendered when browser view is minimized.
browser_view()->Minimize();
run_loop.Run();
}
EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
EXPECT_FALSE(browser_view()->IsLoadingAnimationRunningForTesting());
{
base::RunLoop run_loop;
browser_view()->SetLoadingAnimationStateChangeClosureForTesting(
run_loop.QuitClosure());
// Loading animation is rendered when browser view is restored.
browser_view()->Restore();
run_loop.Run();
}
EXPECT_TRUE(browser()->tab_strip_model()->TabsAreLoading());
EXPECT_TRUE(browser_view()->IsLoadingAnimationRunningForTesting());
// Now block for the navigation to complete.
navigation_watcher.Wait();
EXPECT_FALSE(browser()->tab_strip_model()->TabsAreLoading());
}