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.
4
5#include "ash/accelerators/accelerator_commands.h"
6
7#include "ash/ash_switches.h"
8#include "ash/shell.h"
9#include "ash/wm/window_state.h"
10#include "base/command_line.h"
11#include "chrome/browser/apps/app_browsertest_util.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_commands.h"
14#include "chrome/browser/ui/browser_finder.h"
15#include "chrome/browser/ui/browser_window.h"
16#include "chrome/common/chrome_switches.h"
17#include "chrome/test/base/in_process_browser_test.h"
18#include "chrome/test/base/test_switches.h"
19#include "extensions/browser/app_window/app_window.h"
20#include "extensions/browser/app_window/native_app_window.h"
21#include "ui/aura/client/aura_constants.h"
22#include "ui/views/widget/widget.h"
23#include "ui/views/widget/widget_delegate.h"
24
25using testing::Combine;
26using testing::Values;
27using testing::WithParamInterface;
28
29namespace {
30
31// WidgetDelegateView which allows the widget to be maximized.
32class MaximizableWidgetDelegate : public views::WidgetDelegateView {
33 public:
34  MaximizableWidgetDelegate() {
35  }
36  virtual ~MaximizableWidgetDelegate() {
37  }
38
39  virtual bool CanMaximize() const OVERRIDE {
40    return true;
41  }
42
43 private:
44  DISALLOW_COPY_AND_ASSIGN(MaximizableWidgetDelegate);
45};
46
47// Returns true if |window_state|'s window is in immersive fullscreen. Infer
48// whether the window is in immersive fullscreen based on whether the shelf is
49// hidden when the window is fullscreen. (This is not quite right because the
50// shelf is hidden if a window is in both immersive fullscreen and tab
51// fullscreen.)
52bool IsInImmersiveFullscreen(ash::wm::WindowState* window_state) {
53  return window_state->IsFullscreen() &&
54      !window_state->hide_shelf_when_fullscreen();
55}
56
57}  // namespace
58
59typedef InProcessBrowserTest AcceleratorCommandsBrowserTest;
60
61// Confirm that toggling window miximized works properly
62IN_PROC_BROWSER_TEST_F(AcceleratorCommandsBrowserTest, ToggleMaximized) {
63#if defined(OS_WIN)
64  // Run the test on Win Ash only.
65  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
66    return;
67#endif
68
69  ASSERT_TRUE(ash::Shell::HasInstance()) << "No Instance";
70  ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState();
71  ASSERT_TRUE(window_state);
72
73  // When not in fullscreen, accelerators::ToggleMaximized toggles Maximized.
74  EXPECT_FALSE(window_state->IsMaximized());
75  ash::accelerators::ToggleMaximized();
76  EXPECT_TRUE(window_state->IsMaximized());
77  ash::accelerators::ToggleMaximized();
78  EXPECT_FALSE(window_state->IsMaximized());
79
80  // When in fullscreen accelerators::ToggleMaximized gets out of fullscreen.
81  EXPECT_FALSE(window_state->IsFullscreen());
82  Browser* browser = chrome::FindBrowserWithWindow(window_state->window());
83  ASSERT_TRUE(browser);
84  chrome::ToggleFullscreenMode(browser);
85  EXPECT_TRUE(window_state->IsFullscreen());
86  ash::accelerators::ToggleMaximized();
87  EXPECT_FALSE(window_state->IsFullscreen());
88  EXPECT_FALSE(window_state->IsMaximized());
89  ash::accelerators::ToggleMaximized();
90  EXPECT_FALSE(window_state->IsFullscreen());
91  EXPECT_TRUE(window_state->IsMaximized());
92}
93
94class AcceleratorCommandsFullscreenBrowserTest
95    : public WithParamInterface<ui::WindowShowState>,
96      public InProcessBrowserTest {
97 public:
98  AcceleratorCommandsFullscreenBrowserTest()
99      : initial_show_state_(GetParam()) {
100  }
101  virtual ~AcceleratorCommandsFullscreenBrowserTest() {
102  }
103
104  // Sets |window_state|'s show state to |initial_show_state_|.
105  void SetToInitialShowState(ash::wm::WindowState* window_state) {
106    if (initial_show_state_ == ui::SHOW_STATE_MAXIMIZED)
107      window_state->Maximize();
108    else
109      window_state->Restore();
110  }
111
112  // Returns true if |window_state|'s show state is |initial_show_state_|.
113  bool IsInitialShowState(const ash::wm::WindowState* window_state) const {
114    if (initial_show_state_ == ui::SHOW_STATE_MAXIMIZED)
115      return window_state->IsMaximized();
116    else
117      return window_state->IsNormalStateType();
118  }
119
120 private:
121  ui::WindowShowState initial_show_state_;
122
123  DISALLOW_COPY_AND_ASSIGN(AcceleratorCommandsFullscreenBrowserTest);
124};
125
126// Test that toggling window fullscreen works properly.
127IN_PROC_BROWSER_TEST_P(AcceleratorCommandsFullscreenBrowserTest,
128                       ToggleFullscreen) {
129#if defined(OS_WIN)
130  // Run the test on Win Ash only.
131  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
132    return;
133#endif
134
135  ASSERT_TRUE(ash::Shell::HasInstance()) << "No Instance";
136
137  // 1) Browser windows.
138  ASSERT_TRUE(browser()->is_type_tabbed());
139  ash::wm::WindowState* window_state =
140      ash::wm::GetWindowState(browser()->window()->GetNativeWindow());
141  ASSERT_TRUE(window_state->IsActive());
142  SetToInitialShowState(window_state);
143  EXPECT_TRUE(IsInitialShowState(window_state));
144
145  ash::accelerators::ToggleFullscreen();
146  EXPECT_TRUE(window_state->IsFullscreen());
147  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
148
149  ash::accelerators::ToggleFullscreen();
150  EXPECT_TRUE(IsInitialShowState(window_state));
151
152  // 2) ToggleFullscreen() should have no effect on windows which cannot be
153  // maximized.
154  window_state->window()->SetProperty(aura::client::kCanMaximizeKey, false);
155  ash::accelerators::ToggleFullscreen();
156  EXPECT_TRUE(IsInitialShowState(window_state));
157
158  // 3) Hosted apps.
159  Browser::CreateParams browser_create_params(
160      Browser::CreateParams::CreateForApp("Test",
161                                          true /* trusted_source */,
162                                          gfx::Rect(),
163                                          browser()->profile(),
164                                          chrome::HOST_DESKTOP_TYPE_ASH));
165
166  Browser* app_host_browser = new Browser(browser_create_params);
167  ASSERT_TRUE(app_host_browser->is_app());
168  AddBlankTabAndShow(app_host_browser);
169  window_state =
170      ash::wm::GetWindowState(app_host_browser->window()->GetNativeWindow());
171  ASSERT_TRUE(window_state->IsActive());
172  SetToInitialShowState(window_state);
173  EXPECT_TRUE(IsInitialShowState(window_state));
174
175  ash::accelerators::ToggleFullscreen();
176  EXPECT_TRUE(window_state->IsFullscreen());
177  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
178
179  ash::accelerators::ToggleFullscreen();
180  EXPECT_TRUE(IsInitialShowState(window_state));
181
182  // 4) Popup browser windows.
183  browser_create_params = Browser::CreateParams(
184      Browser::TYPE_POPUP, browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH);
185  Browser* popup_browser = new Browser(browser_create_params);
186  ASSERT_TRUE(popup_browser->is_type_popup());
187  ASSERT_FALSE(popup_browser->is_app());
188  AddBlankTabAndShow(popup_browser);
189  window_state =
190      ash::wm::GetWindowState(popup_browser->window()->GetNativeWindow());
191  ASSERT_TRUE(window_state->IsActive());
192  SetToInitialShowState(window_state);
193  EXPECT_TRUE(IsInitialShowState(window_state));
194
195  ash::accelerators::ToggleFullscreen();
196  EXPECT_TRUE(window_state->IsFullscreen());
197  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
198
199  ash::accelerators::ToggleFullscreen();
200  EXPECT_TRUE(IsInitialShowState(window_state));
201
202  // 5) Miscellaneous windows (e.g. task manager).
203  views::Widget::InitParams params;
204  params.delegate = new MaximizableWidgetDelegate();
205  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
206  scoped_ptr<views::Widget> widget(new views::Widget);
207  widget->Init(params);
208  widget->Show();
209
210  window_state = ash::wm::GetWindowState(widget->GetNativeWindow());
211  ASSERT_TRUE(window_state->IsActive());
212  SetToInitialShowState(window_state);
213  EXPECT_TRUE(IsInitialShowState(window_state));
214
215  ash::accelerators::ToggleFullscreen();
216  EXPECT_TRUE(window_state->IsFullscreen());
217  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
218
219  // TODO(pkotwicz|oshima): Make toggling fullscreen restore the window to its
220  // show state prior to entering fullscreen.
221  ash::accelerators::ToggleFullscreen();
222  EXPECT_FALSE(window_state->IsFullscreen());
223}
224
225INSTANTIATE_TEST_CASE_P(InitiallyRestored,
226                        AcceleratorCommandsFullscreenBrowserTest,
227                        Values(ui::SHOW_STATE_NORMAL));
228INSTANTIATE_TEST_CASE_P(InitiallyMaximized,
229                        AcceleratorCommandsFullscreenBrowserTest,
230                        Values(ui::SHOW_STATE_MAXIMIZED));
231
232class AcceleratorCommandsPlatformAppFullscreenBrowserTest
233    : public WithParamInterface<ui::WindowShowState>,
234      public extensions::PlatformAppBrowserTest {
235 public:
236  AcceleratorCommandsPlatformAppFullscreenBrowserTest()
237      : initial_show_state_(GetParam()) {
238  }
239  virtual ~AcceleratorCommandsPlatformAppFullscreenBrowserTest() {
240  }
241
242  // Sets |app_window|'s show state to |initial_show_state_|.
243  void SetToInitialShowState(extensions::AppWindow* app_window) {
244    if (initial_show_state_ == ui::SHOW_STATE_MAXIMIZED)
245      app_window->Maximize();
246    else
247      app_window->Restore();
248  }
249
250  // Returns true if |app_window|'s show state is |initial_show_state_|.
251  bool IsInitialShowState(extensions::AppWindow* app_window) const {
252    if (initial_show_state_ == ui::SHOW_STATE_MAXIMIZED)
253      return app_window->GetBaseWindow()->IsMaximized();
254    else
255      return ui::BaseWindow::IsRestored(*app_window->GetBaseWindow());
256  }
257
258 private:
259  ui::WindowShowState initial_show_state_;
260
261  DISALLOW_COPY_AND_ASSIGN(AcceleratorCommandsPlatformAppFullscreenBrowserTest);
262};
263
264// Test the behavior of platform apps when ToggleFullscreen() is called.
265IN_PROC_BROWSER_TEST_P(AcceleratorCommandsPlatformAppFullscreenBrowserTest,
266                       ToggleFullscreen) {
267#if defined(OS_WIN)
268  // Run the test on Win Ash only.
269  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
270    return;
271#endif
272
273  ASSERT_TRUE(ash::Shell::HasInstance()) << "No Instance";
274  const extensions::Extension* extension = LoadAndLaunchPlatformApp("minimal",
275                                                                    "Launched");
276
277  {
278    // Test that ToggleFullscreen() toggles a platform's app's fullscreen
279    // state and that it additionally puts the app into immersive fullscreen
280    // if put_all_windows_in_immersive() returns true.
281    extensions::AppWindow::CreateParams params;
282    params.frame = extensions::AppWindow::FRAME_CHROME;
283    extensions::AppWindow* app_window =
284        CreateAppWindowFromParams(extension, params);
285    extensions::NativeAppWindow* native_app_window =
286        app_window->GetBaseWindow();
287    SetToInitialShowState(app_window);
288    ASSERT_TRUE(app_window->GetBaseWindow()->IsActive());
289    EXPECT_TRUE(IsInitialShowState(app_window));
290
291    ash::accelerators::ToggleFullscreen();
292    EXPECT_TRUE(native_app_window->IsFullscreen());
293    ash::wm::WindowState* window_state =
294        ash::wm::GetWindowState(native_app_window->GetNativeWindow());
295    EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
296
297    ash::accelerators::ToggleFullscreen();
298    EXPECT_TRUE(IsInitialShowState(app_window));
299
300    CloseAppWindow(app_window);
301  }
302
303  {
304    // Repeat the test, but make sure that frameless platform apps are never put
305    // into immersive fullscreen.
306    extensions::AppWindow::CreateParams params;
307    params.frame = extensions::AppWindow::FRAME_NONE;
308    extensions::AppWindow* app_window =
309        CreateAppWindowFromParams(extension, params);
310    extensions::NativeAppWindow* native_app_window =
311        app_window->GetBaseWindow();
312    ASSERT_TRUE(app_window->GetBaseWindow()->IsActive());
313    SetToInitialShowState(app_window);
314    EXPECT_TRUE(IsInitialShowState(app_window));
315
316    ash::accelerators::ToggleFullscreen();
317    EXPECT_TRUE(native_app_window->IsFullscreen());
318    ash::wm::WindowState* window_state =
319        ash::wm::GetWindowState(native_app_window->GetNativeWindow());
320    EXPECT_FALSE(IsInImmersiveFullscreen(window_state));
321
322    ash::accelerators::ToggleFullscreen();
323    EXPECT_TRUE(IsInitialShowState(app_window));
324
325    CloseAppWindow(app_window);
326  }
327}
328
329INSTANTIATE_TEST_CASE_P(InitiallyRestored,
330                        AcceleratorCommandsPlatformAppFullscreenBrowserTest,
331                        Values(ui::SHOW_STATE_NORMAL));
332INSTANTIATE_TEST_CASE_P(InitiallyMaximized,
333                        AcceleratorCommandsPlatformAppFullscreenBrowserTest,
334                        Values(ui::SHOW_STATE_MAXIMIZED));
335