user_image_manager_browsertest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright 2014 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 <map>
6#include <string>
7#include <vector>
8
9#include "base/basictypes.h"
10#include "base/compiler_specific.h"
11#include "base/file_util.h"
12#include "base/files/file_path.h"
13#include "base/json/json_writer.h"
14#include "base/memory/linked_ptr.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/ref_counted_memory.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/message_loop/message_loop_proxy.h"
19#include "base/path_service.h"
20#include "base/prefs/pref_change_registrar.h"
21#include "base/prefs/pref_service.h"
22#include "base/prefs/scoped_user_pref_update.h"
23#include "base/run_loop.h"
24#include "base/time/time.h"
25#include "base/values.h"
26#include "chrome/browser/browser_process.h"
27#include "chrome/browser/chrome_notification_types.h"
28#include "chrome/browser/chromeos/login/login_manager_test.h"
29#include "chrome/browser/chromeos/login/startup_utils.h"
30#include "chrome/browser/chromeos/login/users/avatar/default_user_images.h"
31#include "chrome/browser/chromeos/login/users/avatar/user_image.h"
32#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
33#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
34#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
35#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
36#include "chrome/browser/chromeos/login/users/user.h"
37#include "chrome/browser/chromeos/login/users/user_manager.h"
38#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
39#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
40#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
41#include "chrome/browser/profiles/profile.h"
42#include "chrome/browser/profiles/profile_downloader.h"
43#include "chrome/common/chrome_paths.h"
44#include "chrome/test/base/in_process_browser_test.h"
45#include "chrome/test/base/testing_browser_process.h"
46#include "chromeos/chromeos_paths.h"
47#include "chromeos/dbus/cryptohome_client.h"
48#include "chromeos/dbus/dbus_thread_manager.h"
49#include "chromeos/dbus/fake_dbus_thread_manager.h"
50#include "chromeos/dbus/fake_session_manager_client.h"
51#include "chromeos/dbus/session_manager_client.h"
52#include "components/policy/core/common/cloud/cloud_policy_core.h"
53#include "components/policy/core/common/cloud/cloud_policy_store.h"
54#include "components/policy/core/common/cloud/policy_builder.h"
55#include "content/public/browser/notification_service.h"
56#include "content/public/browser/notification_source.h"
57#include "content/public/test/test_utils.h"
58#include "crypto/rsa_private_key.h"
59#include "google_apis/gaia/gaia_oauth_client.h"
60#include "google_apis/gaia/oauth2_token_service.h"
61#include "net/test/embedded_test_server/embedded_test_server.h"
62#include "net/url_request/test_url_fetcher_factory.h"
63#include "net/url_request/url_fetcher_delegate.h"
64#include "net/url_request/url_request_status.h"
65#include "policy/proto/cloud_policy.pb.h"
66#include "testing/gtest/include/gtest/gtest.h"
67#include "third_party/skia/include/core/SkBitmap.h"
68#include "ui/base/layout.h"
69#include "ui/base/resource/resource_bundle.h"
70#include "ui/gfx/image/image_skia.h"
71#include "url/gurl.h"
72
73namespace chromeos {
74
75namespace {
76
77const char kTestUser1[] = "test-user@example.com";
78const char kTestUser2[] = "test-user2@example.com";
79
80policy::CloudPolicyStore* GetStoreForUser(const User* user) {
81  Profile* profile = UserManager::Get()->GetProfileByUser(user);
82  if (!profile) {
83    ADD_FAILURE();
84    return NULL;
85  }
86  policy::UserCloudPolicyManagerChromeOS* policy_manager =
87      policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(profile);
88  if (!policy_manager) {
89    ADD_FAILURE();
90    return NULL;
91  }
92  return policy_manager->core()->store();
93}
94
95}  // namespace
96
97class UserImageManagerTest : public LoginManagerTest,
98                             public UserManager::Observer {
99 protected:
100  UserImageManagerTest() : LoginManagerTest(true) {
101  }
102
103  // LoginManagerTest overrides:
104  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
105    LoginManagerTest::SetUpInProcessBrowserTestFixture();
106
107    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
108    ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_));
109  }
110
111  virtual void SetUpOnMainThread() OVERRIDE {
112    LoginManagerTest::SetUpOnMainThread();
113    local_state_ = g_browser_process->local_state();
114    UserManager::Get()->AddObserver(this);
115  }
116
117  virtual void TearDownOnMainThread() OVERRIDE {
118    UserManager::Get()->RemoveObserver(this);
119    LoginManagerTest::TearDownOnMainThread();
120  }
121
122  // UserManager::Observer overrides:
123  virtual void LocalStateChanged(UserManager* user_manager) OVERRIDE {
124    if (run_loop_)
125      run_loop_->Quit();
126  }
127
128  // Logs in |username|.
129  void LogIn(const std::string& username) {
130    UserManager::Get()->UserLoggedIn(username, username, false);
131  }
132
133  // Stores old (pre-migration) user image info.
134  void SetOldUserImageInfo(const std::string& username,
135                           int image_index,
136                           const base::FilePath& image_path) {
137    RegisterUser(username);
138    DictionaryPrefUpdate images_pref(local_state_, "UserImages");
139    base::DictionaryValue* image_properties = new base::DictionaryValue();
140    image_properties->Set(
141        "index", base::Value::CreateIntegerValue(image_index));
142    image_properties->Set(
143        "path" , new base::StringValue(image_path.value()));
144    images_pref->SetWithoutPathExpansion(username, image_properties);
145  }
146
147  // Verifies user image info in |images_pref| dictionary.
148  void ExpectUserImageInfo(const base::DictionaryValue* images_pref,
149                           const std::string& username,
150                           int image_index,
151                           const base::FilePath& image_path) {
152    ASSERT_TRUE(images_pref);
153    const base::DictionaryValue* image_properties = NULL;
154    images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
155    ASSERT_TRUE(image_properties);
156    int actual_image_index;
157    std::string actual_image_path;
158    ASSERT_TRUE(image_properties->GetInteger("index", &actual_image_index) &&
159                image_properties->GetString("path", &actual_image_path));
160    EXPECT_EQ(image_index, actual_image_index);
161    EXPECT_EQ(image_path.value(), actual_image_path);
162  }
163
164  // Verifies that there is no image info for |username| in dictionary
165  // |images_pref|.
166  void ExpectNoUserImageInfo(const base::DictionaryValue* images_pref,
167                             const std::string& username) {
168    ASSERT_TRUE(images_pref);
169    const base::DictionaryValue* image_properties = NULL;
170    images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
171    ASSERT_FALSE(image_properties);
172  }
173
174  // Verifies that old user image info matches |image_index| and |image_path|
175  // and that new user image info does not exist.
176  void ExpectOldUserImageInfo(const std::string& username,
177                              int image_index,
178                              const base::FilePath& image_path) {
179    ExpectUserImageInfo(local_state_->GetDictionary("UserImages"),
180                        username, image_index, image_path);
181    ExpectNoUserImageInfo(local_state_->GetDictionary("user_image_info"),
182                          username);
183  }
184
185  // Verifies that new user image info matches |image_index| and |image_path|
186  // and that old user image info does not exist.
187  void ExpectNewUserImageInfo(const std::string& username,
188                              int image_index,
189                              const base::FilePath& image_path) {
190    ExpectUserImageInfo(local_state_->GetDictionary("user_image_info"),
191                        username, image_index, image_path);
192    ExpectNoUserImageInfo(local_state_->GetDictionary("UserImages"),
193                          username);
194  }
195
196  // Sets bitmap |resource_id| as image for |username| and saves it to disk.
197  void SaveUserImagePNG(const std::string& username,
198                        int resource_id) {
199    base::FilePath image_path = GetUserImagePath(username, "png");
200    scoped_refptr<base::RefCountedStaticMemory> image_data(
201        ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
202            resource_id, ui::SCALE_FACTOR_100P));
203    int written = base::WriteFile(
204        image_path,
205        reinterpret_cast<const char*>(image_data->front()),
206        image_data->size());
207    EXPECT_EQ(static_cast<int>(image_data->size()), written);
208    SetOldUserImageInfo(username, User::kExternalImageIndex, image_path);
209  }
210
211  // Returns the image path for user |username| with specified |extension|.
212  base::FilePath GetUserImagePath(const std::string& username,
213                                  const std::string& extension) {
214    return user_data_dir_.Append(username).AddExtension(extension);
215  }
216
217  // Completes the download of all non-image profile data for the user
218  // |username|.  This method must only be called after a profile data
219  // download has been started.  |url_fetcher_factory| will capture
220  // the net::TestURLFetcher created by the ProfileDownloader to
221  // download the profile image.
222  void CompleteProfileMetadataDownload(
223      const std::string& username,
224      net::TestURLFetcherFactory* url_fetcher_factory) {
225    ProfileDownloader* profile_downloader =
226        reinterpret_cast<UserImageManagerImpl*>(
227            UserManager::Get()->GetUserImageManager(username))->
228                profile_downloader_.get();
229    ASSERT_TRUE(profile_downloader);
230
231    static_cast<OAuth2TokenService::Consumer*>(profile_downloader)->
232        OnGetTokenSuccess(NULL,
233                          "token",
234                          base::Time::Now() + base::TimeDelta::FromDays(1));
235
236    net::TestURLFetcher* fetcher =
237        url_fetcher_factory->GetFetcherByID(
238            gaia::GaiaOAuthClient::kUrlFetcherId);
239    ASSERT_TRUE(fetcher);
240    fetcher->SetResponseString(
241        "{ \"image\": {\"url\": \"http://localhost/avatar.jpg\"} }");
242    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
243                                              net::OK));
244    fetcher->set_response_code(200);
245    fetcher->delegate()->OnURLFetchComplete(fetcher);
246    base::RunLoop().RunUntilIdle();
247  }
248
249  // Completes the download of the currently logged-in user's profile image.
250  // This method must only be called after a profile data download including
251  // the profile image has been started, the download of all non-image data has
252  // been completed by calling CompleteProfileMetadataDownload() and the
253  // net::TestURLFetcher created by the ProfileDownloader to download the
254  // profile image has been captured by |url_fetcher_factory|.
255  void CompleteProfileImageDownload(
256      net::TestURLFetcherFactory* url_fetcher_factory) {
257    std::string profile_image_data;
258    base::FilePath test_data_dir;
259    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
260    EXPECT_TRUE(ReadFileToString(
261        test_data_dir.Append("chromeos").Append("avatar1.jpg"),
262        &profile_image_data));
263
264    base::RunLoop run_loop;
265    PrefChangeRegistrar pref_change_registrar;
266    pref_change_registrar.Init(local_state_);
267    pref_change_registrar.Add("UserDisplayName", run_loop.QuitClosure());
268    net::TestURLFetcher* fetcher = url_fetcher_factory->GetFetcherByID(0);
269    ASSERT_TRUE(fetcher);
270    fetcher->SetResponseString(profile_image_data);
271    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
272                                              net::OK));
273    fetcher->set_response_code(200);
274    fetcher->delegate()->OnURLFetchComplete(fetcher);
275    run_loop.Run();
276
277    const User* user = UserManager::Get()->GetLoggedInUser();
278    ASSERT_TRUE(user);
279    UserImageManagerImpl* uim = reinterpret_cast<UserImageManagerImpl*>(
280        UserManager::Get()->GetUserImageManager(user->email()));
281    if (uim->job_.get()) {
282      run_loop_.reset(new base::RunLoop);
283      run_loop_->Run();
284    }
285  }
286
287  base::FilePath test_data_dir_;
288  base::FilePath user_data_dir_;
289
290  PrefService* local_state_;
291
292  scoped_ptr<gfx::ImageSkia> decoded_image_;
293
294  scoped_ptr<base::RunLoop> run_loop_;
295
296 private:
297  DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
298};
299
300IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_DefaultUserImagePreserved) {
301  // Setup an old default (stock) user image.
302  ScopedUserManagerEnabler(new MockUserManager);
303  SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
304}
305
306IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DefaultUserImagePreserved) {
307  UserManager::Get()->GetUsers();  // Load users.
308  // Old info preserved.
309  ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
310  LogIn(kTestUser1);
311  // Image info is migrated now.
312  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
313}
314
315IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_OtherUsersUnaffected) {
316  // Setup two users with stock images.
317  ScopedUserManagerEnabler(new MockUserManager);
318  SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
319  SetOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
320                      base::FilePath());
321}
322
323IN_PROC_BROWSER_TEST_F(UserImageManagerTest, OtherUsersUnaffected) {
324  UserManager::Get()->GetUsers();  // Load users.
325  // Old info preserved.
326  ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
327  ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
328                         base::FilePath());
329  LogIn(kTestUser1);
330  // Image info is migrated for the first user and unaffected for the rest.
331  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
332  ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
333                         base::FilePath());
334}
335
336IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_PRE_NonJPEGImageFromFile) {
337  // Setup a user with non-JPEG image.
338  ScopedUserManagerEnabler(new MockUserManager);
339  SaveUserImagePNG(
340      kTestUser1, kDefaultImageResourceIDs[kFirstDefaultImageIndex]);
341}
342
343IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_NonJPEGImageFromFile) {
344  UserManager::Get()->GetUsers();  // Load users.
345  // Old info preserved.
346  ExpectOldUserImageInfo(kTestUser1, User::kExternalImageIndex,
347                         GetUserImagePath(kTestUser1, "png"));
348  const User* user = UserManager::Get()->FindUser(kTestUser1);
349  EXPECT_TRUE(user->image_is_stub());
350
351  base::RunLoop run_loop;
352  PrefChangeRegistrar pref_change_registrar_;
353  pref_change_registrar_.Init(local_state_);
354  pref_change_registrar_.Add("UserImages", run_loop.QuitClosure());
355  LogIn(kTestUser1);
356
357  // Wait for migration.
358  run_loop.Run();
359
360  // Image info is migrated and the image is converted to JPG.
361  ExpectNewUserImageInfo(kTestUser1, User::kExternalImageIndex,
362                         GetUserImagePath(kTestUser1, "jpg"));
363  user = UserManager::Get()->GetLoggedInUser();
364  ASSERT_TRUE(user);
365  EXPECT_FALSE(user->image_is_safe_format());
366  // Check image dimensions.
367  const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
368  EXPECT_EQ(saved_image.width(), user->GetImage().width());
369  EXPECT_EQ(saved_image.height(), user->GetImage().height());
370}
371
372IN_PROC_BROWSER_TEST_F(UserImageManagerTest, NonJPEGImageFromFile) {
373  UserManager::Get()->GetUsers();  // Load users.
374  const User* user = UserManager::Get()->FindUser(kTestUser1);
375  ASSERT_TRUE(user);
376  // Wait for image load.
377  if (user->image_index() == User::kInvalidImageIndex) {
378    content::WindowedNotificationObserver(
379        chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
380        content::NotificationService::AllSources()).Wait();
381  }
382  // Now the migrated image is used.
383  EXPECT_TRUE(user->image_is_safe_format());
384  // Check image dimensions. Images can't be compared since JPEG is lossy.
385  const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
386  EXPECT_EQ(saved_image.width(), user->GetImage().width());
387  EXPECT_EQ(saved_image.height(), user->GetImage().height());
388}
389
390IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserDefaultImageIndex) {
391  RegisterUser(kTestUser1);
392}
393
394// Verifies that SaveUserDefaultImageIndex() correctly sets and persists the
395// chosen user image.
396IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserDefaultImageIndex) {
397  const User* user = UserManager::Get()->FindUser(kTestUser1);
398  ASSERT_TRUE(user);
399
400  const gfx::ImageSkia& default_image =
401      GetDefaultImage(kFirstDefaultImageIndex);
402
403  UserImageManager* user_image_manager =
404      UserManager::Get()->GetUserImageManager(kTestUser1);
405  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
406
407  EXPECT_TRUE(user->HasDefaultImage());
408  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
409  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
410  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
411}
412
413IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImage) {
414  RegisterUser(kTestUser1);
415}
416
417// Verifies that SaveUserImage() correctly sets and persists the chosen user
418// image.
419IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImage) {
420  const User* user = UserManager::Get()->FindUser(kTestUser1);
421  ASSERT_TRUE(user);
422
423  SkBitmap custom_image_bitmap;
424  custom_image_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
425  custom_image_bitmap.allocPixels();
426  custom_image_bitmap.setImmutable();
427  const gfx::ImageSkia custom_image =
428      gfx::ImageSkia::CreateFrom1xBitmap(custom_image_bitmap);
429
430  run_loop_.reset(new base::RunLoop);
431  UserImageManager* user_image_manager =
432      UserManager::Get()->GetUserImageManager(kTestUser1);
433  user_image_manager->SaveUserImage(UserImage::CreateAndEncode(custom_image));
434  run_loop_->Run();
435
436  EXPECT_FALSE(user->HasDefaultImage());
437  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
438  EXPECT_TRUE(test::AreImagesEqual(custom_image, user->GetImage()));
439  ExpectNewUserImageInfo(kTestUser1,
440                         User::kExternalImageIndex,
441                         GetUserImagePath(kTestUser1, "jpg"));
442
443  const scoped_ptr<gfx::ImageSkia> saved_image =
444      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
445  ASSERT_TRUE(saved_image);
446
447  // Check image dimensions. Images can't be compared since JPEG is lossy.
448  EXPECT_EQ(custom_image.width(), saved_image->width());
449  EXPECT_EQ(custom_image.height(), saved_image->height());
450}
451
452IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImageFromFile) {
453  RegisterUser(kTestUser1);
454}
455
456// Verifies that SaveUserImageFromFile() correctly sets and persists the chosen
457// user image.
458IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromFile) {
459  const User* user = UserManager::Get()->FindUser(kTestUser1);
460  ASSERT_TRUE(user);
461
462  const base::FilePath custom_image_path =
463      test_data_dir_.Append(test::kUserAvatarImage1RelativePath);
464  const scoped_ptr<gfx::ImageSkia> custom_image =
465      test::ImageLoader(custom_image_path).Load();
466  ASSERT_TRUE(custom_image);
467
468  run_loop_.reset(new base::RunLoop);
469  UserImageManager* user_image_manager =
470      UserManager::Get()->GetUserImageManager(kTestUser1);
471  user_image_manager->SaveUserImageFromFile(custom_image_path);
472  run_loop_->Run();
473
474  EXPECT_FALSE(user->HasDefaultImage());
475  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
476  EXPECT_TRUE(test::AreImagesEqual(*custom_image, user->GetImage()));
477  ExpectNewUserImageInfo(kTestUser1,
478                         User::kExternalImageIndex,
479                         GetUserImagePath(kTestUser1, "jpg"));
480
481  const scoped_ptr<gfx::ImageSkia> saved_image =
482      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
483  ASSERT_TRUE(saved_image);
484
485  // Check image dimensions. Images can't be compared since JPEG is lossy.
486  EXPECT_EQ(custom_image->width(), saved_image->width());
487  EXPECT_EQ(custom_image->height(), saved_image->height());
488}
489
490IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
491                       PRE_SaveUserImageFromProfileImage) {
492  RegisterUser(kTestUser1);
493  chromeos::StartupUtils::MarkOobeCompleted();
494}
495
496// Verifies that SaveUserImageFromProfileImage() correctly downloads, sets and
497// persists the chosen user image.
498IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromProfileImage) {
499  const User* user = UserManager::Get()->FindUser(kTestUser1);
500  ASSERT_TRUE(user);
501
502  UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
503  LoginUser(kTestUser1);
504
505  run_loop_.reset(new base::RunLoop);
506  UserImageManager* user_image_manager =
507      UserManager::Get()->GetUserImageManager(kTestUser1);
508  user_image_manager->SaveUserImageFromProfileImage();
509  run_loop_->Run();
510
511  net::TestURLFetcherFactory url_fetcher_factory;
512  CompleteProfileMetadataDownload(kTestUser1, &url_fetcher_factory);
513  CompleteProfileImageDownload(&url_fetcher_factory);
514
515  const gfx::ImageSkia& profile_image =
516      user_image_manager->DownloadedProfileImage();
517
518  EXPECT_FALSE(user->HasDefaultImage());
519  EXPECT_EQ(User::kProfileImageIndex, user->image_index());
520  EXPECT_TRUE(test::AreImagesEqual(profile_image, user->GetImage()));
521  ExpectNewUserImageInfo(kTestUser1,
522                         User::kProfileImageIndex,
523                         GetUserImagePath(kTestUser1, "jpg"));
524
525  const scoped_ptr<gfx::ImageSkia> saved_image =
526      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
527  ASSERT_TRUE(saved_image);
528
529  // Check image dimensions. Images can't be compared since JPEG is lossy.
530  EXPECT_EQ(profile_image.width(), saved_image->width());
531  EXPECT_EQ(profile_image.height(), saved_image->height());
532}
533
534IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
535                       PRE_ProfileImageDownloadDoesNotClobber) {
536  RegisterUser(kTestUser1);
537  chromeos::StartupUtils::MarkOobeCompleted();
538}
539
540// Sets the user image to the profile image, then sets it to one of the default
541// images while the profile image download is still in progress. Verifies that
542// when the download completes, the profile image is ignored and does not
543// clobber the default image chosen in the meantime.
544IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
545                       ProfileImageDownloadDoesNotClobber) {
546  const User* user = UserManager::Get()->FindUser(kTestUser1);
547  ASSERT_TRUE(user);
548
549  const gfx::ImageSkia& default_image =
550      GetDefaultImage(kFirstDefaultImageIndex);
551
552  UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
553  LoginUser(kTestUser1);
554
555  run_loop_.reset(new base::RunLoop);
556  UserImageManager* user_image_manager =
557      UserManager::Get()->GetUserImageManager(kTestUser1);
558  user_image_manager->SaveUserImageFromProfileImage();
559  run_loop_->Run();
560
561  net::TestURLFetcherFactory url_fetcher_factory;
562  CompleteProfileMetadataDownload(kTestUser1, &url_fetcher_factory);
563
564  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
565
566  CompleteProfileImageDownload(&url_fetcher_factory);
567
568  EXPECT_TRUE(user->HasDefaultImage());
569  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
570  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
571  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
572}
573
574class UserImageManagerPolicyTest : public UserImageManagerTest,
575                                   public policy::CloudPolicyStore::Observer {
576 protected:
577  UserImageManagerPolicyTest()
578      : fake_dbus_thread_manager_(new chromeos::FakeDBusThreadManager),
579        fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {
580    fake_dbus_thread_manager_->SetFakeClients();
581    fake_dbus_thread_manager_->SetSessionManagerClient(
582        scoped_ptr<SessionManagerClient>(fake_session_manager_client_));
583  }
584
585  // UserImageManagerTest overrides:
586  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
587    DBusThreadManager::SetInstanceForTesting(fake_dbus_thread_manager_);
588    UserImageManagerTest::SetUpInProcessBrowserTestFixture();
589  }
590
591  virtual void SetUpOnMainThread() OVERRIDE {
592    UserImageManagerTest::SetUpOnMainThread();
593
594    base::FilePath user_keys_dir;
595    ASSERT_TRUE(PathService::Get(chromeos::DIR_USER_POLICY_KEYS,
596                                 &user_keys_dir));
597    const std::string sanitized_username =
598        chromeos::CryptohomeClient::GetStubSanitizedUsername(kTestUser1);
599    const base::FilePath user_key_file =
600        user_keys_dir.AppendASCII(sanitized_username)
601                     .AppendASCII("policy.pub");
602    std::vector<uint8> user_key_bits;
603    ASSERT_TRUE(user_policy_.GetSigningKey()->ExportPublicKey(&user_key_bits));
604    ASSERT_TRUE(base::CreateDirectory(user_key_file.DirName()));
605    ASSERT_EQ(base::WriteFile(
606                  user_key_file,
607                  reinterpret_cast<const char*>(user_key_bits.data()),
608                  user_key_bits.size()),
609              static_cast<int>(user_key_bits.size()));
610    user_policy_.policy_data().set_username(kTestUser1);
611
612    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
613
614    policy_image_ = test::ImageLoader(test_data_dir_.Append(
615        test::kUserAvatarImage2RelativePath)).Load();
616    ASSERT_TRUE(policy_image_);
617  }
618
619  // policy::CloudPolicyStore::Observer overrides:
620  virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE {
621    if (run_loop_)
622      run_loop_->Quit();
623  }
624
625  virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE {
626    if (run_loop_)
627      run_loop_->Quit();
628  }
629
630  std::string ConstructPolicy(const std::string& relative_path) {
631    std::string image_data;
632    if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
633                                &image_data)) {
634      ADD_FAILURE();
635    }
636    std::string policy;
637    base::JSONWriter::Write(policy::test::ConstructExternalDataReference(
638        embedded_test_server()->GetURL(std::string("/") + relative_path).spec(),
639        image_data).get(),
640        &policy);
641    return policy;
642  }
643
644  policy::UserPolicyBuilder user_policy_;
645  FakeDBusThreadManager* fake_dbus_thread_manager_;
646  FakeSessionManagerClient* fake_session_manager_client_;
647
648  scoped_ptr<gfx::ImageSkia> policy_image_;
649
650 private:
651  DISALLOW_COPY_AND_ASSIGN(UserImageManagerPolicyTest);
652};
653
654IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_SetAndClear) {
655  RegisterUser(kTestUser1);
656  chromeos::StartupUtils::MarkOobeCompleted();
657}
658
659// Verifies that the user image can be set through policy. Also verifies that
660// after the policy has been cleared, the user is able to choose a different
661// image.
662IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, SetAndClear) {
663  const User* user = UserManager::Get()->FindUser(kTestUser1);
664  ASSERT_TRUE(user);
665
666  LoginUser(kTestUser1);
667  base::RunLoop().RunUntilIdle();
668
669  policy::CloudPolicyStore* store = GetStoreForUser(user);
670  ASSERT_TRUE(store);
671
672  // Set policy. Verify that the policy-provided user image is downloaded, set
673  // and persisted.
674  user_policy_.payload().mutable_useravatarimage()->set_value(
675      ConstructPolicy(test::kUserAvatarImage2RelativePath));
676  user_policy_.Build();
677  fake_session_manager_client_->set_user_policy(kTestUser1,
678                                                user_policy_.GetBlob());
679  run_loop_.reset(new base::RunLoop);
680  store->Load();
681  run_loop_->Run();
682
683  EXPECT_FALSE(user->HasDefaultImage());
684  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
685  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
686  ExpectNewUserImageInfo(kTestUser1,
687                         User::kExternalImageIndex,
688                         GetUserImagePath(kTestUser1, "jpg"));
689
690  scoped_ptr<gfx::ImageSkia> saved_image =
691      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
692  ASSERT_TRUE(saved_image);
693
694  // Check image dimensions. Images can't be compared since JPEG is lossy.
695  EXPECT_EQ(policy_image_->width(), saved_image->width());
696  EXPECT_EQ(policy_image_->height(), saved_image->height());
697
698  // Clear policy. Verify that the user image switches to a random default
699  // image.
700  user_policy_.payload().Clear();
701  user_policy_.Build();
702  fake_session_manager_client_->set_user_policy(kTestUser1,
703                                                user_policy_.GetBlob());
704  run_loop_.reset(new base::RunLoop);
705  store->AddObserver(this);
706  store->Load();
707  run_loop_->Run();
708  store->RemoveObserver(this);
709  base::RunLoop().RunUntilIdle();
710
711  const int default_image_index = user->image_index();
712  EXPECT_TRUE(user->HasDefaultImage());
713  ASSERT_LE(kFirstDefaultImageIndex, default_image_index);
714  ASSERT_GT(kFirstDefaultImageIndex + kDefaultImagesCount, default_image_index);
715  const gfx::ImageSkia& default_image = GetDefaultImage(default_image_index);
716  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
717  ExpectNewUserImageInfo(kTestUser1, default_image_index, base::FilePath());
718
719  // Choose a different user image. Verify that the chosen user image is set and
720  // persisted.
721  const int user_image_index = kFirstDefaultImageIndex +
722      (default_image_index - kFirstDefaultImageIndex + 1) % kDefaultImagesCount;
723  const gfx::ImageSkia& user_image = GetDefaultImage(user_image_index);
724
725  UserImageManager* user_image_manager =
726      UserManager::Get()->GetUserImageManager(kTestUser1);
727  user_image_manager->SaveUserDefaultImageIndex(user_image_index);
728
729  EXPECT_TRUE(user->HasDefaultImage());
730  EXPECT_EQ(user_image_index, user->image_index());
731  EXPECT_TRUE(test::AreImagesEqual(user_image, user->GetImage()));
732  ExpectNewUserImageInfo(kTestUser1, user_image_index, base::FilePath());
733}
734
735IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_PolicyOverridesUser) {
736  RegisterUser(kTestUser1);
737  chromeos::StartupUtils::MarkOobeCompleted();
738}
739
740// Verifies that when the user chooses a user image and a different image is
741// then set through policy, the policy takes precedence, overriding the
742// previously chosen image.
743IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PolicyOverridesUser) {
744  const User* user = UserManager::Get()->FindUser(kTestUser1);
745  ASSERT_TRUE(user);
746
747  LoginUser(kTestUser1);
748  base::RunLoop().RunUntilIdle();
749
750  policy::CloudPolicyStore* store = GetStoreForUser(user);
751  ASSERT_TRUE(store);
752
753  // Choose a user image. Verify that the chosen user image is set and
754  // persisted.
755  const gfx::ImageSkia& default_image =
756      GetDefaultImage(kFirstDefaultImageIndex);
757
758  UserImageManager* user_image_manager =
759      UserManager::Get()->GetUserImageManager(kTestUser1);
760  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
761
762  EXPECT_TRUE(user->HasDefaultImage());
763  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
764  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
765  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
766
767  // Set policy. Verify that the policy-provided user image is downloaded, set
768  // and persisted, overriding the previously set image.
769  user_policy_.payload().mutable_useravatarimage()->set_value(
770      ConstructPolicy(test::kUserAvatarImage2RelativePath));
771  user_policy_.Build();
772  fake_session_manager_client_->set_user_policy(kTestUser1,
773                                                user_policy_.GetBlob());
774  run_loop_.reset(new base::RunLoop);
775  store->Load();
776  run_loop_->Run();
777
778  EXPECT_FALSE(user->HasDefaultImage());
779  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
780  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
781  ExpectNewUserImageInfo(kTestUser1,
782                         User::kExternalImageIndex,
783                         GetUserImagePath(kTestUser1, "jpg"));
784
785  scoped_ptr<gfx::ImageSkia> saved_image =
786      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
787  ASSERT_TRUE(saved_image);
788
789  // Check image dimensions. Images can't be compared since JPEG is lossy.
790  EXPECT_EQ(policy_image_->width(), saved_image->width());
791  EXPECT_EQ(policy_image_->height(), saved_image->height());
792}
793
794IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest,
795                       PRE_UserDoesNotOverridePolicy) {
796  RegisterUser(kTestUser1);
797  chromeos::StartupUtils::MarkOobeCompleted();
798}
799
800// Verifies that when the user image has been set through policy and the user
801// chooses a different image, the policy takes precedence, preventing the user
802// from overriding the previously chosen image.
803IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, UserDoesNotOverridePolicy) {
804  const User* user = UserManager::Get()->FindUser(kTestUser1);
805  ASSERT_TRUE(user);
806
807  LoginUser(kTestUser1);
808  base::RunLoop().RunUntilIdle();
809
810  policy::CloudPolicyStore* store = GetStoreForUser(user);
811  ASSERT_TRUE(store);
812
813  // Set policy. Verify that the policy-provided user image is downloaded, set
814  // and persisted.
815  user_policy_.payload().mutable_useravatarimage()->set_value(
816      ConstructPolicy(test::kUserAvatarImage2RelativePath));
817  user_policy_.Build();
818  fake_session_manager_client_->set_user_policy(kTestUser1,
819                                                user_policy_.GetBlob());
820  run_loop_.reset(new base::RunLoop);
821  store->Load();
822  run_loop_->Run();
823
824  EXPECT_FALSE(user->HasDefaultImage());
825  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
826  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
827  ExpectNewUserImageInfo(kTestUser1,
828                         User::kExternalImageIndex,
829                         GetUserImagePath(kTestUser1, "jpg"));
830
831  scoped_ptr<gfx::ImageSkia> saved_image =
832      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
833  ASSERT_TRUE(saved_image);
834
835  // Check image dimensions. Images can't be compared since JPEG is lossy.
836  EXPECT_EQ(policy_image_->width(), saved_image->width());
837  EXPECT_EQ(policy_image_->height(), saved_image->height());
838
839  // Choose a different user image. Verify that the user image does not change
840  // as policy takes precedence.
841  UserImageManager* user_image_manager =
842      UserManager::Get()->GetUserImageManager(kTestUser1);
843  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
844
845  EXPECT_FALSE(user->HasDefaultImage());
846  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
847  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
848  ExpectNewUserImageInfo(kTestUser1,
849                         User::kExternalImageIndex,
850                         GetUserImagePath(kTestUser1, "jpg"));
851
852  saved_image = test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
853  ASSERT_TRUE(saved_image);
854
855  // Check image dimensions. Images can't be compared since JPEG is lossy.
856  EXPECT_EQ(policy_image_->width(), saved_image->width());
857  EXPECT_EQ(policy_image_->height(), saved_image->height());
858}
859
860}  // namespace chromeos
861