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