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 "ash/shell.h"
6#include "ash/test/ash_test_base.h"
7#include "ash/test/test_session_state_delegate.h"
8#include "ash/test/test_shell_delegate.h"
9#include "ash/wm/window_state.h"
10#include "base/command_line.h"
11#include "base/memory/scoped_ptr.h"
12#include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
13#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
14#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
15#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
16#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
17#include "ui/aura/test/test_windows.h"
18#include "ui/aura/window.h"
19#include "ui/aura/window_event_dispatcher.h"
20
21//#include "base/compiler_specific.h"
22//#include "base/logging.h"
23//#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
24namespace chromeos {
25namespace {
26
27const char* kTestAccount1 = "user1@test.com";
28const char* kTestAccount2 = "user2@test.com";
29
30class WallpaperPrivateApiUnittest : public ash::test::AshTestBase {
31 public:
32  WallpaperPrivateApiUnittest()
33      : fake_user_manager_(new FakeUserManager()),
34        scoped_user_manager_(fake_user_manager_) {
35  }
36
37 protected:
38  FakeUserManager* fake_user_manager() {
39    return fake_user_manager_;
40  }
41
42 private:
43  FakeUserManager* fake_user_manager_;
44  ScopedUserManagerEnabler scoped_user_manager_;
45
46  DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateApiUnittest);
47};
48
49class TestMinimizeFunction
50    : public WallpaperPrivateMinimizeInactiveWindowsFunction {
51 public:
52  TestMinimizeFunction() {}
53
54  virtual bool RunAsync() OVERRIDE {
55    return WallpaperPrivateMinimizeInactiveWindowsFunction::RunAsync();
56  }
57
58 protected:
59  virtual ~TestMinimizeFunction() {}
60};
61
62class TestRestoreFunction
63    : public WallpaperPrivateRestoreMinimizedWindowsFunction {
64 public:
65  TestRestoreFunction() {}
66
67  virtual bool RunAsync() OVERRIDE {
68    return WallpaperPrivateRestoreMinimizedWindowsFunction::RunAsync();
69  }
70 protected:
71  virtual ~TestRestoreFunction() {}
72};
73
74}  // namespace
75
76TEST_F(WallpaperPrivateApiUnittest, HideAndRestoreWindows) {
77  fake_user_manager()->AddUser(kTestAccount1);
78  scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(3));
79  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2));
80  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
81  scoped_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
82
83  ash::wm::WindowState* window0_state = ash::wm::GetWindowState(window0.get());
84  ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1.get());
85  ash::wm::WindowState* window2_state = ash::wm::GetWindowState(window2.get());
86  ash::wm::WindowState* window3_state = ash::wm::GetWindowState(window3.get());
87
88  window3_state->Minimize();
89  window1_state->Maximize();
90
91  // Window 3 starts minimized, window 1 starts maximized.
92  EXPECT_FALSE(window0_state->IsMinimized());
93  EXPECT_FALSE(window1_state->IsMinimized());
94  EXPECT_FALSE(window2_state->IsMinimized());
95  EXPECT_TRUE(window3_state->IsMinimized());
96
97  // We then activate window 0 (i.e. wallpaper picker) and call the minimize
98  // function.
99  window0_state->Activate();
100  EXPECT_TRUE(window0_state->IsActive());
101  scoped_refptr<TestMinimizeFunction> minimize_function(
102      new TestMinimizeFunction());
103  EXPECT_TRUE(minimize_function->RunAsync());
104
105  // All windows except window 0 should be minimized.
106  EXPECT_FALSE(window0_state->IsMinimized());
107  EXPECT_TRUE(window1_state->IsMinimized());
108  EXPECT_TRUE(window2_state->IsMinimized());
109  EXPECT_TRUE(window3_state->IsMinimized());
110
111  // Then we destroy window 0 and call the restore function.
112  window0.reset();
113  scoped_refptr<TestRestoreFunction> restore_function(
114      new TestRestoreFunction());
115  EXPECT_TRUE(restore_function->RunAsync());
116
117  // Windows 1 and 2 should no longer be minimized. Window 1 should again
118  // be maximized. Window 3 should still be minimized.
119  EXPECT_TRUE(window1_state->IsMaximized());
120  EXPECT_FALSE(window2_state->IsMinimized());
121  EXPECT_TRUE(window3_state->IsMinimized());
122}
123
124// Test for multiple calls to |MinimizeInactiveWindows| before call
125// |RestoreWindows|:
126// 1. If all window hasn't change their states, the following calls are noops.
127// 2. If some windows are manually unminimized, the following call will minimize
128// all the unminimized windows.
129TEST_F(WallpaperPrivateApiUnittest, HideAndManualUnminimizeWindows) {
130  fake_user_manager()->AddUser(kTestAccount1);
131  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
132  scoped_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
133
134  ash::wm::WindowState* window0_state = ash::wm::GetWindowState(window0.get());
135  ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1.get());
136
137  // We then activate window 0 (i.e. wallpaper picker) and call the minimize
138  // function.
139  window0_state->Activate();
140  EXPECT_TRUE(window0_state->IsActive());
141  scoped_refptr<TestMinimizeFunction> minimize_function_0(
142      new TestMinimizeFunction());
143  EXPECT_TRUE(minimize_function_0->RunAsync());
144
145  // All windows except window 0 should be minimized.
146  EXPECT_FALSE(window0_state->IsMinimized());
147  EXPECT_TRUE(window1_state->IsMinimized());
148
149  // Calls minimize function again should be an noop if window state didn't
150  // change.
151  scoped_refptr<TestMinimizeFunction> minimize_function_1(
152      new TestMinimizeFunction());
153  EXPECT_TRUE(minimize_function_1->RunAsync());
154
155  // All windows except window 0 should be minimized.
156  EXPECT_FALSE(window0_state->IsMinimized());
157  EXPECT_TRUE(window1_state->IsMinimized());
158
159  // Manually unminimize window 1.
160  window1_state->Unminimize();
161  EXPECT_FALSE(window1_state->IsMinimized());
162  window0_state->Activate();
163
164  scoped_refptr<TestMinimizeFunction> minimize_function_2(
165      new TestMinimizeFunction());
166  EXPECT_TRUE(minimize_function_2->RunAsync());
167
168  // Window 1 should be minimized again.
169  EXPECT_FALSE(window0_state->IsMinimized());
170  EXPECT_TRUE(window1_state->IsMinimized());
171
172  // Then we destroy window 0 and call the restore function.
173  window0.reset();
174  scoped_refptr<TestRestoreFunction> restore_function(
175      new TestRestoreFunction());
176  EXPECT_TRUE(restore_function->RunAsync());
177
178  // Windows 1 should no longer be minimized.
179  EXPECT_FALSE(window1_state->IsMinimized());
180}
181
182class WallpaperPrivateApiMultiUserUnittest
183    : public WallpaperPrivateApiUnittest {
184 public:
185  WallpaperPrivateApiMultiUserUnittest()
186      : multi_user_window_manager_(NULL),
187        session_state_delegate_(NULL) {}
188
189  virtual void SetUp() OVERRIDE;
190  virtual void TearDown() OVERRIDE;
191
192 protected:
193  void SetUpMultiUserWindowManager(
194      const std::string& active_user_id,
195      chrome::MultiUserWindowManager::MultiProfileMode mode);
196
197  void SwitchActiveUser(const std::string& active_user_id);
198
199  chrome::MultiUserWindowManagerChromeOS* multi_user_window_manager() {
200    return multi_user_window_manager_;
201  }
202
203 private:
204  chrome::MultiUserWindowManagerChromeOS* multi_user_window_manager_;
205  ash::test::TestSessionStateDelegate* session_state_delegate_;
206
207  DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateApiMultiUserUnittest);
208};
209
210void WallpaperPrivateApiMultiUserUnittest::SetUp() {
211  AshTestBase::SetUp();
212  session_state_delegate_ =
213      static_cast<ash::test::TestSessionStateDelegate*> (
214          ash::Shell::GetInstance()->session_state_delegate());
215  fake_user_manager()->AddUser(kTestAccount1);
216  fake_user_manager()->AddUser(kTestAccount2);
217}
218
219void WallpaperPrivateApiMultiUserUnittest::TearDown() {
220  chrome::MultiUserWindowManager::DeleteInstance();
221  AshTestBase::TearDown();
222}
223
224void WallpaperPrivateApiMultiUserUnittest::SetUpMultiUserWindowManager(
225    const std::string& active_user_id,
226    chrome::MultiUserWindowManager::MultiProfileMode mode) {
227  multi_user_window_manager_ =
228      new chrome::MultiUserWindowManagerChromeOS(active_user_id);
229  chrome::MultiUserWindowManager::SetInstanceForTest(
230      multi_user_window_manager_, mode);
231  // We do not want animations while the test is going on.
232  multi_user_window_manager_->SetAnimationSpeedForTest(
233      chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
234  EXPECT_TRUE(multi_user_window_manager_);
235}
236
237void WallpaperPrivateApiMultiUserUnittest::SwitchActiveUser(
238    const std::string& active_user_id) {
239  fake_user_manager()->SwitchActiveUser(active_user_id);
240  multi_user_window_manager_->ActiveUserChanged(active_user_id);
241}
242
243// In multi profile mode, user may open wallpaper picker in one profile and
244// then switch to a different profile and open another wallpaper picker
245// without closing the first one.
246TEST_F(WallpaperPrivateApiMultiUserUnittest, HideAndRestoreWindowsTwoUsers) {
247  SetUpMultiUserWindowManager(kTestAccount1,
248      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED);
249
250  scoped_ptr<aura::Window> window4(CreateTestWindowInShellWithId(4));
251  scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(3));
252  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2));
253  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
254  scoped_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
255
256  ash::wm::WindowState* window0_state = ash::wm::GetWindowState(window0.get());
257  ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1.get());
258  ash::wm::WindowState* window2_state = ash::wm::GetWindowState(window2.get());
259  ash::wm::WindowState* window3_state = ash::wm::GetWindowState(window3.get());
260  ash::wm::WindowState* window4_state = ash::wm::GetWindowState(window4.get());
261
262  multi_user_window_manager()->SetWindowOwner(window0.get(), kTestAccount1);
263  multi_user_window_manager()->SetWindowOwner(window1.get(), kTestAccount1);
264
265  // Set some windows to an inactive owner.
266  multi_user_window_manager()->SetWindowOwner(window2.get(), kTestAccount2);
267  multi_user_window_manager()->SetWindowOwner(window3.get(), kTestAccount2);
268  multi_user_window_manager()->SetWindowOwner(window4.get(), kTestAccount2);
269
270  EXPECT_FALSE(window0_state->IsMinimized());
271  EXPECT_FALSE(window1_state->IsMinimized());
272  EXPECT_FALSE(window2_state->IsMinimized());
273  EXPECT_FALSE(window3_state->IsMinimized());
274  EXPECT_FALSE(window4_state->IsMinimized());
275
276  // We then activate window 0 (i.e. wallpaper picker) and call the minimize
277  // function.
278  window0_state->Activate();
279  EXPECT_TRUE(window0_state->IsActive());
280  scoped_refptr<TestMinimizeFunction> minimize_function_0(
281      new TestMinimizeFunction());
282  EXPECT_TRUE(minimize_function_0->RunAsync());
283
284  // All windows except window 0 should be minimized.
285  EXPECT_FALSE(window0_state->IsMinimized());
286  EXPECT_TRUE(window1_state->IsMinimized());
287
288  // All windows that belong to inactive user should not be affected.
289  EXPECT_FALSE(window2_state->IsMinimized());
290  EXPECT_FALSE(window3_state->IsMinimized());
291  EXPECT_FALSE(window4_state->IsMinimized());
292
293  // Activate kTestAccount2. kTestAccount1 becomes inactive user.
294  SwitchActiveUser(kTestAccount2);
295
296  window2_state->Activate();
297  EXPECT_TRUE(window2_state->IsActive());
298  scoped_refptr<TestMinimizeFunction> minimize_function_1(
299      new TestMinimizeFunction());
300  EXPECT_TRUE(minimize_function_1->RunAsync());
301
302  // All windows except window 2 should be minimized.
303  EXPECT_FALSE(window2_state->IsMinimized());
304  EXPECT_TRUE(window3_state->IsMinimized());
305  EXPECT_TRUE(window4_state->IsMinimized());
306
307  // All windows that belong to inactive user should not be affected.
308  EXPECT_FALSE(window0_state->IsMinimized());
309  EXPECT_TRUE(window1_state->IsMinimized());
310
311  // Destroy window 4. Nothing should happen to other windows.
312  window4_state->Unminimize();
313  window4.reset();
314
315  EXPECT_FALSE(window2_state->IsMinimized());
316  EXPECT_TRUE(window3_state->IsMinimized());
317  EXPECT_FALSE(window0_state->IsMinimized());
318  EXPECT_TRUE(window1_state->IsMinimized());
319
320  // Then we destroy window 2 and call the restore function.
321  window2.reset();
322  scoped_refptr<TestRestoreFunction> restore_function_0(
323      new TestRestoreFunction());
324  EXPECT_TRUE(restore_function_0->RunAsync());
325
326  EXPECT_FALSE(window3_state->IsMinimized());
327
328  // All windows that belong to inactive user should not be affected.
329  EXPECT_FALSE(window0_state->IsMinimized());
330  EXPECT_TRUE(window1_state->IsMinimized());
331
332  SwitchActiveUser(kTestAccount1);
333
334  // Then we destroy window 0 and call the restore function.
335  window0.reset();
336  scoped_refptr<TestRestoreFunction> restore_function_1(
337      new TestRestoreFunction());
338  EXPECT_TRUE(restore_function_1->RunAsync());
339
340  EXPECT_FALSE(window1_state->IsMinimized());
341  EXPECT_FALSE(window3_state->IsMinimized());
342}
343
344// In multi profile mode, user may teleport windows. Teleported window should
345// also be minimized when open wallpaper picker.
346TEST_F(WallpaperPrivateApiMultiUserUnittest, HideTeleportedWindow) {
347  SetUpMultiUserWindowManager(kTestAccount1,
348      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_MIXED);
349
350  scoped_ptr<aura::Window> window3(CreateTestWindowInShellWithId(3));
351  scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2));
352  scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
353  scoped_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
354
355  ash::wm::WindowState* window0_state = ash::wm::GetWindowState(window0.get());
356  ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1.get());
357  ash::wm::WindowState* window2_state = ash::wm::GetWindowState(window2.get());
358  ash::wm::WindowState* window3_state = ash::wm::GetWindowState(window3.get());
359
360  multi_user_window_manager()->SetWindowOwner(window0.get(), kTestAccount1);
361  multi_user_window_manager()->SetWindowOwner(window1.get(), kTestAccount1);
362
363  // Set some windows to an inactive owner.
364  multi_user_window_manager()->SetWindowOwner(window2.get(), kTestAccount2);
365  multi_user_window_manager()->SetWindowOwner(window3.get(), kTestAccount2);
366
367  // Teleport window2 to kTestAccount1.
368  multi_user_window_manager()->ShowWindowForUser(window2.get(), kTestAccount1);
369
370  // Initial window state. All windows shouldn't be minimized.
371  EXPECT_FALSE(window0_state->IsMinimized());
372  EXPECT_FALSE(window1_state->IsMinimized());
373  EXPECT_FALSE(window2_state->IsMinimized());
374  EXPECT_FALSE(window3_state->IsMinimized());
375
376  // We then activate window 0 (i.e. wallpaper picker) and call the minimize
377  // function.
378  window0_state->Activate();
379  EXPECT_TRUE(window0_state->IsActive());
380  scoped_refptr<TestMinimizeFunction> minimize_function_0(
381      new TestMinimizeFunction());
382  EXPECT_TRUE(minimize_function_0->RunAsync());
383
384  // All windows except window 0 should be minimized.
385  EXPECT_FALSE(window0_state->IsMinimized());
386  EXPECT_TRUE(window1_state->IsMinimized());
387
388  // Teleported window should also be minimized.
389  EXPECT_TRUE(window2_state->IsMinimized());
390  // Other window should remain the same.
391  EXPECT_FALSE(window3_state->IsMinimized());
392
393  // Then we destroy window 0 and call the restore function.
394  window0.reset();
395  scoped_refptr<TestRestoreFunction> restore_function_1(
396      new TestRestoreFunction());
397  EXPECT_TRUE(restore_function_1->RunAsync());
398
399  EXPECT_FALSE(window1_state->IsMinimized());
400  EXPECT_FALSE(window2_state->IsMinimized());
401  EXPECT_FALSE(window3_state->IsMinimized());
402}
403
404}  // namespace chromeos
405