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.
5 #include "ash/ash_switches.h"
6 #include "ash/launcher/launcher.h"
8 #include "ash/shell_delegate.h"
9 #include "ash/shell_window_ids.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/wm/root_window_layout_manager.h"
12 #include "ash/wm/shelf_layout_manager.h"
13 #include "base/command_line.h"
14 #include "base/utf_string_conversions.h"
15 #include "ui/aura/client/aura_constants.h"
16 #include "ui/aura/test/aura_test_base.h"
17 #include "ui/aura/root_window.h"
18 #include "ui/aura/window.h"
19 #include "ui/gfx/size.h"
20 #include "ui/views/widget/widget.h"
21 #include "ui/views/widget/widget_delegate.h"
23 using aura::RootWindow
;
29 views::Widget
* CreateTestWindow(const views::Widget::InitParams
& params
) {
30 views::Widget
* widget
= new views::Widget
;
35 aura::Window
* GetDefaultContainer() {
36 return Shell::GetContainer(
37 Shell::GetPrimaryRootWindow(),
38 internal::kShellWindowId_DefaultContainer
);
41 aura::Window
* GetAlwaysOnTopContainer() {
42 return Shell::GetContainer(
43 Shell::GetPrimaryRootWindow(),
44 internal::kShellWindowId_AlwaysOnTopContainer
);
47 // Expect ALL the containers!
48 void ExpectAllContainers() {
49 aura::RootWindow
* root_window
= Shell::GetPrimaryRootWindow();
50 EXPECT_TRUE(Shell::GetContainer(
51 root_window
, internal::kShellWindowId_DesktopBackgroundContainer
));
52 EXPECT_TRUE(Shell::GetContainer(
53 root_window
, internal::kShellWindowId_DefaultContainer
));
54 EXPECT_TRUE(Shell::GetContainer(
55 root_window
, internal::kShellWindowId_AlwaysOnTopContainer
));
56 EXPECT_TRUE(Shell::GetContainer(
57 root_window
, internal::kShellWindowId_PanelContainer
));
58 EXPECT_TRUE(Shell::GetContainer(
59 root_window
, internal::kShellWindowId_LauncherContainer
));
60 EXPECT_TRUE(Shell::GetContainer(
61 root_window
, internal::kShellWindowId_SystemModalContainer
));
62 EXPECT_TRUE(Shell::GetContainer(
63 root_window
, internal::kShellWindowId_LockScreenContainer
));
64 EXPECT_TRUE(Shell::GetContainer(
65 root_window
, internal::kShellWindowId_LockSystemModalContainer
));
66 EXPECT_TRUE(Shell::GetContainer(
67 root_window
, internal::kShellWindowId_StatusContainer
));
68 EXPECT_TRUE(Shell::GetContainer(
69 root_window
, internal::kShellWindowId_MenuContainer
));
70 EXPECT_TRUE(Shell::GetContainer(
71 root_window
, internal::kShellWindowId_DragImageAndTooltipContainer
));
72 EXPECT_TRUE(Shell::GetContainer(
73 root_window
, internal::kShellWindowId_SettingBubbleContainer
));
74 EXPECT_TRUE(Shell::GetContainer(
75 root_window
, internal::kShellWindowId_OverlayContainer
));
78 void TestCreateWindow(views::Widget::InitParams::Type type
,
80 aura::Window
* expected_container
) {
81 views::Widget::InitParams
widget_params(type
);
82 widget_params
.keep_on_top
= always_on_top
;
84 views::Widget
* widget
= CreateTestWindow(widget_params
);
87 EXPECT_EQ(expected_container
, widget
->GetNativeWindow()->parent()) <<
88 "TestCreateWindow: type=" << type
<< ", always_on_top=" << always_on_top
;
93 class ModalWindow
: public views::WidgetDelegateView
{
96 virtual ~ModalWindow() {}
98 // Overridden from views::WidgetDelegate:
99 virtual views::View
* GetContentsView() OVERRIDE
{
102 virtual bool CanResize() const OVERRIDE
{
105 virtual string16
GetWindowTitle() const OVERRIDE
{
106 return ASCIIToUTF16("Modal Window");
108 virtual ui::ModalType
GetModalType() const OVERRIDE
{
109 return ui::MODAL_TYPE_SYSTEM
;
113 DISALLOW_COPY_AND_ASSIGN(ModalWindow
);
118 class ShellTest
: public test::AshTestBase
{
121 virtual ~ShellTest() {}
124 DISALLOW_COPY_AND_ASSIGN(ShellTest
);
127 TEST_F(ShellTest
, CreateWindow
) {
128 // Normal window should be created in default container.
129 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW
,
130 false, // always_on_top
131 GetDefaultContainer());
132 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP
,
133 false, // always_on_top
134 GetDefaultContainer());
136 // Always-on-top window and popup are created in always-on-top container.
137 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW
,
138 true, // always_on_top
139 GetAlwaysOnTopContainer());
140 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP
,
141 true, // always_on_top
142 GetAlwaysOnTopContainer());
145 TEST_F(ShellTest
, ChangeAlwaysOnTop
) {
146 views::Widget::InitParams
widget_params(
147 views::Widget::InitParams::TYPE_WINDOW
);
149 // Creates a normal window
150 views::Widget
* widget
= CreateTestWindow(widget_params
);
153 // It should be in default container.
154 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
156 // Flip always-on-top flag.
157 widget
->SetAlwaysOnTop(true);
158 // And it should in always on top container now.
159 EXPECT_EQ(GetAlwaysOnTopContainer(), widget
->GetNativeWindow()->parent());
161 // Flip always-on-top flag.
162 widget
->SetAlwaysOnTop(false);
163 // It should go back to default container.
164 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
166 // Set the same always-on-top flag again.
167 widget
->SetAlwaysOnTop(false);
168 // Should have no effect and we are still in the default container.
169 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
174 TEST_F(ShellTest
, CreateModalWindow
) {
175 views::Widget::InitParams
widget_params(
176 views::Widget::InitParams::TYPE_WINDOW
);
178 // Create a normal window.
179 views::Widget
* widget
= CreateTestWindow(widget_params
);
182 // It should be in default container.
183 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
185 // Create a modal window.
186 views::Widget
* modal_widget
= views::Widget::CreateWindowWithParent(
187 new ModalWindow(), widget
->GetNativeView());
188 modal_widget
->Show();
190 // It should be in modal container.
191 aura::Window
* modal_container
= Shell::GetContainer(
192 Shell::GetPrimaryRootWindow(),
193 internal::kShellWindowId_SystemModalContainer
);
194 EXPECT_EQ(modal_container
, modal_widget
->GetNativeWindow()->parent());
196 modal_widget
->Close();
200 TEST_F(ShellTest
, CreateLockScreenModalWindow
) {
201 views::Widget::InitParams
widget_params(
202 views::Widget::InitParams::TYPE_WINDOW
);
204 // Create a normal window.
205 views::Widget
* widget
= CreateTestWindow(widget_params
);
208 // It should be in default container.
209 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
211 // Create a LockScreen window.
212 views::Widget
* lock_widget
= CreateTestWindow(widget_params
);
213 ash::Shell::GetContainer(
214 Shell::GetPrimaryRootWindow(),
215 ash::internal::kShellWindowId_LockScreenContainer
)->
216 AddChild(lock_widget
->GetNativeView());
219 // It should be in LockScreen container.
220 aura::Window
* lock_screen
= Shell::GetContainer(
221 Shell::GetPrimaryRootWindow(),
222 ash::internal::kShellWindowId_LockScreenContainer
);
223 EXPECT_EQ(lock_screen
, lock_widget
->GetNativeWindow()->parent());
225 // Create a modal window with a lock window as parent.
226 views::Widget
* lock_modal_widget
= views::Widget::CreateWindowWithParent(
227 new ModalWindow(), lock_widget
->GetNativeView());
228 lock_modal_widget
->Show();
230 // It should be in LockScreen modal container.
231 aura::Window
* lock_modal_container
= Shell::GetContainer(
232 Shell::GetPrimaryRootWindow(),
233 ash::internal::kShellWindowId_LockSystemModalContainer
);
234 EXPECT_EQ(lock_modal_container
,
235 lock_modal_widget
->GetNativeWindow()->parent());
237 // Create a modal window with a normal window as parent.
238 views::Widget
* modal_widget
= views::Widget::CreateWindowWithParent(
239 new ModalWindow(), widget
->GetNativeView());
240 modal_widget
->Show();
242 // It should be in non-LockScreen modal container.
243 aura::Window
* modal_container
= Shell::GetContainer(
244 Shell::GetPrimaryRootWindow(),
245 ash::internal::kShellWindowId_SystemModalContainer
);
246 EXPECT_EQ(modal_container
, modal_widget
->GetNativeWindow()->parent());
248 modal_widget
->Close();
249 lock_modal_widget
->Close();
250 lock_widget
->Close();
254 TEST_F(ShellTest
, IsScreenLocked
) {
255 ash::Shell::GetInstance()->delegate()->LockScreen();
256 EXPECT_TRUE(Shell::GetInstance()->IsScreenLocked());
257 ash::Shell::GetInstance()->delegate()->UnlockScreen();
258 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
261 // Fails on Mac, see http://crbug.com/115662
262 #if defined(OS_MACOSX)
263 #define MAYBE_ManagedWindowModeBasics FAILS_ManagedWindowModeBasics
265 #define MAYBE_ManagedWindowModeBasics ManagedWindowModeBasics
267 TEST_F(ShellTest
, MAYBE_ManagedWindowModeBasics
) {
268 Shell
* shell
= Shell::GetInstance();
269 Shell::TestApi
test_api(shell
);
271 // We start with the usual window containers.
272 ExpectAllContainers();
273 // We have a default container event filter (for window drags).
274 EXPECT_TRUE(GetDefaultContainer()->event_filter());
275 // Launcher is visible.
276 views::Widget
* launcher_widget
= shell
->launcher()->widget();
277 EXPECT_TRUE(launcher_widget
->IsVisible());
278 // Launcher is at bottom-left of screen.
279 EXPECT_EQ(0, launcher_widget
->GetWindowScreenBounds().x());
280 EXPECT_EQ(Shell::GetPrimaryRootWindow()->GetHostSize().height(),
281 launcher_widget
->GetWindowScreenBounds().bottom());
282 // We have a desktop background but not a bare layer.
283 EXPECT_TRUE(test_api
.root_window_layout()->background_widget());
284 EXPECT_FALSE(test_api
.root_window_layout()->background_layer());
286 // Create a normal window. It is not maximized.
287 views::Widget::InitParams
widget_params(
288 views::Widget::InitParams::TYPE_WINDOW
);
289 widget_params
.bounds
.SetRect(11, 22, 300, 400);
290 views::Widget
* widget
= CreateTestWindow(widget_params
);
292 EXPECT_FALSE(widget
->IsMaximized());
298 TEST_F(ShellTest
, FullscreenWindowHidesShelf
) {
299 ExpectAllContainers();
301 // Create a normal window. It is not maximized.
302 views::Widget::InitParams
widget_params(
303 views::Widget::InitParams::TYPE_WINDOW
);
304 widget_params
.bounds
.SetRect(11, 22, 300, 400);
305 views::Widget
* widget
= CreateTestWindow(widget_params
);
307 EXPECT_FALSE(widget
->IsMaximized());
309 // Shelf defaults to visible.
310 EXPECT_EQ(internal::ShelfLayoutManager::VISIBLE
,
311 Shell::GetInstance()->shelf()->visibility_state());
313 // Fullscreen window hides it.
314 widget
->SetFullscreen(true);
315 EXPECT_EQ(internal::ShelfLayoutManager::HIDDEN
,
316 Shell::GetInstance()->shelf()->visibility_state());
318 // Restoring the window restores it.
320 EXPECT_EQ(internal::ShelfLayoutManager::VISIBLE
,
321 Shell::GetInstance()->shelf()->visibility_state());
327 // This verifies WindowObservers are removed when a window is destroyed after
328 // the Shell is destroyed. This scenario (aura::Windows being deleted after the
329 // Shell) occurs if someone is holding a reference to an unparented Window, as
330 // is the case with a RenderWidgetHostViewAura that isn't on screen. As long as
331 // everything is ok, we won't crash. If there is a bug, window's destructor will
332 // notify some deleted object (say VideoDetector or ActivationController) and
334 class ShellTest2
: public test::AshTestBase
{
337 virtual ~ShellTest2() {}
340 scoped_ptr
<aura::Window
> window_
;
343 DISALLOW_COPY_AND_ASSIGN(ShellTest2
);
346 TEST_F(ShellTest2
, DontCrashWhenWindowDeleted
) {
347 window_
.reset(new aura::Window(NULL
));
348 window_
->Init(ui::LAYER_NOT_DRAWN
);