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 "chrome/browser/chromeos/login/wallpaper_manager.h"
7 #include "ash/ash_resources/grit/ash_resources.h"
8 #include "ash/desktop_background/desktop_background_controller.h"
9 #include "ash/desktop_background/desktop_background_controller_observer.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/shell.h"
12 #include "ash/test/display_manager_test_api.h"
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/prefs/scoped_user_pref_update.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/time/time.h"
19 #include "base/values.h"
20 #include "chrome/browser/chromeos/login/user.h"
21 #include "chrome/browser/chromeos/login/user_manager.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chrome/test/base/testing_browser_process.h"
25 #include "chromeos/chromeos_switches.h"
26 #include "chromeos/dbus/cryptohome_client.h"
27 #include "ui/aura/env.h"
28 #include "ui/base/resource/resource_bundle.h"
36 const int kLargeWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_LARGE;
37 const int kSmallWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_SMALL;
39 int kLargeWallpaperWidth = 256;
40 int kLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
41 int kSmallWallpaperWidth = 256;
42 int kSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
44 const char kTestUser1[] = "test@domain.com";
45 const char kTestUser1Hash[] = "test@domain.com-hash";
49 class WallpaperManagerBrowserTest : public InProcessBrowserTest,
50 public DesktopBackgroundControllerObserver {
52 WallpaperManagerBrowserTest () : controller_(NULL),
56 virtual ~WallpaperManagerBrowserTest () {}
58 virtual void SetUpOnMainThread() OVERRIDE {
59 controller_ = ash::Shell::GetInstance()->desktop_background_controller();
60 controller_->AddObserver(this);
61 local_state_ = g_browser_process->local_state();
62 UpdateDisplay("800x600");
65 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
66 command_line->AppendSwitch(switches::kLoginManager);
67 command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
70 virtual void CleanUpOnMainThread() OVERRIDE {
71 controller_->RemoveObserver(this);
75 // Update the display configuration as given in |display_specs|.
76 // See ash::test::DisplayManagerTestApi::UpdateDisplay for more
78 void UpdateDisplay(const std::string& display_specs) {
79 ash::test::DisplayManagerTestApi display_manager_test_api(
80 ash::Shell::GetInstance()->display_manager());
81 display_manager_test_api.UpdateDisplay(display_specs);
84 void WaitAsyncWallpaperLoad() {
85 base::MessageLoop::current()->Run();
88 virtual void OnWallpaperDataChanged() OVERRIDE {
89 base::MessageLoop::current()->Quit();
93 // Return custom wallpaper path. Create directory if not exist.
94 base::FilePath GetCustomWallpaperPath(const char* sub_dir,
95 const std::string& username_hash,
96 const std::string& id) {
97 base::FilePath wallpaper_path =
98 WallpaperManager::Get()->GetCustomWallpaperPath(sub_dir,
101 if (!base::DirectoryExists(wallpaper_path.DirName()))
102 file_util::CreateDirectory(wallpaper_path.DirName());
104 return wallpaper_path;
107 // Logs in |username|.
108 void LogIn(const std::string& username, const std::string& username_hash) {
109 UserManager::Get()->UserLoggedIn(username, username_hash, false);
112 // Saves bitmap |resource_id| to disk.
113 void SaveUserWallpaperData(const std::string& username,
114 const base::FilePath& wallpaper_path,
116 scoped_refptr<base::RefCountedStaticMemory> image_data(
117 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
118 resource_id, ui::SCALE_FACTOR_100P));
119 int written = file_util::WriteFile(
121 reinterpret_cast<const char*>(image_data->front()),
123 EXPECT_EQ(static_cast<int>(image_data->size()), written);
126 int LoadedWallpapers() {
127 return WallpaperManager::Get()->loaded_wallpapers();
130 DesktopBackgroundController* controller_;
131 PrefService* local_state_;
134 DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest);
137 // Tests that the appropriate custom wallpaper (large vs. small) is loaded
138 // depending on the desktop resolution.
139 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
140 LoadCustomLargeWallpaperForLargeExternalScreen) {
141 WallpaperManager* wallpaper_manager = WallpaperManager::Get();
142 LogIn(kTestUser1, kTestUser1Hash);
143 // Wait for default wallpaper loaded.
144 WaitAsyncWallpaperLoad();
145 std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
146 base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
147 kSmallWallpaperSubDir,
150 base::FilePath large_wallpaper_path = GetCustomWallpaperPath(
151 kLargeWallpaperSubDir,
155 // Saves the small/large resolution wallpapers to small/large custom
157 SaveUserWallpaperData(kTestUser1,
158 small_wallpaper_path,
159 kSmallWallpaperResourceId);
160 SaveUserWallpaperData(kTestUser1,
161 large_wallpaper_path,
162 kLargeWallpaperResourceId);
164 std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
165 // Saves wallpaper info to local state for user |kTestUser1|.
166 WallpaperInfo info = {
168 WALLPAPER_LAYOUT_CENTER_CROPPED,
170 base::Time::Now().LocalMidnight()
172 wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
174 // Set the wallpaper for |kTestUser1|.
175 wallpaper_manager->SetUserWallpaper(kTestUser1);
176 WaitAsyncWallpaperLoad();
177 gfx::ImageSkia wallpaper = controller_->GetWallpaper();
179 // Display is initialized to 800x600. The small resolution custom wallpaper is
181 EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
182 EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
184 // Hook up another 800x600 display.
185 UpdateDisplay("800x600,800x600");
186 WaitAsyncWallpaperLoad();
187 // The small resolution custom wallpaper is expected.
188 EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
189 EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
191 // Detach the secondary display.
192 UpdateDisplay("800x600");
193 // Hook up a 2000x2000 display. The large resolution custom wallpaper should
195 UpdateDisplay("800x600,2000x2000");
196 WaitAsyncWallpaperLoad();
197 wallpaper = controller_->GetWallpaper();
199 // The large resolution custom wallpaper is expected.
200 EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
201 EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
203 // Detach the secondary display.
204 UpdateDisplay("800x600");
205 // Hook up the 2000x2000 display again. The large resolution default wallpaper
206 // should persist. Test for crbug/165788.
207 UpdateDisplay("800x600,2000x2000");
208 WaitAsyncWallpaperLoad();
209 wallpaper = controller_->GetWallpaper();
211 // The large resolution custom wallpaper is expected.
212 EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
213 EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
216 // If chrome tries to reload the same wallpaper twice, the latter request should
217 // be prevented. Otherwise, there are some strange animation issues as
218 // described in crbug.com/158383.
219 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
220 PreventReloadingSameWallpaper) {
221 WallpaperManager* wallpaper_manager = WallpaperManager::Get();
222 // New user log in, a default wallpaper is loaded.
223 LogIn(kTestUser1, kTestUser1Hash);
224 EXPECT_EQ(1, LoadedWallpapers());
225 // Loads the same wallpaper before the initial one finished. It should be
227 wallpaper_manager->SetUserWallpaper(kTestUser1);
228 EXPECT_EQ(1, LoadedWallpapers());
229 WaitAsyncWallpaperLoad();
230 // Loads the same wallpaper after the initial one finished. It should be
232 wallpaper_manager->SetUserWallpaper(kTestUser1);
233 EXPECT_EQ(1, LoadedWallpapers());
234 wallpaper_manager->ClearWallpaperCache();
236 // Change wallpaper to a custom wallpaper.
237 std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
238 base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
239 kSmallWallpaperSubDir,
242 SaveUserWallpaperData(kTestUser1,
243 small_wallpaper_path,
244 kSmallWallpaperResourceId);
246 std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
247 // Saves wallpaper info to local state for user |kTestUser1|.
248 WallpaperInfo info = {
250 WALLPAPER_LAYOUT_CENTER_CROPPED,
252 base::Time::Now().LocalMidnight()
254 wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
256 wallpaper_manager->SetUserWallpaper(kTestUser1);
257 EXPECT_EQ(2, LoadedWallpapers());
258 // Loads the same wallpaper before the initial one finished. It should be
260 wallpaper_manager->SetUserWallpaper(kTestUser1);
261 EXPECT_EQ(2, LoadedWallpapers());
262 WaitAsyncWallpaperLoad();
263 wallpaper_manager->SetUserWallpaper(kTestUser1);
264 EXPECT_EQ(2, LoadedWallpapers());
267 // Some users have old user profiles which may have legacy wallpapers. And these
268 // lagacy wallpapers should migrate to new wallpaper picker version seamlessly.
269 // This tests make sure we compatible with migrated old wallpapers.
271 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
272 PRE_UseMigratedWallpaperInfo) {
273 // New user log in, a default wallpaper is loaded.
274 LogIn(kTestUser1, kTestUser1Hash);
275 WaitAsyncWallpaperLoad();
276 // Old wallpaper migration code doesn't exist in codebase anymore. Modify user
277 // wallpaper info directly to simulate the wallpaper migration. See
278 // crosbug.com/38429 for details about why we modify wallpaper info this way.
279 WallpaperInfo info = {
281 WALLPAPER_LAYOUT_CENTER_CROPPED,
283 base::Time::Now().LocalMidnight()
285 WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
288 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
289 UseMigratedWallpaperInfo) {
290 LogIn(kTestUser1, kTestUser1Hash);
291 WaitAsyncWallpaperLoad();
292 // This test should finish normally. If timeout, it is probably because
293 // migrated wallpaper is somehow not loaded. Bad things can happen if
294 // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
297 // Some users have old user profiles which may never get a chance to migrate.
298 // This tests make sure we compatible with these profiles.
299 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
300 PRE_UsePreMigrationWallpaperInfo) {
301 // New user log in, a default wallpaper is loaded.
302 LogIn(kTestUser1, kTestUser1Hash);
303 WaitAsyncWallpaperLoad();
304 // Old wallpaper migration code doesn't exist in codebase anymore. So if
305 // user's profile is not migrated, it is the same as no wallpaper info. To
306 // simulate this, we remove user's wallpaper info here.
307 WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
310 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
311 UsePreMigrationWallpaperInfo) {
312 LogIn(kTestUser1, kTestUser1Hash);
313 WaitAsyncWallpaperLoad();
314 // This test should finish normally. If timeout, it is probably because chrome
315 // can not handle pre migrated user profile (M21 profile or older).
318 // Test for http://crbug.com/265689. When hooked up a large external monitor,
319 // the default large resolution wallpaper should load.
320 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
321 HotPlugInScreenAtGAIALoginScreen) {
322 UpdateDisplay("800x600");
323 // Set initial wallpaper to the default wallpaper.
324 WallpaperManager::Get()->SetDefaultWallpaper();
325 WaitAsyncWallpaperLoad();
327 // Hook up a 2000x2000 display. The large resolution custom wallpaper should
329 UpdateDisplay("800x600,2000x2000");
330 WaitAsyncWallpaperLoad();
333 class WallpaperManagerBrowserTestNoAnimation
334 : public WallpaperManagerBrowserTest {
336 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
337 command_line->AppendSwitch(switches::kLoginManager);
338 command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
339 command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
340 command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
344 // Same test as WallpaperManagerBrowserTest.UseMigratedWallpaperInfo. But
345 // disabled boot and login animation.
346 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
347 PRE_UseMigratedWallpaperInfo) {
348 // New user log in, a default wallpaper is loaded.
349 LogIn(kTestUser1, kTestUser1Hash);
350 WaitAsyncWallpaperLoad();
351 // Old wallpaper migration code doesn't exist in codebase anymore. Modify user
352 // wallpaper info directly to simulate the wallpaper migration. See
353 // crosbug.com/38429 for details about why we modify wallpaper info this way.
354 WallpaperInfo info = {
356 WALLPAPER_LAYOUT_CENTER_CROPPED,
358 base::Time::Now().LocalMidnight()
360 WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
363 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
364 UseMigratedWallpaperInfo) {
365 LogIn(kTestUser1, kTestUser1Hash);
366 WaitAsyncWallpaperLoad();
367 // This test should finish normally. If timeout, it is probably because
368 // migrated wallpaper is somehow not loaded. Bad things can happen if
369 // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
372 // Same test as WallpaperManagerBrowserTest.UsePreMigrationWallpaperInfo. But
373 // disabled boot and login animation.
374 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
375 PRE_UsePreMigrationWallpaperInfo) {
376 // New user log in, a default wallpaper is loaded.
377 LogIn(kTestUser1, kTestUser1Hash);
378 WaitAsyncWallpaperLoad();
379 // Old wallpaper migration code doesn't exist in codebase anymore. So if
380 // user's profile is not migrated, it is the same as no wallpaper info. To
381 // simulate this, we remove user's wallpaper info here.
382 WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
385 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
386 UsePreMigrationWallpaperInfo) {
387 LogIn(kTestUser1, kTestUser1Hash);
388 WaitAsyncWallpaperLoad();
389 // This test should finish normally. If timeout, it is probably because chrome
390 // can not handle pre migrated user profile (M21 profile or older).
393 class WallpaperManagerBrowserTestCrashRestore
394 : public WallpaperManagerBrowserTest {
396 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
397 command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
398 command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
399 command_line->AppendSwitch(::switches::kMultiProfiles);
400 command_line->AppendSwitchASCII(switches::kLoginUser, kTestUser1);
401 command_line->AppendSwitchASCII(switches::kLoginProfile,
402 CryptohomeClient::GetStubSanitizedUsername(kTestUser1));
406 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
407 PRE_RestoreWallpaper) {
408 LogIn(kTestUser1, kTestUser1Hash);
411 // Test for crbug.com/270278. It simulates a browser crash and verifies if user
412 // wallpaper is loaded.
413 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
415 EXPECT_EQ(1, LoadedWallpapers());
418 } // namespace chromeos