user_image_manager_browsertest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <map>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/basictypes.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/files/file_path.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/json/json_writer.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/linked_ptr.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/ref_counted.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/prefs/pref_change_registrar.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/run_loop.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/time/time.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/browser_process.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/login/login_manager_test.h"
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/login/startup_utils.h"
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/default_user_images.h"
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/user.h"
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/user_manager.h"
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/profiles/profile_downloader.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_browser_process.h"
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/chromeos_paths.h"
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h"
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/fake_dbus_thread_manager.h"
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/fake_session_manager_client.h"
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chromeos/dbus/session_manager_client.h"
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_core.h"
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_store.h"
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/policy_builder.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/notification_source.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "crypto/rsa_private_key.h"
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "google_apis/gaia/gaia_oauth_client.h"
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h"
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h"
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_status.h"
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/cloud_policy.pb.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestUser1[] = "test-user@example.com";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestUser2[] = "test-user2@example.com";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)policy::CloudPolicyStore* GetStoreForUser(const User* user) {
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Profile* profile = UserManager::Get()->GetProfileByUser(user);
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!profile) {
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ADD_FAILURE();
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return NULL;
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  policy::UserCloudPolicyManagerChromeOS* policy_manager =
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(profile);
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!policy_manager) {
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ADD_FAILURE();
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return NULL;
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return policy_manager->core()->store();
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class UserImageManagerTest : public LoginManagerTest,
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             public UserManager::Observer {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManagerTest() : LoginManagerTest(true) {
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // LoginManagerTest overrides:
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LoginManagerTest::SetUpInProcessBrowserTestFixture();
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LoginManagerTest::SetUpOnMainThread();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_state_ = g_browser_process->local_state();
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    UserManager::Get()->AddObserver(this);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void TearDownOnMainThread() OVERRIDE {
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    UserManager::Get()->RemoveObserver(this);
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LoginManagerTest::TearDownOnMainThread();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // UserManager::Observer overrides:
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void LocalStateChanged(UserManager* user_manager) OVERRIDE {
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (run_loop_)
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      run_loop_->Quit();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Logs in |username|.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LogIn(const std::string& username) {
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UserManager::Get()->UserLoggedIn(username, username, false);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stores old (pre-migration) user image info.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOldUserImageInfo(const std::string& username,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int image_index,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const base::FilePath& image_path) {
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    RegisterUser(username);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryPrefUpdate images_pref(local_state_, "UserImages");
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* image_properties = new base::DictionaryValue();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_properties->Set(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "index", base::Value::CreateIntegerValue(image_index));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_properties->Set(
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "path" , new base::StringValue(image_path.value()));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    images_pref->SetWithoutPathExpansion(username, image_properties);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies user image info in |images_pref| dictionary.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectUserImageInfo(const base::DictionaryValue* images_pref,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& username,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int image_index,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const base::FilePath& image_path) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(images_pref);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue* image_properties = NULL;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(image_properties);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int actual_image_index;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string actual_image_path;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(image_properties->GetInteger("index", &actual_image_index) &&
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                image_properties->GetString("path", &actual_image_path));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(image_index, actual_image_index);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(image_path.value(), actual_image_path);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that there is no image info for |username| in dictionary
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |images_pref|.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectNoUserImageInfo(const base::DictionaryValue* images_pref,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& username) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(images_pref);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue* image_properties = NULL;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(image_properties);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that old user image info matches |image_index| and |image_path|
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and that new user image info does not exist.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectOldUserImageInfo(const std::string& username,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int image_index,
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const base::FilePath& image_path) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectUserImageInfo(local_state_->GetDictionary("UserImages"),
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        username, image_index, image_path);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectNoUserImageInfo(local_state_->GetDictionary("user_image_info"),
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          username);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that new user image info matches |image_index| and |image_path|
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and that old user image info does not exist.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectNewUserImageInfo(const std::string& username,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int image_index,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const base::FilePath& image_path) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectUserImageInfo(local_state_->GetDictionary("user_image_info"),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        username, image_index, image_path);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectNoUserImageInfo(local_state_->GetDictionary("UserImages"),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          username);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets bitmap |resource_id| as image for |username| and saves it to disk.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SaveUserImagePNG(const std::string& username,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int resource_id) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath image_path = GetUserImagePath(username, "png");
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::RefCountedStaticMemory> image_data(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            resource_id, ui::SCALE_FACTOR_100P));
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int written = base::WriteFile(
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        image_path,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const char*>(image_data->front()),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        image_data->size());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(static_cast<int>(image_data->size()), written);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetOldUserImageInfo(username, User::kExternalImageIndex, image_path);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the image path for user |username| with specified |extension|.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetUserImagePath(const std::string& username,
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  const std::string& extension) {
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return user_data_dir_.Append(username).AddExtension(extension);
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Completes the download of all non-image profile data for the user
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |username|.  This method must only be called after a profile data
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // download has been started.  |url_fetcher_factory| will capture
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the net::TestURLFetcher created by the ProfileDownloader to
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // download the profile image.
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void CompleteProfileMetadataDownload(
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& username,
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net::TestURLFetcherFactory* url_fetcher_factory) {
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ProfileDownloader* profile_downloader =
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        reinterpret_cast<UserImageManagerImpl*>(
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            UserManager::Get()->GetUserImageManager(username))->
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                profile_downloader_.get();
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(profile_downloader);
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    static_cast<OAuth2TokenService::Consumer*>(profile_downloader)->
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        OnGetTokenSuccess(NULL,
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          "token",
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          base::Time::Now() + base::TimeDelta::FromDays(1));
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::TestURLFetcher* fetcher =
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        url_fetcher_factory->GetFetcherByID(
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            gaia::GaiaOAuthClient::kUrlFetcherId);
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(fetcher);
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->SetResponseString(
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        "{ \"image\": {\"url\": \"http://localhost/avatar.jpg\"} }");
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                              net::OK));
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->set_response_code(200);
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->delegate()->OnURLFetchComplete(fetcher);
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Completes the download of the currently logged-in user's profile image.
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // This method must only be called after a profile data download including
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the profile image has been started, the download of all non-image data has
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been completed by calling CompleteProfileMetadataDownload() and the
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // net::TestURLFetcher created by the ProfileDownloader to download the
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // profile image has been captured by |url_fetcher_factory|.
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void CompleteProfileImageDownload(
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net::TestURLFetcherFactory* url_fetcher_factory) {
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string profile_image_data;
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::FilePath test_data_dir;
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EXPECT_TRUE(ReadFileToString(
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        test_data_dir.Append("chromeos").Append("avatar1.jpg"),
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        &profile_image_data));
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::RunLoop run_loop;
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PrefChangeRegistrar pref_change_registrar;
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    pref_change_registrar.Init(local_state_);
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    pref_change_registrar.Add("UserDisplayName", run_loop.QuitClosure());
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::TestURLFetcher* fetcher = url_fetcher_factory->GetFetcherByID(0);
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(fetcher);
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->SetResponseString(profile_image_data);
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                              net::OK));
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->set_response_code(200);
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fetcher->delegate()->OnURLFetchComplete(fetcher);
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    run_loop.Run();
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const User* user = UserManager::Get()->GetLoggedInUser();
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(user);
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UserImageManagerImpl* uim = reinterpret_cast<UserImageManagerImpl*>(
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        UserManager::Get()->GetUserImageManager(user->email()));
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (uim->job_.get()) {
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      run_loop_.reset(new base::RunLoop);
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      run_loop_->Run();
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::FilePath test_data_dir_;
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::FilePath user_data_dir_;
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* local_state_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gfx::ImageSkia> decoded_image_;
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_DefaultUserImagePreserved) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup an old default (stock) user image.
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedUserManagerEnabler(new MockUserManager);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DefaultUserImagePreserved) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UserManager::Get()->GetUsers();  // Load users.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Old info preserved.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogIn(kTestUser1);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image info is migrated now.
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_OtherUsersUnaffected) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup two users with stock images.
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedUserManagerEnabler(new MockUserManager);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::FilePath());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, OtherUsersUnaffected) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UserManager::Get()->GetUsers();  // Load users.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Old info preserved.
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::FilePath());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogIn(kTestUser1);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image info is migrated for the first user and unaffected for the rest.
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::FilePath());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_PRE_NonJPEGImageFromFile) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup a user with non-JPEG image.
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedUserManagerEnabler(new MockUserManager);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SaveUserImagePNG(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestUser1, kDefaultImageResourceIDs[kFirstDefaultImageIndex]);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_NonJPEGImageFromFile) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UserManager::Get()->GetUsers();  // Load users.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Old info preserved.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectOldUserImageInfo(kTestUser1, User::kExternalImageIndex,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "png"));
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(user->image_is_stub());
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop run_loop;
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PrefChangeRegistrar pref_change_registrar_;
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pref_change_registrar_.Init(local_state_);
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pref_change_registrar_.Add("UserImages", run_loop.QuitClosure());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogIn(kTestUser1);
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for migration.
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  run_loop.Run();
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image info is migrated and the image is converted to JPG.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, User::kExternalImageIndex,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  user = UserManager::Get()->GetLoggedInUser();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(user);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(user->image_is_safe_format());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check image dimensions.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(saved_image.width(), user->GetImage().width());
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(saved_image.height(), user->GetImage().height());
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, NonJPEGImageFromFile) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UserManager::Get()->GetUsers();  // Load users.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(user);
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wait for image load.
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (user->image_index() == User::kInvalidImageIndex) {
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WindowedNotificationObserver(
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content::NotificationService::AllSources()).Wait();
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Now the migrated image is used.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(user->image_is_safe_format());
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(saved_image.width(), user->GetImage().width());
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(saved_image.height(), user->GetImage().height());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserDefaultImageIndex) {
391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that SaveUserDefaultImageIndex() correctly sets and persists the
395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// chosen user image.
396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserDefaultImageIndex) {
397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const gfx::ImageSkia& default_image =
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetDefaultImage(kFirstDefaultImageIndex);
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(user->HasDefaultImage());
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImage) {
414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that SaveUserImage() correctly sets and persists the chosen user
418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// image.
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImage) {
420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SkBitmap custom_image_bitmap;
424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  custom_image_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  custom_image_bitmap.allocPixels();
426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  custom_image_bitmap.setImmutable();
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const gfx::ImageSkia custom_image =
428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gfx::ImageSkia::CreateFrom1xBitmap(custom_image_bitmap);
429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserImage(UserImage::CreateAndEncode(custom_image));
434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(custom_image, user->GetImage()));
439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_ptr<gfx::ImageSkia> saved_image =
444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(custom_image.width(), saved_image->width());
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(custom_image.height(), saved_image->height());
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_SaveUserImageFromFile) {
453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that SaveUserImageFromFile() correctly sets and persists the chosen
457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// user image.
458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromFile) {
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const base::FilePath custom_image_path =
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test_data_dir_.Append(test::kUserAvatarImage1RelativePath);
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_ptr<gfx::ImageSkia> custom_image =
465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(custom_image_path).Load();
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(custom_image);
467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserImageFromFile(custom_image_path);
472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
4765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(*custom_image, user->GetImage()));
477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_ptr<gfx::ImageSkia> saved_image =
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(custom_image->width(), saved_image->width());
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(custom_image->height(), saved_image->height());
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       PRE_SaveUserImageFromProfileImage) {
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chromeos::StartupUtils::MarkOobeCompleted();
494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that SaveUserImageFromProfileImage() correctly downloads, sets and
497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// persists the chosen user image.
498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest, SaveUserImageFromProfileImage) {
499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoginUser(kTestUser1);
504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
505a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserImageFromProfileImage();
509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CompleteProfileMetadataDownload(kTestUser1, &url_fetcher_factory);
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CompleteProfileImageDownload(&url_fetcher_factory);
514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const gfx::ImageSkia& profile_image =
516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      user_image_manager->DownloadedProfileImage();
517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kProfileImageIndex, user->image_index());
5205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(profile_image, user->GetImage()));
521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kProfileImageIndex,
523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_ptr<gfx::ImageSkia> saved_image =
526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(profile_image.width(), saved_image->width());
531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(profile_image.height(), saved_image->height());
532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       PRE_ProfileImageDownloadDoesNotClobber) {
536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chromeos::StartupUtils::MarkOobeCompleted();
538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sets the user image to the profile image, then sets it to one of the default
541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// images while the profile image download is still in progress. Verifies that
542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// when the download completes, the profile image is ignored and does not
543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// clobber the default image chosen in the meantime.
544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerTest,
545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       ProfileImageDownloadDoesNotClobber) {
546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const gfx::ImageSkia& default_image =
550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetDefaultImage(kFirstDefaultImageIndex);
551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManagerImpl::IgnoreProfileDataDownloadDelayForTesting();
553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoginUser(kTestUser1);
554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserImageFromProfileImage();
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory;
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CompleteProfileMetadataDownload(kTestUser1, &url_fetcher_factory);
563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
566a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CompleteProfileImageDownload(&url_fetcher_factory);
567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(user->HasDefaultImage());
569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class UserImageManagerPolicyTest : public UserImageManagerTest,
575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   public policy::CloudPolicyStore::Observer {
576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected:
577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManagerPolicyTest()
578a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : fake_dbus_thread_manager_(new chromeos::FakeDBusThreadManager),
579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {
580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fake_dbus_thread_manager_->SetFakeClients();
581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fake_dbus_thread_manager_->SetSessionManagerClient(
582a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        scoped_ptr<SessionManagerClient>(fake_session_manager_client_));
583a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
584a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
585a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // UserImageManagerTest overrides:
586a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
587a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DBusThreadManager::SetInstanceForTesting(fake_dbus_thread_manager_);
588a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    UserImageManagerTest::SetUpInProcessBrowserTestFixture();
589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    UserImageManagerTest::SetUpOnMainThread();
593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::FilePath user_keys_dir;
595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chromeos::DIR_USER_POLICY_KEYS,
596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 &user_keys_dir));
597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string sanitized_username =
598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        chromeos::CryptohomeClient::GetStubSanitizedUsername(kTestUser1);
599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::FilePath user_key_file =
600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        user_keys_dir.AppendASCII(sanitized_username)
601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     .AppendASCII("policy.pub");
602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::vector<uint8> user_key_bits;
603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(user_policy_.GetSigningKey()->ExportPublicKey(&user_key_bits));
604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(base::CreateDirectory(user_key_file.DirName()));
605a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ASSERT_EQ(base::WriteFile(
606a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  user_key_file,
607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  reinterpret_cast<const char*>(user_key_bits.data()),
608a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                  user_key_bits.size()),
609a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              static_cast<int>(user_key_bits.size()));
610a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    user_policy_.policy_data().set_username(kTestUser1);
611a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
612a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
613a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
614a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    policy_image_ = test::ImageLoader(test_data_dir_.Append(
615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        test::kUserAvatarImage2RelativePath)).Load();
616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(policy_image_);
617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // policy::CloudPolicyStore::Observer overrides:
620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE {
621a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (run_loop_)
622a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      run_loop_->Quit();
623a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
624a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE {
626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (run_loop_)
627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      run_loop_->Quit();
628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string ConstructPolicy(const std::string& relative_path) {
631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string image_data;
632a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                &image_data)) {
634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ADD_FAILURE();
635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string policy;
637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::JSONWriter::Write(policy::test::ConstructExternalDataReference(
638a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        embedded_test_server()->GetURL(std::string("/") + relative_path).spec(),
639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        image_data).get(),
640a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        &policy);
641a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return policy;
642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  policy::UserPolicyBuilder user_policy_;
645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FakeDBusThreadManager* fake_dbus_thread_manager_;
646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FakeSessionManagerClient* fake_session_manager_client_;
647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gfx::ImageSkia> policy_image_;
649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UserImageManagerPolicyTest);
652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_SetAndClear) {
655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chromeos::StartupUtils::MarkOobeCompleted();
657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that the user image can be set through policy. Also verifies that
660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// after the policy has been cleared, the user is able to choose a different
661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// image.
662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, SetAndClear) {
663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
666a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoginUser(kTestUser1);
667a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  policy::CloudPolicyStore* store = GetStoreForUser(user);
670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(store);
671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Set policy. Verify that the policy-provided user image is downloaded, set
673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and persisted.
674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.payload().mutable_useravatarimage()->set_value(
675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ConstructPolicy(test::kUserAvatarImage2RelativePath));
676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.Build();
677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  fake_session_manager_client_->set_user_policy(kTestUser1,
678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                user_policy_.GetBlob());
679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->Load();
681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
6855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gfx::ImageSkia> saved_image =
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->width(), saved_image->width());
696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->height(), saved_image->height());
697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Clear policy. Verify that the user image switches to a random default
69946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // image.
700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.payload().Clear();
701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.Build();
702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  fake_session_manager_client_->set_user_policy(kTestUser1,
703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                user_policy_.GetBlob());
704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->AddObserver(this);
706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->Load();
707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
708a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->RemoveObserver(this);
709a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
71146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const int default_image_index = user->image_index();
71246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(user->HasDefaultImage());
71346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_LE(kFirstDefaultImageIndex, default_image_index);
71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_GT(kFirstDefaultImageIndex + kDefaultImagesCount, default_image_index);
71546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const gfx::ImageSkia& default_image = GetDefaultImage(default_image_index);
71646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
71746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, default_image_index, base::FilePath());
718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Choose a different user image. Verify that the chosen user image is set and
720a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // persisted.
72146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const int user_image_index = kFirstDefaultImageIndex +
72246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      (default_image_index - kFirstDefaultImageIndex + 1) % kDefaultImagesCount;
72346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const gfx::ImageSkia& user_image = GetDefaultImage(user_image_index);
724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
725a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
72746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  user_image_manager->SaveUserDefaultImageIndex(user_image_index);
728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(user->HasDefaultImage());
73046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_EQ(user_image_index, user->image_index());
73146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  EXPECT_TRUE(test::AreImagesEqual(user_image, user->GetImage()));
73246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, user_image_index, base::FilePath());
733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PRE_PolicyOverridesUser) {
736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chromeos::StartupUtils::MarkOobeCompleted();
738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that when the user chooses a user image and a different image is
741a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// then set through policy, the policy takes precedence, overriding the
742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// previously chosen image.
743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, PolicyOverridesUser) {
744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoginUser(kTestUser1);
748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  policy::CloudPolicyStore* store = GetStoreForUser(user);
751a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(store);
752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Choose a user image. Verify that the chosen user image is set and
754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // persisted.
755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const gfx::ImageSkia& default_image =
756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetDefaultImage(kFirstDefaultImageIndex);
757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(user->HasDefaultImage());
763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(kFirstDefaultImageIndex, user->image_index());
7645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(default_image, user->GetImage()));
765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Set policy. Verify that the policy-provided user image is downloaded, set
768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and persisted, overriding the previously set image.
769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.payload().mutable_useravatarimage()->set_value(
770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ConstructPolicy(test::kUserAvatarImage2RelativePath));
771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.Build();
772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  fake_session_manager_client_->set_user_policy(kTestUser1,
773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                user_policy_.GetBlob());
774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
775a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->Load();
776a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
778a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
7805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
781a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
782a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
783a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
784a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gfx::ImageSkia> saved_image =
786a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
788a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
789a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->width(), saved_image->width());
791a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->height(), saved_image->height());
792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest,
795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       PRE_UserDoesNotOverridePolicy) {
796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RegisterUser(kTestUser1);
797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chromeos::StartupUtils::MarkOobeCompleted();
798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verifies that when the user image has been set through policy and the user
801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// chooses a different image, the policy takes precedence, preventing the user
802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// from overriding the previously chosen image.
803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(UserImageManagerPolicyTest, UserDoesNotOverridePolicy) {
804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const User* user = UserManager::Get()->FindUser(kTestUser1);
805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(user);
806a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LoginUser(kTestUser1);
808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  policy::CloudPolicyStore* store = GetStoreForUser(user);
811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(store);
812a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
813a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Set policy. Verify that the policy-provided user image is downloaded, set
814a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and persisted.
815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.payload().mutable_useravatarimage()->set_value(
816a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ConstructPolicy(test::kUserAvatarImage2RelativePath));
817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  user_policy_.Build();
818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  fake_session_manager_client_->set_user_policy(kTestUser1,
819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                user_policy_.GetBlob());
820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop);
821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  store->Load();
822a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
8265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<gfx::ImageSkia> saved_image =
832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
836a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->width(), saved_image->width());
837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->height(), saved_image->height());
838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Choose a different user image. Verify that the user image does not change
840a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // as policy takes precedence.
841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UserImageManager* user_image_manager =
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UserManager::Get()->GetUserImageManager(kTestUser1);
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_image_manager->SaveUserDefaultImageIndex(kFirstDefaultImageIndex);
844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(user->HasDefaultImage());
846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(User::kExternalImageIndex, user->image_index());
8475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(test::AreImagesEqual(*policy_image_, user->GetImage()));
848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ExpectNewUserImageInfo(kTestUser1,
849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         User::kExternalImageIndex,
850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         GetUserImagePath(kTestUser1, "jpg"));
851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  saved_image = test::ImageLoader(GetUserImagePath(kTestUser1, "jpg")).Load();
853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(saved_image);
854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check image dimensions. Images can't be compared since JPEG is lossy.
856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->width(), saved_image->width());
857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(policy_image_->height(), saved_image->height());
858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
861