blob: bf7c640fdacbd7c2987ab329ed0882632a6b54ee [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/login/wallpaper_manager.h"
#include "ash/ash_resources/grit/ash_resources.h"
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/desktop_background/desktop_background_controller_observer.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ash/test/display_manager_test_api.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "ui/aura/env.h"
#include "ui/base/resource/resource_bundle.h"
using namespace ash;
namespace chromeos {
namespace {
const int kLargeWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_LARGE;
const int kSmallWallpaperResourceId = IDR_AURA_WALLPAPER_DEFAULT_SMALL;
int kLargeWallpaperWidth = 256;
int kLargeWallpaperHeight = ash::kLargeWallpaperMaxHeight;
int kSmallWallpaperWidth = 256;
int kSmallWallpaperHeight = ash::kSmallWallpaperMaxHeight;
const char kTestUser1[] = "test@domain.com";
const char kTestUser1Hash[] = "test@domain.com-hash";
} // namespace
class WallpaperManagerBrowserTest : public InProcessBrowserTest,
public DesktopBackgroundControllerObserver {
public:
WallpaperManagerBrowserTest () : controller_(NULL),
local_state_(NULL) {
}
virtual ~WallpaperManagerBrowserTest () {}
virtual void SetUpOnMainThread() OVERRIDE {
controller_ = ash::Shell::GetInstance()->desktop_background_controller();
controller_->AddObserver(this);
local_state_ = g_browser_process->local_state();
UpdateDisplay("800x600");
}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kLoginManager);
command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
}
virtual void CleanUpOnMainThread() OVERRIDE {
controller_->RemoveObserver(this);
controller_ = NULL;
}
// Update the display configuration as given in |display_specs|.
// See ash::test::DisplayManagerTestApi::UpdateDisplay for more
// details.
void UpdateDisplay(const std::string& display_specs) {
ash::test::DisplayManagerTestApi display_manager_test_api(
ash::Shell::GetInstance()->display_manager());
display_manager_test_api.UpdateDisplay(display_specs);
}
void WaitAsyncWallpaperLoad() {
base::MessageLoop::current()->Run();
}
virtual void OnWallpaperDataChanged() OVERRIDE {
base::MessageLoop::current()->Quit();
}
protected:
// Return custom wallpaper path. Create directory if not exist.
base::FilePath GetCustomWallpaperPath(const char* sub_dir,
const std::string& username_hash,
const std::string& id) {
base::FilePath wallpaper_path =
WallpaperManager::Get()->GetCustomWallpaperPath(sub_dir,
username_hash,
id);
if (!base::DirectoryExists(wallpaper_path.DirName()))
file_util::CreateDirectory(wallpaper_path.DirName());
return wallpaper_path;
}
// Logs in |username|.
void LogIn(const std::string& username, const std::string& username_hash) {
UserManager::Get()->UserLoggedIn(username, username_hash, false);
}
// Saves bitmap |resource_id| to disk.
void SaveUserWallpaperData(const std::string& username,
const base::FilePath& wallpaper_path,
int resource_id) {
scoped_refptr<base::RefCountedStaticMemory> image_data(
ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
resource_id, ui::SCALE_FACTOR_100P));
int written = file_util::WriteFile(
wallpaper_path,
reinterpret_cast<const char*>(image_data->front()),
image_data->size());
EXPECT_EQ(static_cast<int>(image_data->size()), written);
}
int LoadedWallpapers() {
return WallpaperManager::Get()->loaded_wallpapers();
}
DesktopBackgroundController* controller_;
PrefService* local_state_;
private:
DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest);
};
// Tests that the appropriate custom wallpaper (large vs. small) is loaded
// depending on the desktop resolution.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
LoadCustomLargeWallpaperForLargeExternalScreen) {
WallpaperManager* wallpaper_manager = WallpaperManager::Get();
LogIn(kTestUser1, kTestUser1Hash);
// Wait for default wallpaper loaded.
WaitAsyncWallpaperLoad();
std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
kSmallWallpaperSubDir,
kTestUser1Hash,
id);
base::FilePath large_wallpaper_path = GetCustomWallpaperPath(
kLargeWallpaperSubDir,
kTestUser1Hash,
id);
// Saves the small/large resolution wallpapers to small/large custom
// wallpaper paths.
SaveUserWallpaperData(kTestUser1,
small_wallpaper_path,
kSmallWallpaperResourceId);
SaveUserWallpaperData(kTestUser1,
large_wallpaper_path,
kLargeWallpaperResourceId);
std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
// Saves wallpaper info to local state for user |kTestUser1|.
WallpaperInfo info = {
relative_path,
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::CUSTOMIZED,
base::Time::Now().LocalMidnight()
};
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
// Set the wallpaper for |kTestUser1|.
wallpaper_manager->SetUserWallpaper(kTestUser1);
WaitAsyncWallpaperLoad();
gfx::ImageSkia wallpaper = controller_->GetWallpaper();
// Display is initialized to 800x600. The small resolution custom wallpaper is
// expected.
EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
// Hook up another 800x600 display.
UpdateDisplay("800x600,800x600");
WaitAsyncWallpaperLoad();
// The small resolution custom wallpaper is expected.
EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
// Detach the secondary display.
UpdateDisplay("800x600");
// Hook up a 2000x2000 display. The large resolution custom wallpaper should
// be loaded.
UpdateDisplay("800x600,2000x2000");
WaitAsyncWallpaperLoad();
wallpaper = controller_->GetWallpaper();
// The large resolution custom wallpaper is expected.
EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
// Detach the secondary display.
UpdateDisplay("800x600");
// Hook up the 2000x2000 display again. The large resolution default wallpaper
// should persist. Test for crbug/165788.
UpdateDisplay("800x600,2000x2000");
WaitAsyncWallpaperLoad();
wallpaper = controller_->GetWallpaper();
// The large resolution custom wallpaper is expected.
EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
}
// If chrome tries to reload the same wallpaper twice, the latter request should
// be prevented. Otherwise, there are some strange animation issues as
// described in crbug.com/158383.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
PreventReloadingSameWallpaper) {
WallpaperManager* wallpaper_manager = WallpaperManager::Get();
// New user log in, a default wallpaper is loaded.
LogIn(kTestUser1, kTestUser1Hash);
EXPECT_EQ(1, LoadedWallpapers());
// Loads the same wallpaper before the initial one finished. It should be
// prevented.
wallpaper_manager->SetUserWallpaper(kTestUser1);
EXPECT_EQ(1, LoadedWallpapers());
WaitAsyncWallpaperLoad();
// Loads the same wallpaper after the initial one finished. It should be
// prevented.
wallpaper_manager->SetUserWallpaper(kTestUser1);
EXPECT_EQ(1, LoadedWallpapers());
wallpaper_manager->ClearWallpaperCache();
// Change wallpaper to a custom wallpaper.
std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
kSmallWallpaperSubDir,
kTestUser1Hash,
id);
SaveUserWallpaperData(kTestUser1,
small_wallpaper_path,
kSmallWallpaperResourceId);
std::string relative_path = base::FilePath(kTestUser1Hash).Append(id).value();
// Saves wallpaper info to local state for user |kTestUser1|.
WallpaperInfo info = {
relative_path,
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::CUSTOMIZED,
base::Time::Now().LocalMidnight()
};
wallpaper_manager->SetUserWallpaperInfo(kTestUser1, info, true);
wallpaper_manager->SetUserWallpaper(kTestUser1);
EXPECT_EQ(2, LoadedWallpapers());
// Loads the same wallpaper before the initial one finished. It should be
// prevented.
wallpaper_manager->SetUserWallpaper(kTestUser1);
EXPECT_EQ(2, LoadedWallpapers());
WaitAsyncWallpaperLoad();
wallpaper_manager->SetUserWallpaper(kTestUser1);
EXPECT_EQ(2, LoadedWallpapers());
}
// Some users have old user profiles which may have legacy wallpapers. And these
// lagacy wallpapers should migrate to new wallpaper picker version seamlessly.
// This tests make sure we compatible with migrated old wallpapers.
// crosbug.com/38429
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
PRE_UseMigratedWallpaperInfo) {
// New user log in, a default wallpaper is loaded.
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// Old wallpaper migration code doesn't exist in codebase anymore. Modify user
// wallpaper info directly to simulate the wallpaper migration. See
// crosbug.com/38429 for details about why we modify wallpaper info this way.
WallpaperInfo info = {
"123",
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::DEFAULT,
base::Time::Now().LocalMidnight()
};
WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
}
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
UseMigratedWallpaperInfo) {
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// This test should finish normally. If timeout, it is probably because
// migrated wallpaper is somehow not loaded. Bad things can happen if
// wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
}
// Some users have old user profiles which may never get a chance to migrate.
// This tests make sure we compatible with these profiles.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
PRE_UsePreMigrationWallpaperInfo) {
// New user log in, a default wallpaper is loaded.
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// Old wallpaper migration code doesn't exist in codebase anymore. So if
// user's profile is not migrated, it is the same as no wallpaper info. To
// simulate this, we remove user's wallpaper info here.
WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
}
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
UsePreMigrationWallpaperInfo) {
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// This test should finish normally. If timeout, it is probably because chrome
// can not handle pre migrated user profile (M21 profile or older).
}
// Test for http://crbug.com/265689. When hooked up a large external monitor,
// the default large resolution wallpaper should load.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
HotPlugInScreenAtGAIALoginScreen) {
UpdateDisplay("800x600");
// Set initial wallpaper to the default wallpaper.
WallpaperManager::Get()->SetDefaultWallpaper();
WaitAsyncWallpaperLoad();
// Hook up a 2000x2000 display. The large resolution custom wallpaper should
// be loaded.
UpdateDisplay("800x600,2000x2000");
WaitAsyncWallpaperLoad();
}
class WallpaperManagerBrowserTestNoAnimation
: public WallpaperManagerBrowserTest {
public:
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(switches::kLoginManager);
command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
}
};
// Same test as WallpaperManagerBrowserTest.UseMigratedWallpaperInfo. But
// disabled boot and login animation.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
PRE_UseMigratedWallpaperInfo) {
// New user log in, a default wallpaper is loaded.
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// Old wallpaper migration code doesn't exist in codebase anymore. Modify user
// wallpaper info directly to simulate the wallpaper migration. See
// crosbug.com/38429 for details about why we modify wallpaper info this way.
WallpaperInfo info = {
"123",
WALLPAPER_LAYOUT_CENTER_CROPPED,
User::DEFAULT,
base::Time::Now().LocalMidnight()
};
WallpaperManager::Get()->SetUserWallpaperInfo(kTestUser1, info, true);
}
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
UseMigratedWallpaperInfo) {
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// This test should finish normally. If timeout, it is probably because
// migrated wallpaper is somehow not loaded. Bad things can happen if
// wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
}
// Same test as WallpaperManagerBrowserTest.UsePreMigrationWallpaperInfo. But
// disabled boot and login animation.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
PRE_UsePreMigrationWallpaperInfo) {
// New user log in, a default wallpaper is loaded.
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// Old wallpaper migration code doesn't exist in codebase anymore. So if
// user's profile is not migrated, it is the same as no wallpaper info. To
// simulate this, we remove user's wallpaper info here.
WallpaperManager::Get()->RemoveUserWallpaperInfo(kTestUser1);
}
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
UsePreMigrationWallpaperInfo) {
LogIn(kTestUser1, kTestUser1Hash);
WaitAsyncWallpaperLoad();
// This test should finish normally. If timeout, it is probably because chrome
// can not handle pre migrated user profile (M21 profile or older).
}
class WallpaperManagerBrowserTestCrashRestore
: public WallpaperManagerBrowserTest {
public:
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
command_line->AppendSwitch(::switches::kMultiProfiles);
command_line->AppendSwitchASCII(switches::kLoginUser, kTestUser1);
command_line->AppendSwitchASCII(switches::kLoginProfile,
CryptohomeClient::GetStubSanitizedUsername(kTestUser1));
}
};
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
PRE_RestoreWallpaper) {
LogIn(kTestUser1, kTestUser1Hash);
}
// Test for crbug.com/270278. It simulates a browser crash and verifies if user
// wallpaper is loaded.
IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
RestoreWallpaper) {
EXPECT_EQ(1, LoadedWallpapers());
}
} // namespace chromeos