browser_non_client_frame_view_ash_browsertest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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/views/frame/browser_non_client_frame_view_ash.h"
6
7#include "ash/ash_constants.h"
8#include "ash/ash_switches.h"
9#include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
10#include "ash/frame/header_painter.h"
11#include "ash/shell.h"
12#include "ash/wm/maximize_mode/maximize_mode_controller.h"
13#include "base/command_line.h"
14#include "chrome/browser/ui/browser.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/immersive_mode_controller.h"
20#include "chrome/browser/ui/views/tabs/tab.h"
21#include "chrome/test/base/in_process_browser_test.h"
22#include "ui/base/hit_test.h"
23#include "ui/compositor/scoped_animation_duration_scale_mode.h"
24#include "ui/views/widget/widget.h"
25
26using views::Widget;
27
28namespace {
29
30class BrowserNonClientFrameViewAshTest : public InProcessBrowserTest {
31 public:
32  BrowserNonClientFrameViewAshTest() {}
33  virtual ~BrowserNonClientFrameViewAshTest() {}
34
35  // InProcessBrowserTest:
36  virtual void SetUp() OVERRIDE;
37  virtual void TearDown() OVERRIDE;
38
39 private:
40  scoped_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
41  DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAshTest);
42};
43
44void BrowserNonClientFrameViewAshTest::SetUp() {
45  zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode(
46      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
47  InProcessBrowserTest::SetUp();
48}
49
50void BrowserNonClientFrameViewAshTest::TearDown() {
51  zero_duration_mode_.reset();
52  InProcessBrowserTest::TearDown();
53}
54
55}  // namespace
56
57IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, NonClientHitTest) {
58  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
59  Widget* widget = browser_view->GetWidget();
60  // We know we're using Ash, so static cast.
61  BrowserNonClientFrameViewAsh* frame_view =
62      static_cast<BrowserNonClientFrameViewAsh*>(
63          widget->non_client_view()->frame_view());
64
65  // Click on the top edge of a restored window hits the top edge resize handle.
66  const int kWindowWidth = 300;
67  const int kWindowHeight = 290;
68  widget->SetBounds(gfx::Rect(10, 10, kWindowWidth, kWindowHeight));
69  gfx::Point top_edge(kWindowWidth / 2, 0);
70  EXPECT_EQ(HTTOP, frame_view->NonClientHitTest(top_edge));
71
72  // Click just below the resize handle hits the caption.
73  gfx::Point below_resize(kWindowWidth / 2, ash::kResizeInsideBoundsSize);
74  EXPECT_EQ(HTCAPTION, frame_view->NonClientHitTest(below_resize));
75
76  // Click in the top edge of a maximized window now hits the client area,
77  // because we want it to fall through to the tab strip and select a tab.
78  widget->Maximize();
79  EXPECT_EQ(HTCLIENT, frame_view->NonClientHitTest(top_edge));
80}
81
82// Test that the frame view does not do any painting in non-immersive
83// fullscreen.
84IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest,
85                       NonImmersiveFullscreen) {
86  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
87  content::WebContents* web_contents = browser_view->GetActiveWebContents();
88  Widget* widget = browser_view->GetWidget();
89  // We know we're using Ash, so static cast.
90  BrowserNonClientFrameViewAsh* frame_view =
91      static_cast<BrowserNonClientFrameViewAsh*>(
92          widget->non_client_view()->frame_view());
93
94  // Frame paints by default.
95  EXPECT_TRUE(frame_view->ShouldPaint());
96
97  // No painting should occur in non-immersive fullscreen. (We enter into tab
98  // fullscreen here because tab fullscreen is non-immersive even on ChromeOS).
99  {
100    // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously.
101    scoped_ptr<FullscreenNotificationObserver> waiter(
102        new FullscreenNotificationObserver());
103    browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
104        web_contents, true);
105    waiter->Wait();
106  }
107  EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled());
108  EXPECT_FALSE(frame_view->ShouldPaint());
109
110  // The client view abuts top of the window.
111  EXPECT_EQ(0, frame_view->GetBoundsForClientView().y());
112
113  // The frame should be painted again when fullscreen is exited and the caption
114  // buttons should be visible.
115  {
116    scoped_ptr<FullscreenNotificationObserver> waiter(
117        new FullscreenNotificationObserver());
118    chrome::ToggleFullscreenMode(browser());
119    waiter->Wait();
120  }
121  EXPECT_TRUE(frame_view->ShouldPaint());
122  EXPECT_TRUE(frame_view->caption_button_container_->visible());
123}
124
125// TODO(zturner): Change this to USE_ASH after fixing the test on Windows.
126#if defined(OS_CHROMEOS)
127IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) {
128  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
129  content::WebContents* web_contents = browser_view->GetActiveWebContents();
130  Widget* widget = browser_view->GetWidget();
131  // We know we're using Ash, so static cast.
132  BrowserNonClientFrameViewAsh* frame_view =
133      static_cast<BrowserNonClientFrameViewAsh*>(
134          widget->non_client_view()->frame_view());
135
136  ImmersiveModeController* immersive_mode_controller =
137      browser_view->immersive_mode_controller();
138  immersive_mode_controller->SetupForTest();
139
140  // Immersive fullscreen starts disabled.
141  ASSERT_FALSE(widget->IsFullscreen());
142  EXPECT_FALSE(immersive_mode_controller->IsEnabled());
143
144  // Frame paints by default.
145  EXPECT_TRUE(frame_view->ShouldPaint());
146  EXPECT_LT(Tab::GetImmersiveHeight(),
147            frame_view->header_painter_->GetHeaderHeightForPainting());
148
149  // Enter both browser fullscreen and tab fullscreen. Entering browser
150  // fullscreen should enable immersive fullscreen.
151  {
152    // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously.
153    scoped_ptr<FullscreenNotificationObserver> waiter(
154        new FullscreenNotificationObserver());
155    chrome::ToggleFullscreenMode(browser());
156    waiter->Wait();
157  }
158  {
159    scoped_ptr<FullscreenNotificationObserver> waiter(
160        new FullscreenNotificationObserver());
161    browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
162        web_contents, true);
163    waiter->Wait();
164  }
165  EXPECT_TRUE(immersive_mode_controller->IsEnabled());
166
167  // An immersive reveal shows the buttons and the top of the frame.
168  scoped_ptr<ImmersiveRevealedLock> revealed_lock(
169      immersive_mode_controller->GetRevealedLock(
170          ImmersiveModeController::ANIMATE_REVEAL_NO));
171  EXPECT_TRUE(immersive_mode_controller->IsRevealed());
172  EXPECT_TRUE(frame_view->ShouldPaint());
173  EXPECT_TRUE(frame_view->caption_button_container_->visible());
174  EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle());
175
176  // End the reveal. When in both immersive browser fullscreen and tab
177  // fullscreen, the tab lightbars should not be painted.
178  revealed_lock.reset();
179  EXPECT_FALSE(immersive_mode_controller->IsRevealed());
180  EXPECT_FALSE(frame_view->ShouldPaint());
181  EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting());
182
183  // Repeat test but without tab fullscreen. The tab lightbars should now show
184  // when the top-of-window views are not revealed.
185  {
186    scoped_ptr<FullscreenNotificationObserver> waiter(
187        new FullscreenNotificationObserver());
188    browser()->fullscreen_controller()->ToggleFullscreenModeForTab(
189        web_contents, false);
190    waiter->Wait();
191  }
192
193  // Immersive reveal should have same behavior as before.
194  revealed_lock.reset(immersive_mode_controller->GetRevealedLock(
195      ImmersiveModeController::ANIMATE_REVEAL_NO));
196  EXPECT_TRUE(immersive_mode_controller->IsRevealed());
197  EXPECT_TRUE(frame_view->ShouldPaint());
198  EXPECT_TRUE(frame_view->caption_button_container_->visible());
199  EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle());
200  EXPECT_LT(Tab::GetImmersiveHeight(),
201            frame_view->header_painter_->GetHeaderHeightForPainting());
202
203  // Ending the reveal should hide the caption buttons and the header should
204  // be in the lightbar style.
205  revealed_lock.reset();
206  EXPECT_TRUE(frame_view->ShouldPaint());
207  EXPECT_FALSE(frame_view->caption_button_container_->visible());
208  EXPECT_TRUE(frame_view->UseImmersiveLightbarHeaderStyle());
209  EXPECT_EQ(Tab::GetImmersiveHeight(),
210            frame_view->header_painter_->GetHeaderHeightForPainting());
211
212  // Exiting immersive fullscreen should make the caption buttons and the frame
213  // visible again.
214  {
215    scoped_ptr<FullscreenNotificationObserver> waiter(
216        new FullscreenNotificationObserver());
217    browser_view->ExitFullscreen();
218    waiter->Wait();
219  }
220  EXPECT_FALSE(immersive_mode_controller->IsEnabled());
221  EXPECT_TRUE(frame_view->ShouldPaint());
222  EXPECT_TRUE(frame_view->caption_button_container_->visible());
223  EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle());
224  EXPECT_LT(Tab::GetImmersiveHeight(),
225            frame_view->header_painter_->GetHeaderHeightForPainting());
226}
227#endif  // defined(OS_CHROMEOS)
228
229// Tests that FrameCaptionButtonContainer has been relaid out in response to
230// maximize mode being toggled.
231IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest,
232                       ToggleMaximizeModeRelayout) {
233  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
234  Widget* widget = browser_view->GetWidget();
235  // We know we're using Ash, so static cast.
236  BrowserNonClientFrameViewAsh* frame_view =
237      static_cast<BrowserNonClientFrameViewAsh*>(
238          widget->non_client_view()->frame_view());
239
240  const gfx::Rect initial = frame_view->caption_button_container_->bounds();
241  ash::Shell::GetInstance()->maximize_mode_controller()->
242      EnableMaximizeModeWindowManager(true);
243  const gfx::Rect during_maximize = frame_view->caption_button_container_->
244      bounds();
245  EXPECT_GT(initial.width(), during_maximize.width());
246  ash::Shell::GetInstance()->maximize_mode_controller()->
247      EnableMaximizeModeWindowManager(false);
248  const gfx::Rect after_restore = frame_view->caption_button_container_->
249      bounds();
250  EXPECT_EQ(initial, after_restore);
251}
252