• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/chromeos/login/wallpaper_manager.h"
6 
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/files/file_path.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/path_service.h"
18 #include "base/prefs/scoped_user_pref_update.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/time/time.h"
21 #include "base/values.h"
22 #include "chrome/browser/chromeos/login/user.h"
23 #include "chrome/browser/chromeos/login/user_manager.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/test/base/in_process_browser_test.h"
27 #include "chrome/test/base/testing_browser_process.h"
28 #include "chromeos/chromeos_switches.h"
29 #include "chromeos/dbus/cryptohome_client.h"
30 #include "content/public/test/test_utils.h"
31 #include "ui/aura/env.h"
32 #include "ui/base/resource/resource_bundle.h"
33 
34 using namespace ash;
35 
36 namespace chromeos {
37 
38 namespace {
39 
40 const int kLargeWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_LARGE;
41 const int kSmallWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_SMALL;
42 
43 int kLargeWallpaperWidth = 256;
44 int kLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
45 int kSmallWallpaperWidth = 256;
46 int kSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
47 
48 const char kTestUser1[] = "test@domain.com";
49 const char kTestUser1Hash[] = "test@domain.com-hash";
50 
51 }  // namespace
52 
53 class WallpaperManagerBrowserTest : public InProcessBrowserTest,
54                                     public DesktopBackgroundControllerObserver {
55  public:
WallpaperManagerBrowserTest()56   WallpaperManagerBrowserTest () : controller_(NULL),
57                                    local_state_(NULL) {
58   }
59 
~WallpaperManagerBrowserTest()60   virtual ~WallpaperManagerBrowserTest () {}
61 
SetUpOnMainThread()62   virtual void SetUpOnMainThread() OVERRIDE {
63     controller_ = ash::Shell::GetInstance()->desktop_background_controller();
64     controller_->AddObserver(this);
65     local_state_ = g_browser_process->local_state();
66     UpdateDisplay("800x600");
67   }
68 
SetUpCommandLine(CommandLine * command_line)69   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
70     command_line->AppendSwitch(switches::kLoginManager);
71     command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
72   }
73 
CleanUpOnMainThread()74   virtual void CleanUpOnMainThread() OVERRIDE {
75     controller_->RemoveObserver(this);
76     controller_ = NULL;
77   }
78 
79   // Update the display configuration as given in |display_specs|.
80   // See ash::test::DisplayManagerTestApi::UpdateDisplay for more
81   // details.
UpdateDisplay(const std::string & display_specs)82   void UpdateDisplay(const std::string& display_specs) {
83     ash::test::DisplayManagerTestApi display_manager_test_api(
84         ash::Shell::GetInstance()->display_manager());
85     display_manager_test_api.UpdateDisplay(display_specs);
86   }
87 
WaitAsyncWallpaperLoad()88   void WaitAsyncWallpaperLoad() {
89     base::MessageLoop::current()->Run();
90   }
91 
OnWallpaperDataChanged()92   virtual void OnWallpaperDataChanged() OVERRIDE {
93     base::MessageLoop::current()->Quit();
94   }
95 
96  protected:
97   // Return custom wallpaper path. Create directory if not exist.
GetCustomWallpaperPath(const char * sub_dir,const std::string & username_hash,const std::string & id)98   base::FilePath GetCustomWallpaperPath(const char* sub_dir,
99                                         const std::string& username_hash,
100                                         const std::string& id) {
101     base::FilePath wallpaper_path =
102         WallpaperManager::Get()->GetCustomWallpaperPath(sub_dir,
103                                                         username_hash,
104                                                         id);
105     if (!base::DirectoryExists(wallpaper_path.DirName()))
106       base::CreateDirectory(wallpaper_path.DirName());
107 
108     return wallpaper_path;
109   }
110 
111   // Logs in |username|.
LogIn(const std::string & username,const std::string & username_hash)112   void LogIn(const std::string& username, const std::string& username_hash) {
113     UserManager::Get()->UserLoggedIn(username, username_hash, false);
114   }
115 
116   // Saves bitmap |resource_id| to disk.
SaveUserWallpaperData(const base::FilePath & wallpaper_path,int resource_id)117   void SaveUserWallpaperData(const base::FilePath& wallpaper_path,
118                              int resource_id) {
119     scoped_refptr<base::RefCountedStaticMemory> image_data(
120         ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
121             resource_id, ui::SCALE_FACTOR_100P));
122     int written = file_util::WriteFile(
123         wallpaper_path,
124         reinterpret_cast<const char*>(image_data->front()),
125         image_data->size());
126     EXPECT_EQ(static_cast<int>(image_data->size()), written);
127   }
128 
LoadedWallpapers()129   int LoadedWallpapers() {
130     return WallpaperManager::Get()->loaded_wallpapers();
131   }
132 
133   DesktopBackgroundController* controller_;
134   PrefService* local_state_;
135 
136  private:
137   DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest);
138 };
139 
140 // Tests that the appropriate custom wallpaper (large vs. small) is loaded
141 // depending on the desktop resolution.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,LoadCustomLargeWallpaperForLargeExternalScreen)142 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
143                        LoadCustomLargeWallpaperForLargeExternalScreen) {
144   WallpaperManager* wallpaper_manager = WallpaperManager::Get();
145   LogIn(kTestUser1, kTestUser1Hash);
146   // Wait for default wallpaper loaded.
147   WaitAsyncWallpaperLoad();
148   std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
149   base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
150       kSmallWallpaperSubDir,
151       kTestUser1Hash,
152       id);
153   base::FilePath large_wallpaper_path = GetCustomWallpaperPath(
154       kLargeWallpaperSubDir,
155       kTestUser1Hash,
156       id);
157 
158   // Saves the small/large resolution wallpapers to small/large custom
159   // wallpaper paths.
160   SaveUserWallpaperData(small_wallpaper_path,
161                         kSmallWallpaperResourceId);
162   SaveUserWallpaperData(large_wallpaper_path,
163                         kLargeWallpaperResourceId);
164 
165   std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
166   // Saves wallpaper info to local state for user |kTestUser1|.
167   WallpaperInfo info = {
168       relative_path,
169       WALLPAPER_LAYOUT_CENTER_CROPPED,
170       User::CUSTOMIZED,
171       base::Time::Now().LocalMidnight()
172   };
173   wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
174 
175   // Set the wallpaper for |kTestUser1|.
176   wallpaper_manager->SetUserWallpaper(kTestUser1);
177   WaitAsyncWallpaperLoad();
178   gfx::ImageSkia wallpaper = controller_->GetWallpaper();
179 
180   // Display is initialized to 800x600. The small resolution custom wallpaper is
181   // expected.
182   EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
183   EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
184 
185   // Hook up another 800x600 display. This shouldn't trigger a reload.
186   UpdateDisplay("800x600,800x600");
187   content::RunAllPendingInMessageLoop();
188   // The small resolution custom wallpaper is expected.
189   EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
190   EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
191 
192   // Detach the secondary display.
193   UpdateDisplay("800x600");
194   // Hook up a 2000x2000 display. The large resolution custom wallpaper should
195   // be loaded.
196   UpdateDisplay("800x600,2000x2000");
197   WaitAsyncWallpaperLoad();
198   wallpaper = controller_->GetWallpaper();
199 
200   // The large resolution custom wallpaper is expected.
201   EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
202   EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
203 
204   // Detach the secondary display.
205   UpdateDisplay("800x600");
206   // Hook up the 2000x2000 display again. The large resolution default wallpaper
207   // should persist. Test for crbug/165788.
208   UpdateDisplay("800x600,2000x2000");
209   WaitAsyncWallpaperLoad();
210   wallpaper = controller_->GetWallpaper();
211 
212   // The large resolution custom wallpaper is expected.
213   EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
214   EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
215 }
216 
217 // If chrome tries to reload the same wallpaper twice, the latter request should
218 // be prevented. Otherwise, there are some strange animation issues as
219 // described in crbug.com/158383.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,PreventReloadingSameWallpaper)220 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
221                        PreventReloadingSameWallpaper) {
222   WallpaperManager* wallpaper_manager = WallpaperManager::Get();
223   // New user log in, a default wallpaper is loaded.
224   LogIn(kTestUser1, kTestUser1Hash);
225   EXPECT_EQ(1, LoadedWallpapers());
226   // Loads the same wallpaper before the initial one finished. It should be
227   // prevented.
228   wallpaper_manager->SetUserWallpaper(kTestUser1);
229   EXPECT_EQ(1, LoadedWallpapers());
230   WaitAsyncWallpaperLoad();
231   // Loads the same wallpaper after the initial one finished. It should be
232   // prevented.
233   wallpaper_manager->SetUserWallpaper(kTestUser1);
234   EXPECT_EQ(1, LoadedWallpapers());
235   wallpaper_manager->ClearWallpaperCache();
236 
237   // Change wallpaper to a custom wallpaper.
238   std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
239   base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
240       kSmallWallpaperSubDir,
241       kTestUser1Hash,
242       id);
243   SaveUserWallpaperData(small_wallpaper_path,
244                         kSmallWallpaperResourceId);
245 
246   std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
247   // Saves wallpaper info to local state for user |kTestUser1|.
248   WallpaperInfo info = {
249       relative_path,
250       WALLPAPER_LAYOUT_CENTER_CROPPED,
251       User::CUSTOMIZED,
252       base::Time::Now().LocalMidnight()
253   };
254   wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
255 
256   wallpaper_manager->SetUserWallpaper(kTestUser1);
257   EXPECT_EQ(2, LoadedWallpapers());
258   // Loads the same wallpaper before the initial one finished. It should be
259   // prevented.
260   wallpaper_manager->SetUserWallpaper(kTestUser1);
261   EXPECT_EQ(2, LoadedWallpapers());
262   WaitAsyncWallpaperLoad();
263   wallpaper_manager->SetUserWallpaper(kTestUser1);
264   EXPECT_EQ(2, LoadedWallpapers());
265 }
266 
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.
270 // crosbug.com/38429
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,PRE_UseMigratedWallpaperInfo)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 = {
280       "123",
281       WALLPAPER_LAYOUT_CENTER_CROPPED,
282       User::DEFAULT,
283       base::Time::Now().LocalMidnight()
284   };
285   base::FilePath user_data_dir;
286   ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
287   SaveUserWallpaperData(user_data_dir.Append("123"),
288                         kLargeWallpaperResourceId);
289   WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
290 }
291 
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,UseMigratedWallpaperInfo)292 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
293                        UseMigratedWallpaperInfo) {
294   LogIn(kTestUser1, kTestUser1Hash);
295   WaitAsyncWallpaperLoad();
296   // This test should finish normally. If timeout, it is probably because
297   // migrated wallpaper is somehow not loaded. Bad things can happen if
298   // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
299 }
300 
301 // Some users have old user profiles which may never get a chance to migrate.
302 // This tests make sure we compatible with these profiles.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,PRE_UsePreMigrationWallpaperInfo)303 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
304                        PRE_UsePreMigrationWallpaperInfo) {
305   // New user log in, a default wallpaper is loaded.
306   LogIn(kTestUser1, kTestUser1Hash);
307   WaitAsyncWallpaperLoad();
308   // Old wallpaper migration code doesn't exist in codebase anymore. So if
309   // user's profile is not migrated, it is the same as no wallpaper info. To
310   // simulate this, we remove user's wallpaper info here.
311   WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
312 }
313 
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,UsePreMigrationWallpaperInfo)314 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
315                        UsePreMigrationWallpaperInfo) {
316   LogIn(kTestUser1, kTestUser1Hash);
317   WaitAsyncWallpaperLoad();
318   // This test should finish normally. If timeout, it is probably because chrome
319   // can not handle pre migrated user profile (M21 profile or older).
320 }
321 
322 // Test for http://crbug.com/265689. When hooked up a large external monitor,
323 // the default large resolution wallpaper should load.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,HotPlugInScreenAtGAIALoginScreen)324 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
325                        HotPlugInScreenAtGAIALoginScreen) {
326   UpdateDisplay("800x600");
327   // Set initial wallpaper to the default wallpaper.
328   WallpaperManager::Get()->SetDefaultWallpaper();
329   WaitAsyncWallpaperLoad();
330 
331   // Hook up a 2000x2000 display. The large resolution custom wallpaper should
332   // be loaded.
333   UpdateDisplay("800x600,2000x2000");
334   WaitAsyncWallpaperLoad();
335 }
336 
337 class WallpaperManagerBrowserTestNoAnimation
338     : public WallpaperManagerBrowserTest {
339  public:
SetUpCommandLine(CommandLine * command_line)340   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
341     command_line->AppendSwitch(switches::kLoginManager);
342     command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
343     command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
344     command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
345   }
346 };
347 
348 // Same test as WallpaperManagerBrowserTest.UseMigratedWallpaperInfo. But
349 // disabled boot and login animation.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,PRE_UseMigratedWallpaperInfo)350 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
351                        PRE_UseMigratedWallpaperInfo) {
352   // New user log in, a default wallpaper is loaded.
353   LogIn(kTestUser1, kTestUser1Hash);
354   WaitAsyncWallpaperLoad();
355   // Old wallpaper migration code doesn't exist in codebase anymore. Modify user
356   // wallpaper info directly to simulate the wallpaper migration. See
357   // crosbug.com/38429 for details about why we modify wallpaper info this way.
358   WallpaperInfo info = {
359       "123",
360       WALLPAPER_LAYOUT_CENTER_CROPPED,
361       User::DEFAULT,
362       base::Time::Now().LocalMidnight()
363   };
364   base::FilePath user_data_dir;
365   ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
366   SaveUserWallpaperData(user_data_dir.Append("123"),
367                         kLargeWallpaperResourceId);
368   WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
369 }
370 
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,UseMigratedWallpaperInfo)371 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
372                        UseMigratedWallpaperInfo) {
373   LogIn(kTestUser1, kTestUser1Hash);
374   WaitAsyncWallpaperLoad();
375   // This test should finish normally. If timeout, it is probably because
376   // migrated wallpaper is somehow not loaded. Bad things can happen if
377   // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
378 }
379 
380 // Same test as WallpaperManagerBrowserTest.UsePreMigrationWallpaperInfo. But
381 // disabled boot and login animation.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,PRE_UsePreMigrationWallpaperInfo)382 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
383                        PRE_UsePreMigrationWallpaperInfo) {
384   // New user log in, a default wallpaper is loaded.
385   LogIn(kTestUser1, kTestUser1Hash);
386   WaitAsyncWallpaperLoad();
387   // Old wallpaper migration code doesn't exist in codebase anymore. So if
388   // user's profile is not migrated, it is the same as no wallpaper info. To
389   // simulate this, we remove user's wallpaper info here.
390   WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
391 }
392 
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,UsePreMigrationWallpaperInfo)393 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
394                        UsePreMigrationWallpaperInfo) {
395   LogIn(kTestUser1, kTestUser1Hash);
396   WaitAsyncWallpaperLoad();
397   // This test should finish normally. If timeout, it is probably because chrome
398   // can not handle pre migrated user profile (M21 profile or older).
399 }
400 
401 class WallpaperManagerBrowserTestCrashRestore
402     : public WallpaperManagerBrowserTest {
403  public:
SetUpCommandLine(CommandLine * command_line)404   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
405     command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
406     command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
407     command_line->AppendSwitch(::switches::kMultiProfiles);
408     command_line->AppendSwitchASCII(switches::kLoginUser, kTestUser1);
409     command_line->AppendSwitchASCII(switches::kLoginProfile,
410         CryptohomeClient::GetStubSanitizedUsername(kTestUser1));
411   }
412 };
413 
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,PRE_RestoreWallpaper)414 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
415                        PRE_RestoreWallpaper) {
416   LogIn(kTestUser1, kTestUser1Hash);
417 }
418 
419 // Test for crbug.com/270278. It simulates a browser crash and verifies if user
420 // wallpaper is loaded.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,RestoreWallpaper)421 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
422                        RestoreWallpaper) {
423   EXPECT_EQ(1, LoadedWallpapers());
424 }
425 
426 }  // namespace chromeos
427