blob: 4c1cd243ad4b87ec9f32b7a26d1f5ff894a43042 [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 <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_writer.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/path_service.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/mock_user_manager.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_image.h"
#include "chrome/browser/chromeos/login/user_image_manager.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
#include "chrome/browser/chromeos/login/user_image_manager_test_util.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_downloader.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_dbus_thread_manager.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/policy_builder.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_utils.h"
#include "crypto/rsa_private_key.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_status.h"
#include "policy/proto/cloud_policy.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia.h"
#include "url/gurl.h"
namespace chromeos {
namespace {
const char kTestUser1[] = "test-user@example.com";
const char kTestUser2[] = "test-user2@example.com";
policy::CloudPolicyStore* GetStoreForUser(const User* user) {
Profile* profile = UserManager::Get()->GetProfileByUser(user);
if (!profile) {
ADD_FAILURE();
return NULL;
}
policy::UserCloudPolicyManagerChromeOS* policy_manager =
policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(profile);
if (!policy_manager) {
ADD_FAILURE();
return NULL;
}
return policy_manager->core()->store();
}
} // namespace
class UserImageManagerTest : public LoginManagerTest,
public UserManager::Observer {
protected:
UserImageManagerTest() : LoginManagerTest(true) {
}
// LoginManagerTest overrides:
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
LoginManagerTest::SetUpInProcessBrowserTestFixture();
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_));
}
virtual void SetUpOnMainThread() OVERRIDE {
LoginManagerTest::SetUpOnMainThread();
local_state_ = g_browser_process->local_state();
UserManager::Get()->AddObserver(this);
}
virtual void TearDownOnMainThread() OVERRIDE {
UserManager::Get()->RemoveObserver(this);
LoginManagerTest::TearDownOnMainThread();
}
// UserManager::Observer overrides:
virtual void LocalStateChanged(UserManager* user_manager) OVERRIDE {
if (run_loop_)
run_loop_->Quit();
}
// Logs in |username|.
void LogIn(const std::string& username) {
UserManager::Get()->UserLoggedIn(username, username, false);
}
// Stores old (pre-migration) user image info.
void SetOldUserImageInfo(const std::string& username,
int image_index,
const base::FilePath& image_path) {
RegisterUser(username);
DictionaryPrefUpdate images_pref(local_state_, "UserImages");
base::DictionaryValue* image_properties = new base::DictionaryValue();
image_properties->Set(
"index", base::Value::CreateIntegerValue(image_index));
image_properties->Set(
"path" , new base::StringValue(image_path.value()));
images_pref->SetWithoutPathExpansion(username, image_properties);
}
// Verifies user image info in |images_pref| dictionary.
void ExpectUserImageInfo(const base::DictionaryValue* images_pref,
const std::string& username,
int image_index,
const base::FilePath& image_path) {
ASSERT_TRUE(images_pref);
const base::DictionaryValue* image_properties = NULL;
images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
ASSERT_TRUE(image_properties);
int actual_image_index;
std::string actual_image_path;
ASSERT_TRUE(image_properties->GetInteger("index", &actual_image_index) &&
image_properties->GetString("path", &actual_image_path));
EXPECT_EQ(image_index, actual_image_index);
EXPECT_EQ(image_path.value(), actual_image_path);
}
// Verifies that there is no image info for |username| in dictionary
// |images_pref|.
void ExpectNoUserImageInfo(const base::DictionaryValue* images_pref,
const std::string& username) {
ASSERT_TRUE(images_pref);
const base::DictionaryValue* image_properties = NULL;
images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
ASSERT_FALSE(image_properties);
}
// Verifies that old user image info matches |image_index| and |image_path|
// and that new user image info does not exist.
void ExpectOldUserImageInfo(const std::string& username,
int image_index,
const base::FilePath& image_path) {
ExpectUserImageInfo(local_state_->GetDictionary("UserImages"),
username, image_index, image_path);
ExpectNoUserImageInfo(local_state_->GetDictionary("user_image_info"),
username);
}
// Verifies that new user image info matches |image_index| and |image_path|
// and that old user image info does not exist.
void ExpectNewUserImageInfo(const std::string& username,
int image_index,
const base::FilePath& image_path) {
ExpectUserImageInfo(local_state_->GetDictionary("user_image_info"),
username, image_index, image_path);
ExpectNoUserImageInfo(local_state_->GetDictionary("UserImages"),
username);
}
// Sets bitmap |resource_id| as image for |username| and saves it to disk.
void SaveUserImagePNG(const std::string& username,
int resource_id) {
base::FilePath image_path = GetUserImagePath(username, "png");
scoped_refptr<base::RefCountedStaticMemory> image_data(
ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
resource_id, ui::SCALE_FACTOR_100P));
int written = file_util::WriteFile(
image_path,
reinterpret_cast<const char*>(image_data->front()),
image_data->size());
EXPECT_EQ(static_cast<int>(image_data->size()), written);
SetOldUserImageInfo(username, User::kExternalImageIndex, image_path);
}
// Returns the image path for user |username| with specified |extension|.
base::FilePath GetUserImagePath(const std::string& username,
const std::string& extension) {
return user_data_dir_.Append(username).AddExtension(extension);
}
// Completes the download of all non-image profile data for the currently
// logged-in user. This method must only be called after a profile data
// download has been started.
// |url_fetcher_factory| will capture the net::TestURLFetcher created by the
// ProfileDownloader to download the profile image.
void CompleteProfileMetadataDownload(
net::TestURLFetcherFactory* url_fetcher_factory) {
ProfileDownloader* profile_downloader =
reinterpret_cast<UserImageManagerImpl*>(
UserManager::Get()->GetUserImageManager())->
profile_downloader_.get();
ASSERT_TRUE(profile_downloader);
static_cast<OAuth2TokenService::Consumer*>(profile_downloader)->
OnGetTokenSuccess(NULL,
std::string(),
base::Time::Now() + base::TimeDelta::FromDays(1));
net::TestURLFetcher* fetcher = url_fetcher_factory->GetFetcherByID(0);
ASSERT_TRUE(fetcher);
fetcher->SetResponseString(
"{ \"picture\": \"http://localhost/avatar.jpg\" }");
fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
net::OK));
fetcher->set_response_code(200);
fetcher->delegate()->OnURLFetchComplete(fetcher);
base::RunLoop().RunUntilIdle();
}
// Completes the download of the currently logged-in user's profile image.
// This method must only be called after a profile data download including
// the profile image has been started, the download of all non-image data has
// been completed by calling CompleteProfileMetadataDownload() and the
// net::TestURLFetcher created by the ProfileDownloader to download the
// profile image has been captured by |url_fetcher_factory|.
void CompleteProfileImageDownload(
net::TestURLFetcherFactory* url_fetcher_factory) {
std::string profile_image_data;
base::FilePath test_data_dir;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
EXPECT_TRUE(ReadFileToString(
test_data_dir.Append("chromeos").Append("avatar1.jpg"),
&profile_image_data));
base::RunLoop run_loop;
PrefChangeRegistrar pref_change_registrar;
pref_change_registrar.Init(local_state_);
pref_change_registrar.Add("UserDisplayName", run_loop.QuitClosure());
net::TestURLFetcher* fetcher = url_fetcher_factory->GetFetcherByID(0);
ASSERT_TRUE(fetcher);
fetcher->SetResponseString(profile_image_data);
fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
net::OK));
fetcher->set_response_code(200);
fetcher->delegate()->OnURLFetchComplete(fetcher);
run_loop.Run();
const User* user = UserManager::Get()->GetLoggedInUser();
ASSERT_TRUE(user);
const std::map<std::string, linked_ptr<UserImageManagerImpl::Job> >&
job_map = reinterpret_cast<UserImageManagerImpl*>(
UserManager::Get()->GetUserImageManager())->jobs_;
if (job_map.find(user->email()) != job_map.end()) {
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
}
}
base::FilePath test_data_dir_;
base::FilePath user_data_dir_;
PrefService* local_state_;
scoped_ptr<gfx::ImageSkia> decoded_image_;
scoped_ptr<base::RunLoop> run_loop_;
private:
DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
};
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_DefaultUserImagePreserved) {
// Setup an old default (stock) user image.
ScopedUserManagerEnabler(new MockUserManager);
SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DefaultUserImagePreserved) {
UserManager::Get()->GetUsers(); // Load users.
// Old info preserved.
ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
LogIn(kTestUser1);
// Image info is migrated now.
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_OtherUsersUnaffected) {
// Setup two users with stock images.
ScopedUserManagerEnabler(new MockUserManager);
SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
SetOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, OtherUsersUnaffected) {
UserManager::Get()->GetUsers(); // Load users.
// Old info preserved.
ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
base::FilePath());
LogIn(kTestUser1);
// Image info is migrated for the first user and unaffected for the rest.
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_PRE_NonJPEGImageFromFile) {
// Setup a user with non-JPEG image.
ScopedUserManagerEnabler(new MockUserManager);
SaveUserImagePNG(
kTestUser1, kDefaultImageResourceIDs[kFirstDefaultImageIndex]);
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_NonJPEGImageFromFile) {
UserManager::Get()->GetUsers(); // Load users.
// Old info preserved.
ExpectOldUserImageInfo(kTestUser1, User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "png"));
const User* user = UserManager::Get()->FindUser(kTestUser1);
EXPECT_TRUE(user->image_is_stub());
base::RunLoop run_loop;
PrefChangeRegistrar pref_change_registrar_;
pref_change_registrar_.Init(local_state_);
pref_change_registrar_.Add("UserImages", run_loop.QuitClosure());
LogIn(kTestUser1);
// Wait for migration.
run_loop.Run();
// Image info is migrated and the image is converted to JPG.
ExpectNewUserImageInfo(kTestUser1, User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
user = UserManager::Get()->GetLoggedInUser();
ASSERT_TRUE(user);
EXPECT_FALSE(user->image_is_safe_format());
// Check image dimensions.
const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
EXPECT_EQ(saved_image.width(), user->image().width());
EXPECT_EQ(saved_image.height(), user->image().height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, NonJPEGImageFromFile) {
UserManager::Get()->GetUsers(); // Load users.
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
// Wait for image load.
if (user->image_index() == User::kInvalidImageIndex) {
content::WindowedNotificationObserver(
chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
content::NotificationService::AllSources()).Wait();
}
// Now the migrated image is used.
EXPECT_TRUE(user->image_is_safe_format());
// Check image dimensions. Images can't be compared since JPEG is lossy.
const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
EXPECT_EQ(saved_image.width(), user->image().width());
EXPECT_EQ(saved_image.height(), user->image().height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserDefaultImageIndex) {
RegisterUser(kTestUser1);
}
// Verifies that SaveUserDefaultImageIndex() correctly sets and persists the
// chosen user image.
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserDefaultImageIndex) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
const gfx::ImageSkia& default_image =
GetDefaultImage(kFirstDefaultImageIndex);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserDefaultImageIndex(kTestUser1,
kFirstDefaultImageIndex);
EXPECT_TRUE(user->HasDefaultImage());
EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(default_image, user->image()));
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImage) {
RegisterUser(kTestUser1);
}
// Verifies that SaveUserImage() correctly sets and persists the chosen user
// image.
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImage) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
SkBitmap custom_image_bitmap;
custom_image_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
custom_image_bitmap.allocPixels();
custom_image_bitmap.setImmutable();
const gfx::ImageSkia custom_image =
gfx::ImageSkia::CreateFrom1xBitmap(custom_image_bitmap);
run_loop_.reset(new base::RunLoop);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserImage(kTestUser1,
UserImage::CreateAndEncode(custom_image));
run_loop_->Run();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(custom_image, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
const scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(custom_image.width(), saved_image->width());
EXPECT_EQ(custom_image.height(), saved_image->height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImageFromFile) {
RegisterUser(kTestUser1);
}
// Verifies that SaveUserImageFromFile() correctly sets and persists the chosen
// user image.
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromFile) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
const base::FilePath custom_image_path =
test_data_dir_.Append(test::kUserAvatarImage1RelativePath);
const scoped_ptr<gfx::ImageSkia> custom_image =
test::ImageLoader(custom_image_path).Load();
ASSERT_TRUE(custom_image);
run_loop_.reset(new base::RunLoop);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserImageFromFile(kTestUser1, custom_image_path);
run_loop_->Run();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*custom_image, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
const scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(custom_image->width(), saved_image->width());
EXPECT_EQ(custom_image->height(), saved_image->height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
PRE_SaveUserImageFromProfileImage) {
RegisterUser(kTestUser1);
chromeos::StartupUtils::MarkOobeCompleted();
}
// Verifies that SaveUserImageFromProfileImage() correctly downloads, sets and
// persists the chosen user image.
IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromProfileImage) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
LoginUser(kTestUser1);
run_loop_.reset(new base::RunLoop);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserImageFromProfileImage(kTestUser1);
run_loop_->Run();
net::TestURLFetcherFactory url_fetcher_factory;
CompleteProfileMetadataDownload(&url_fetcher_factory);
CompleteProfileImageDownload(&url_fetcher_factory);
const gfx::ImageSkia& profile_image =
user_image_manager->DownloadedProfileImage();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kProfileImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(profile_image, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kProfileImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
const scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(profile_image.width(), saved_image->width());
EXPECT_EQ(profile_image.height(), saved_image->height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
PRE_ProfileImageDownloadDoesNotClobber) {
RegisterUser(kTestUser1);
chromeos::StartupUtils::MarkOobeCompleted();
}
// Sets the user image to the profile image, then sets it to one of the default
// images while the profile image download is still in progress. Verifies that
// when the download completes, the profile image is ignored and does not
// clobber the default image chosen in the meantime.
IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
ProfileImageDownloadDoesNotClobber) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
const gfx::ImageSkia& default_image =
GetDefaultImage(kFirstDefaultImageIndex);
UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
LoginUser(kTestUser1);
run_loop_.reset(new base::RunLoop);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserImageFromProfileImage(kTestUser1);
run_loop_->Run();
net::TestURLFetcherFactory url_fetcher_factory;
CompleteProfileMetadataDownload(&url_fetcher_factory);
user_image_manager->SaveUserDefaultImageIndex(kTestUser1,
kFirstDefaultImageIndex);
CompleteProfileImageDownload(&url_fetcher_factory);
EXPECT_TRUE(user->HasDefaultImage());
EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(default_image, user->image()));
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
}
class UserImageManagerPolicyTest : public UserImageManagerTest,
public policy::CloudPolicyStore::Observer {
protected:
UserImageManagerPolicyTest()
: fake_dbus_thread_manager_(new chromeos::FakeDBusThreadManager),
fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {
fake_dbus_thread_manager_->SetFakeClients();
fake_dbus_thread_manager_->SetSessionManagerClient(
scoped_ptr<SessionManagerClient>(fake_session_manager_client_));
}
// UserImageManagerTest overrides:
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
DBusThreadManager::SetInstanceForTesting(fake_dbus_thread_manager_);
UserImageManagerTest::SetUpInProcessBrowserTestFixture();
}
virtual void SetUpOnMainThread() OVERRIDE {
UserImageManagerTest::SetUpOnMainThread();
base::FilePath user_keys_dir;
ASSERT_TRUE(PathService::Get(chromeos::DIR_USER_POLICY_KEYS,
&user_keys_dir));
const std::string sanitized_username =
chromeos::CryptohomeClient::GetStubSanitizedUsername(kTestUser1);
const base::FilePath user_key_file =
user_keys_dir.AppendASCII(sanitized_username)
.AppendASCII("policy.pub");
std::vector<uint8> user_key_bits;
ASSERT_TRUE(user_policy_.GetSigningKey()->ExportPublicKey(&user_key_bits));
ASSERT_TRUE(base::CreateDirectory(user_key_file.DirName()));
ASSERT_EQ(file_util::WriteFile(
user_key_file,
reinterpret_cast<const char*>(user_key_bits.data()),
user_key_bits.size()),
static_cast<int>(user_key_bits.size()));
user_policy_.policy_data().set_username(kTestUser1);
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
policy_image_ = test::ImageLoader(test_data_dir_.Append(
test::kUserAvatarImage2RelativePath)).Load();
ASSERT_TRUE(policy_image_);
}
// policy::CloudPolicyStore::Observer overrides:
virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE {
if (run_loop_)
run_loop_->Quit();
}
virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE {
if (run_loop_)
run_loop_->Quit();
}
std::string ConstructPolicy(const std::string& relative_path) {
std::string image_data;
if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
&image_data)) {
ADD_FAILURE();
}
std::string policy;
base::JSONWriter::Write(policy::test::ConstructExternalDataReference(
embedded_test_server()->GetURL(std::string("/") + relative_path).spec(),
image_data).get(),
&policy);
return policy;
}
policy::UserPolicyBuilder user_policy_;
FakeDBusThreadManager* fake_dbus_thread_manager_;
FakeSessionManagerClient* fake_session_manager_client_;
scoped_ptr<gfx::ImageSkia> policy_image_;
private:
DISALLOW_COPY_AND_ASSIGN(UserImageManagerPolicyTest);
};
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_SetAndClear) {
RegisterUser(kTestUser1);
chromeos::StartupUtils::MarkOobeCompleted();
}
// Verifies that the user image can be set through policy. Also verifies that
// after the policy has been cleared, the user is able to choose a different
// image.
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, SetAndClear) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
LoginUser(kTestUser1);
base::RunLoop().RunUntilIdle();
policy::CloudPolicyStore* store = GetStoreForUser(user);
ASSERT_TRUE(store);
// Set policy. Verify that the policy-provided user image is downloaded, set
// and persisted.
user_policy_.payload().mutable_useravatarimage()->set_value(
ConstructPolicy(test::kUserAvatarImage2RelativePath));
user_policy_.Build();
fake_session_manager_client_->set_user_policy(kTestUser1,
user_policy_.GetBlob());
run_loop_.reset(new base::RunLoop);
store->Load();
run_loop_->Run();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(policy_image_->width(), saved_image->width());
EXPECT_EQ(policy_image_->height(), saved_image->height());
// Clear policy. Verify that the policy-provided user image remains set as no
// different user image has been chosen yet.
user_policy_.payload().Clear();
user_policy_.Build();
fake_session_manager_client_->set_user_policy(kTestUser1,
user_policy_.GetBlob());
run_loop_.reset(new base::RunLoop);
store->AddObserver(this);
store->Load();
run_loop_->Run();
store->RemoveObserver(this);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
saved_image = test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(policy_image_->width(), saved_image->width());
EXPECT_EQ(policy_image_->height(), saved_image->height());
// Choose a different user image. Verify that the chosen user image is set and
// persisted.
const gfx::ImageSkia& default_image =
GetDefaultImage(kFirstDefaultImageIndex);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserDefaultImageIndex(kTestUser1,
kFirstDefaultImageIndex);
EXPECT_TRUE(user->HasDefaultImage());
EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(default_image, user->image()));
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_PolicyOverridesUser) {
RegisterUser(kTestUser1);
chromeos::StartupUtils::MarkOobeCompleted();
}
// Verifies that when the user chooses a user image and a different image is
// then set through policy, the policy takes precedence, overriding the
// previously chosen image.
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PolicyOverridesUser) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
LoginUser(kTestUser1);
base::RunLoop().RunUntilIdle();
policy::CloudPolicyStore* store = GetStoreForUser(user);
ASSERT_TRUE(store);
// Choose a user image. Verify that the chosen user image is set and
// persisted.
const gfx::ImageSkia& default_image =
GetDefaultImage(kFirstDefaultImageIndex);
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserDefaultImageIndex(kTestUser1,
kFirstDefaultImageIndex);
EXPECT_TRUE(user->HasDefaultImage());
EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(default_image, user->image()));
ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
// Set policy. Verify that the policy-provided user image is downloaded, set
// and persisted, overriding the previously set image.
user_policy_.payload().mutable_useravatarimage()->set_value(
ConstructPolicy(test::kUserAvatarImage2RelativePath));
user_policy_.Build();
fake_session_manager_client_->set_user_policy(kTestUser1,
user_policy_.GetBlob());
run_loop_.reset(new base::RunLoop);
store->Load();
run_loop_->Run();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(policy_image_->width(), saved_image->width());
EXPECT_EQ(policy_image_->height(), saved_image->height());
}
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest,
PRE_UserDoesNotOverridePolicy) {
RegisterUser(kTestUser1);
chromeos::StartupUtils::MarkOobeCompleted();
}
// Verifies that when the user image has been set through policy and the user
// chooses a different image, the policy takes precedence, preventing the user
// from overriding the previously chosen image.
IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, UserDoesNotOverridePolicy) {
const User* user = UserManager::Get()->FindUser(kTestUser1);
ASSERT_TRUE(user);
LoginUser(kTestUser1);
base::RunLoop().RunUntilIdle();
policy::CloudPolicyStore* store = GetStoreForUser(user);
ASSERT_TRUE(store);
// Set policy. Verify that the policy-provided user image is downloaded, set
// and persisted.
user_policy_.payload().mutable_useravatarimage()->set_value(
ConstructPolicy(test::kUserAvatarImage2RelativePath));
user_policy_.Build();
fake_session_manager_client_->set_user_policy(kTestUser1,
user_policy_.GetBlob());
run_loop_.reset(new base::RunLoop);
store->Load();
run_loop_->Run();
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
scoped_ptr<gfx::ImageSkia> saved_image =
test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(policy_image_->width(), saved_image->width());
EXPECT_EQ(policy_image_->height(), saved_image->height());
// Choose a different user image. Verify that the user image does not change
// as policy takes precedence.
UserImageManager* user_image_manager =
UserManager::Get()->GetUserImageManager();
user_image_manager->SaveUserDefaultImageIndex(kTestUser1,
kFirstDefaultImageIndex);
EXPECT_FALSE(user->HasDefaultImage());
EXPECT_EQ(User::kExternalImageIndex, user->image_index());
EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->image()));
ExpectNewUserImageInfo(kTestUser1,
User::kExternalImageIndex,
GetUserImagePath(kTestUser1, "jpg"));
saved_image = test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
ASSERT_TRUE(saved_image);
// Check image dimensions. Images can't be compared since JPEG is lossy.
EXPECT_EQ(policy_image_->width(), saved_image->width());
EXPECT_EQ(policy_image_->height(), saved_image->height());
}
} // namespace chromeos