blob: 420a7a081bc05c74043bbfc154e3e2c1ff07d9c7 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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/immersive_mode_controller_ash.h"
#include "ash/frame/caption_buttons/frame_caption_button.h"
#include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
#include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
#include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/macros.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h"
#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
#include "chrome/browser/ui/views/frame/top_container_view.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "ui/aura/client/aura_constants.h"
class ImmersiveModeControllerAshHostedAppBrowserTest
: public InProcessBrowserTest {
public:
ImmersiveModeControllerAshHostedAppBrowserTest() = default;
~ImmersiveModeControllerAshHostedAppBrowserTest() override = default;
// InProcessBrowserTest override:
void SetUpOnMainThread() override {
Browser::CreateParams params = Browser::CreateParams::CreateForApp(
"test_browser_app", true /* trusted_source */, gfx::Rect(),
InProcessBrowserTest::browser()->profile(), true);
browser_ = new Browser(params);
controller_ = browser_view()->immersive_mode_controller();
// Disable animations in immersive fullscreen before we show the window,
// which triggers an animation.
ash::ImmersiveFullscreenControllerTestApi(
static_cast<ImmersiveModeControllerAsh*>(controller_)->controller())
.SetupForTest();
browser_->window()->Show();
}
// Returns the bounds of |view| in widget coordinates.
gfx::Rect GetBoundsInWidget(views::View* view) {
return view->ConvertRectToWidget(view->GetLocalBounds());
}
// Toggle the browser's fullscreen state.
void ToggleFullscreen() {
// NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. The notification
// is used to trigger changes in whether the shelf is auto hidden.
std::unique_ptr<FullscreenNotificationObserver> waiter(
new FullscreenNotificationObserver());
chrome::ToggleFullscreenMode(browser());
waiter->Wait();
}
// Attempt revealing the top-of-window views.
void AttemptReveal() {
if (!revealed_lock_.get()) {
revealed_lock_.reset(controller_->GetRevealedLock(
ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO));
}
}
Browser* browser() { return browser_; }
BrowserView* browser_view() {
return BrowserView::GetBrowserViewForBrowser(browser_);
}
ImmersiveModeController* controller() { return controller_; }
private:
// Not owned.
Browser* browser_;
ImmersiveModeController* controller_;
std::unique_ptr<ImmersiveRevealedLock> revealed_lock_;
DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshHostedAppBrowserTest);
};
// Test the layout and visibility of the TopContainerView and web contents when
// a hosted app is put into immersive fullscreen.
IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerAshHostedAppBrowserTest, Layout) {
TabStrip* tabstrip = browser_view()->tabstrip();
ToolbarView* toolbar = browser_view()->toolbar();
views::WebView* contents_web_view =
browser_view()->GetContentsWebViewForTest();
views::View* top_container = browser_view()->top_container();
// Immersive fullscreen starts out disabled.
ASSERT_FALSE(browser_view()->GetWidget()->IsFullscreen());
ASSERT_FALSE(controller()->IsEnabled());
// The tabstrip and toolbar are not visible for hosted apps.
EXPECT_FALSE(tabstrip->visible());
EXPECT_FALSE(toolbar->visible());
// The window header should be above the web contents.
int header_height = GetBoundsInWidget(contents_web_view).y();
ToggleFullscreen();
EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen());
EXPECT_TRUE(controller()->IsEnabled());
EXPECT_FALSE(controller()->IsRevealed());
// Entering immersive fullscreen should make the web contents flush with the
// top of the widget. The popup browser type doesn't support tabstrip and
// toolbar feature, thus invisible.
EXPECT_FALSE(tabstrip->visible());
EXPECT_FALSE(toolbar->visible());
EXPECT_TRUE(top_container->GetVisibleBounds().IsEmpty());
EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
// Reveal the window header.
AttemptReveal();
// The tabstrip and toolbar should still be hidden and the web contents should
// still be flush with the top of the screen.
EXPECT_FALSE(tabstrip->visible());
EXPECT_FALSE(toolbar->visible());
EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
// During an immersive reveal, the window header should be painted to the
// TopContainerView. The TopContainerView should be flush with the top of the
// widget and have |header_height|.
gfx::Rect top_container_bounds_in_widget(GetBoundsInWidget(top_container));
EXPECT_EQ(0, top_container_bounds_in_widget.y());
EXPECT_EQ(header_height, top_container_bounds_in_widget.height());
// Exit immersive fullscreen. The web contents should be back below the window
// header.
ToggleFullscreen();
EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen());
EXPECT_FALSE(controller()->IsEnabled());
EXPECT_FALSE(tabstrip->visible());
EXPECT_FALSE(toolbar->visible());
EXPECT_EQ(header_height, GetBoundsInWidget(contents_web_view).y());
}
// Verify the immersive mode status is as expected in tablet mode (titlebars are
// autohidden in tablet mode).
IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerAshHostedAppBrowserTest,
ImmersiveModeStatusTabletMode) {
ASSERT_FALSE(controller()->IsEnabled());
aura::Window* window =
browser_view()->frame()->GetFrameView()->frame()->GetNativeWindow();
// Verify that after entering tablet mode, immersive mode is enabled, and the
// the associated window's top inset is 0 (the top of the window is not
// visible).
ash::TabletModeController* tablet_mode_controller =
ash::Shell::Get()->tablet_mode_controller();
tablet_mode_controller->EnableTabletModeWindowManager(true);
tablet_mode_controller->FlushForTesting();
EXPECT_TRUE(controller()->IsEnabled());
EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset));
// Verify that after minimizing, immersive mode is disabled.
browser()->window()->Minimize();
EXPECT_FALSE(controller()->IsEnabled());
// Verify that after showing the browser, immersive mode is reenabled.
browser()->window()->Show();
tablet_mode_controller->FlushForTesting();
EXPECT_TRUE(controller()->IsEnabled());
// Verify that immersive mode remains if fullscreen is toggled while in tablet
// mode.
ToggleFullscreen();
EXPECT_TRUE(controller()->IsEnabled());
tablet_mode_controller->EnableTabletModeWindowManager(false);
tablet_mode_controller->FlushForTesting();
EXPECT_TRUE(controller()->IsEnabled());
// Verify that immersive mode remains if the browser was fullscreened when
// entering tablet mode.
tablet_mode_controller->EnableTabletModeWindowManager(true);
tablet_mode_controller->FlushForTesting();
EXPECT_TRUE(controller()->IsEnabled());
// Verify that if the browser is not fullscreened, upon exiting tablet mode,
// immersive mode is not enabled, and the associated window's top inset is
// greater than 0 (the top of the window is visible).
ToggleFullscreen();
EXPECT_TRUE(controller()->IsEnabled());
tablet_mode_controller->EnableTabletModeWindowManager(false);
tablet_mode_controller->FlushForTesting();
EXPECT_FALSE(controller()->IsEnabled());
EXPECT_GT(window->GetProperty(aura::client::kTopViewInset), 0);
}
// Verify that the frame layout is as expected when using immersive mode in
// tablet mode.
IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerAshHostedAppBrowserTest,
FrameLayout) {
ASSERT_FALSE(controller()->IsEnabled());
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
// We know we're using Ash, so static cast.
BrowserNonClientFrameViewAsh* frame_view =
static_cast<BrowserNonClientFrameViewAsh*>(
browser_view->GetWidget()->non_client_view()->frame_view());
ash::FrameCaptionButtonContainerView* caption_button_container =
frame_view->caption_button_container_;
ash::FrameCaptionButtonContainerView::TestApi frame_test_api(
caption_button_container);
EXPECT_TRUE(frame_test_api.size_button()->visible());
// Verify the size button is hidden in tablet mode.
ash::TabletModeController* tablet_mode_controller =
ash::Shell::Get()->tablet_mode_controller();
tablet_mode_controller->EnableTabletModeWindowManager(true);
tablet_mode_controller->FlushForTesting();
frame_test_api.EndAnimations();
EXPECT_FALSE(frame_test_api.size_button()->visible());
// Verify the size button is visible in clamshell mode, and that it does not
// cover the other two buttons.
tablet_mode_controller->EnableTabletModeWindowManager(false);
tablet_mode_controller->FlushForTesting();
frame_test_api.EndAnimations();
EXPECT_TRUE(frame_test_api.size_button()->visible());
EXPECT_FALSE(frame_test_api.size_button()->GetBoundsInScreen().Intersects(
frame_test_api.close_button()->GetBoundsInScreen()));
EXPECT_FALSE(frame_test_api.size_button()->GetBoundsInScreen().Intersects(
frame_test_api.minimize_button()->GetBoundsInScreen()));
}