1 // Copyright 2013 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.
5 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shelf/shelf_types.h"
11 #include "ash/shell.h"
12 #include "ash/test/ash_test_base.h"
13 #include "base/command_line.h"
14 #include "chrome/app/chrome_command_ids.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
17 #include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h"
18 #include "chrome/browser/ui/views/frame/browser_view.h"
19 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
20 #include "chrome/browser/ui/views/frame/top_container_view.h"
21 #include "chrome/browser/ui/views/tabs/tab_strip.h"
22 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
23 #include "ui/aura/window.h"
24 #include "ui/views/controls/webview/webview.h"
26 class ImmersiveModeControllerAshTest
: public TestWithBrowserView
{
28 ImmersiveModeControllerAshTest()
29 : TestWithBrowserView(Browser::TYPE_TABBED
,
30 chrome::HOST_DESKTOP_TYPE_ASH
,
33 ImmersiveModeControllerAshTest(
34 Browser::Type browser_type
,
35 chrome::HostDesktopType host_desktop_type
,
37 : TestWithBrowserView(browser_type
,
41 virtual ~ImmersiveModeControllerAshTest() {}
43 // TestWithBrowserView override:
44 virtual void SetUp() OVERRIDE
{
45 TestWithBrowserView::SetUp();
47 browser()->window()->Show();
49 controller_
= browser_view()->immersive_mode_controller();
50 controller_
->SetupForTest();
53 // Returns the bounds of |view| in widget coordinates.
54 gfx::Rect
GetBoundsInWidget(views::View
* view
) {
55 return view
->ConvertRectToWidget(view
->GetLocalBounds());
58 // Toggle the browser's fullscreen state.
59 void ToggleFullscreen() {
60 // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. The notification
61 // is used to trigger changes in whether the shelf is auto hidden and
62 // whether a "light bar" version of the tab strip is used when the
63 // top-of-window views are hidden.
64 scoped_ptr
<FullscreenNotificationObserver
> waiter(
65 new FullscreenNotificationObserver());
66 chrome::ToggleFullscreenMode(browser());
70 // Set whether the browser is in tab fullscreen.
71 void SetTabFullscreen(bool tab_fullscreen
) {
72 content::WebContents
* web_contents
=
73 browser_view()->GetContentsWebViewForTest()->GetWebContents();
74 scoped_ptr
<FullscreenNotificationObserver
> waiter(
75 new FullscreenNotificationObserver());
76 browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
77 web_contents
, tab_fullscreen
);
81 // Attempt revealing the top-of-window views.
82 void AttemptReveal() {
83 if (!revealed_lock_
.get()) {
84 revealed_lock_
.reset(controller_
->GetRevealedLock(
85 ImmersiveModeControllerAsh::ANIMATE_REVEAL_NO
));
89 // Attempt unrevealing the top-of-window views.
90 void AttemptUnreveal() {
91 revealed_lock_
.reset();
94 ImmersiveModeController
* controller() { return controller_
; }
98 ImmersiveModeController
* controller_
;
100 scoped_ptr
<ImmersiveRevealedLock
> revealed_lock_
;
102 DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshTest
);
105 // Test the layout and visibility of the tabstrip, toolbar and TopContainerView
106 // in immersive fullscreen.
107 TEST_F(ImmersiveModeControllerAshTest
, Layout
) {
108 AddTab(browser(), GURL("about:blank"));
110 TabStrip
* tabstrip
= browser_view()->tabstrip();
111 ToolbarView
* toolbar
= browser_view()->toolbar();
112 views::WebView
* contents_web_view
=
113 browser_view()->GetContentsWebViewForTest();
115 // Immersive fullscreen starts out disabled.
116 ASSERT_FALSE(browser_view()->GetWidget()->IsFullscreen());
117 ASSERT_FALSE(controller()->IsEnabled());
119 // By default, the tabstrip and toolbar should be visible.
120 EXPECT_TRUE(tabstrip
->visible());
121 EXPECT_TRUE(toolbar
->visible());
124 EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen());
125 EXPECT_TRUE(controller()->IsEnabled());
126 EXPECT_FALSE(controller()->IsRevealed());
128 // Entering immersive fullscreen should make the tab strip use the immersive
129 // style and hide the toolbar.
130 EXPECT_TRUE(tabstrip
->visible());
131 EXPECT_TRUE(tabstrip
->IsImmersiveStyle());
132 EXPECT_FALSE(toolbar
->visible());
134 // The tab indicators should be flush with the top of the widget.
135 EXPECT_EQ(0, GetBoundsInWidget(tabstrip
).y());
137 // The web contents should be immediately below the tab indicators.
138 EXPECT_EQ(Tab::GetImmersiveHeight(),
139 GetBoundsInWidget(contents_web_view
).y());
141 // Revealing the top-of-window views should set the tab strip back to the
142 // normal style and show the toolbar.
144 EXPECT_TRUE(controller()->IsRevealed());
145 EXPECT_TRUE(tabstrip
->visible());
146 EXPECT_FALSE(tabstrip
->IsImmersiveStyle());
147 EXPECT_TRUE(toolbar
->visible());
149 // The TopContainerView should be flush with the top edge of the widget. If
150 // it is not flush with the top edge the immersive reveal animation looks
152 EXPECT_EQ(0, GetBoundsInWidget(browser_view()->top_container()).y());
154 // The web contents should be at the same y position as they were when the
155 // top-of-window views were hidden.
156 EXPECT_EQ(Tab::GetImmersiveHeight(),
157 GetBoundsInWidget(contents_web_view
).y());
159 // Repeat the test for when in both immersive fullscreen and tab fullscreen.
160 SetTabFullscreen(true);
161 // Hide and reveal the top-of-window views so that they get relain out.
165 // The tab strip and toolbar should still be visible and the TopContainerView
166 // should still be flush with the top edge of the widget.
167 EXPECT_TRUE(controller()->IsRevealed());
168 EXPECT_TRUE(tabstrip
->visible());
169 EXPECT_FALSE(tabstrip
->IsImmersiveStyle());
170 EXPECT_TRUE(toolbar
->visible());
171 EXPECT_EQ(0, GetBoundsInWidget(browser_view()->top_container()).y());
173 // The web contents should be flush with the top edge of the widget when in
174 // both immersive and tab fullscreen.
175 EXPECT_EQ(0, GetBoundsInWidget(contents_web_view
).y());
177 // Hide the top-of-window views. Both the tab strip and the toolbar should
178 // hide when in both immersive and tab fullscreen.
180 EXPECT_FALSE(controller()->IsRevealed());
181 EXPECT_FALSE(tabstrip
->visible());
182 EXPECT_FALSE(toolbar
->visible());
184 // The web contents should still be flush with the edge of the widget.
185 EXPECT_EQ(0, GetBoundsInWidget(contents_web_view
).y());
187 // Exiting both immersive and tab fullscreen should show the tab strip and
190 EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen());
191 EXPECT_FALSE(controller()->IsEnabled());
192 EXPECT_FALSE(controller()->IsRevealed());
193 EXPECT_TRUE(tabstrip
->visible());
194 EXPECT_FALSE(tabstrip
->IsImmersiveStyle());
195 EXPECT_TRUE(toolbar
->visible());
198 // Test that the browser commands which are usually disabled in fullscreen are
199 // are enabled in immersive fullscreen.
200 TEST_F(ImmersiveModeControllerAshTest
, EnabledCommands
) {
201 ASSERT_FALSE(controller()->IsEnabled());
202 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL
));
203 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT
));
204 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION
));
207 EXPECT_TRUE(controller()->IsEnabled());
208 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL
));
209 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT
));
210 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION
));
213 // Test that restoring a window properly exits immersive fullscreen.
214 TEST_F(ImmersiveModeControllerAshTest
, ExitUponRestore
) {
215 ASSERT_FALSE(controller()->IsEnabled());
218 ASSERT_TRUE(controller()->IsEnabled());
219 ASSERT_TRUE(controller()->IsRevealed());
220 ASSERT_TRUE(browser_view()->GetWidget()->IsFullscreen());
222 browser_view()->GetWidget()->Restore();
223 EXPECT_FALSE(controller()->IsEnabled());
226 // Test how being simultaneously in tab fullscreen and immersive fullscreen
227 // affects the shelf visibility and whether the tab indicators are hidden.
228 TEST_F(ImmersiveModeControllerAshTest
, TabAndBrowserFullscreen
) {
229 AddTab(browser(), GURL("about:blank"));
231 // The shelf should start out as visible.
232 ash::ShelfLayoutManager
* shelf
=
233 ash::Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
234 ASSERT_EQ(ash::SHELF_VISIBLE
, shelf
->visibility_state());
236 // 1) Test that entering tab fullscreen from immersive fullscreen hides the
237 // tab indicators and the shelf.
239 ASSERT_TRUE(controller()->IsEnabled());
240 EXPECT_EQ(ash::SHELF_AUTO_HIDE
, shelf
->visibility_state());
241 EXPECT_FALSE(controller()->ShouldHideTabIndicators());
243 SetTabFullscreen(true);
244 ASSERT_TRUE(controller()->IsEnabled());
245 EXPECT_EQ(ash::SHELF_HIDDEN
, shelf
->visibility_state());
246 EXPECT_TRUE(controller()->ShouldHideTabIndicators());
248 // 2) Test that exiting tab fullscreen shows the tab indicators and autohides
250 SetTabFullscreen(false);
251 ASSERT_TRUE(controller()->IsEnabled());
252 EXPECT_EQ(ash::SHELF_AUTO_HIDE
, shelf
->visibility_state());
253 EXPECT_FALSE(controller()->ShouldHideTabIndicators());
255 // 3) Test that exiting tab fullscreen and immersive fullscreen
256 // simultaneously correctly updates the shelf visibility and whether the tab
257 // indicators should be hidden.
258 SetTabFullscreen(true);
260 ASSERT_FALSE(controller()->IsEnabled());
261 EXPECT_EQ(ash::SHELF_VISIBLE
, shelf
->visibility_state());
262 EXPECT_TRUE(controller()->ShouldHideTabIndicators());
265 class ImmersiveModeControllerAshTestHostedApp
266 : public ImmersiveModeControllerAshTest
{
268 ImmersiveModeControllerAshTestHostedApp()
269 : ImmersiveModeControllerAshTest(Browser::TYPE_POPUP
,
270 chrome::HOST_DESKTOP_TYPE_ASH
,
273 virtual ~ImmersiveModeControllerAshTestHostedApp() {}
276 DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshTestHostedApp
);
279 // Test the layout and visibility of the TopContainerView and web contents when
280 // a hosted app is put into immersive fullscreen.
281 TEST_F(ImmersiveModeControllerAshTestHostedApp
, Layout
) {
282 // Add a tab because the browser starts out without any tabs at all.
283 AddTab(browser(), GURL("about:blank"));
285 TabStrip
* tabstrip
= browser_view()->tabstrip();
286 ToolbarView
* toolbar
= browser_view()->toolbar();
287 views::WebView
* contents_web_view
=
288 browser_view()->GetContentsWebViewForTest();
289 views::View
* top_container
= browser_view()->top_container();
291 // Immersive fullscreen starts out disabled.
292 ASSERT_FALSE(browser_view()->GetWidget()->IsFullscreen());
293 ASSERT_FALSE(controller()->IsEnabled());
295 // The tabstrip and toolbar are not visible for hosted apps.
296 EXPECT_FALSE(tabstrip
->visible());
297 EXPECT_FALSE(toolbar
->visible());
299 // The window header should be above the web contents.
300 int header_height
= GetBoundsInWidget(contents_web_view
).y();
303 EXPECT_TRUE(browser_view()->GetWidget()->IsFullscreen());
304 EXPECT_TRUE(controller()->IsEnabled());
305 EXPECT_FALSE(controller()->IsRevealed());
307 // Entering immersive fullscreen should make the web contents flush with the
308 // top of the widget.
309 EXPECT_FALSE(tabstrip
->visible());
310 EXPECT_FALSE(toolbar
->visible());
311 EXPECT_TRUE(top_container
->GetVisibleBounds().IsEmpty());
312 EXPECT_EQ(0, GetBoundsInWidget(contents_web_view
).y());
314 // Reveal the window header.
317 // The tabstrip and toolbar should still be hidden and the web contents should
318 // still be flush with the top of the screen.
319 EXPECT_FALSE(tabstrip
->visible());
320 EXPECT_FALSE(toolbar
->visible());
321 EXPECT_EQ(0, GetBoundsInWidget(contents_web_view
).y());
323 // During an immersive reveal, the window header should be painted to the
324 // TopContainerView. The TopContainerView should be flush with the top of the
325 // widget and have |header_height|.
326 gfx::Rect
top_container_bounds_in_widget(GetBoundsInWidget(top_container
));
327 EXPECT_EQ(0, top_container_bounds_in_widget
.y());
328 EXPECT_EQ(header_height
, top_container_bounds_in_widget
.height());
330 // Exit immersive fullscreen. The web contents should be back below the window
333 EXPECT_FALSE(browser_view()->GetWidget()->IsFullscreen());
334 EXPECT_FALSE(controller()->IsEnabled());
335 EXPECT_FALSE(tabstrip
->visible());
336 EXPECT_FALSE(toolbar
->visible());
337 EXPECT_EQ(header_height
, GetBoundsInWidget(contents_web_view
).y());