- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / user_image_manager_browsertest.cc
1 // Copyright (c) 2012 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 <string>
6
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/chromeos/login/default_user_images.h"
16 #include "chrome/browser/chromeos/login/mock_user_manager.h"
17 #include "chrome/browser/chromeos/login/user_image_manager_impl.h"
18 #include "chrome/browser/chromeos/login/user_manager.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "chrome/test/base/testing_browser_process.h"
23 #include "chromeos/chromeos_switches.h"
24 #include "content/public/browser/notification_observer.h"
25 #include "content/public/browser/notification_registrar.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/test/test_utils.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "ui/base/layout.h"
30 #include "ui/base/resource/resource_bundle.h"
31
32 namespace chromeos {
33
34 const char kTestUser1[] = "test-user@example.com";
35 const char kTestUser2[] = "test-user2@example.com";
36
37 class UserImageManagerTest : public InProcessBrowserTest,
38                              public content::NotificationObserver,
39                              public UserManager::Observer {
40  protected:
41   UserImageManagerTest() {
42   }
43
44   // InProcessBrowserTest overrides:
45   virtual void SetUpOnMainThread() OVERRIDE {
46     UserManager::Get()->AddObserver(this);
47     user_image_manager_ = UserManager::Get()->GetUserImageManager();
48     local_state_ = g_browser_process->local_state();
49     // No migration delay for testing.
50     UserImageManagerImpl::user_image_migration_delay_sec = 0;
51   }
52
53   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
54     command_line->AppendSwitch(switches::kLoginManager);
55     command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
56   }
57
58   // content::NotificationObserver overrides:
59   virtual void Observe(int type,
60                        const content::NotificationSource& source,
61                        const content::NotificationDetails& details) OVERRIDE {
62     DCHECK(type == chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED);
63     registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
64                       content::NotificationService::AllSources());
65     base::MessageLoopForUI::current()->Quit();
66   }
67
68   // UserManager::Observer overrides:
69   virtual void LocalStateChanged(UserManager* user_manager) OVERRIDE {
70     base::MessageLoopForUI::current()->Quit();
71   }
72
73   // Adds given user to Local State, if not there.
74   void AddUser(const std::string& username) {
75     ListPrefUpdate users_pref(local_state_, "LoggedInUsers");
76     users_pref->AppendIfNotPresent(new base::StringValue(username));
77   }
78
79   // Logs in |username|.
80   void LogIn(const std::string& username) {
81     UserManager::Get()->UserLoggedIn(username, username, false);
82   }
83
84   // Subscribes for image change notification.
85   void ExpectImageChange() {
86     registrar_.Add(this, chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
87                    content::NotificationService::AllSources());
88   }
89
90   // Stores old (pre-migration) user image info.
91   void SetOldUserImageInfo(const std::string& username,
92                            int image_index,
93                            const base::FilePath& image_path) {
94     AddUser(username);
95     DictionaryPrefUpdate images_pref(local_state_, "UserImages");
96     base::DictionaryValue* image_properties = new base::DictionaryValue();
97     image_properties->Set(
98         "index", base::Value::CreateIntegerValue(image_index));
99     image_properties->Set(
100         "path" , new base::StringValue(image_path.value()));
101     images_pref->SetWithoutPathExpansion(username, image_properties);
102   }
103
104   // Verifies user image info in |images_pref| dictionary.
105   void ExpectUserImageInfo(const base::DictionaryValue* images_pref,
106                            const std::string& username,
107                            int image_index,
108                            const base::FilePath& image_path) {
109     ASSERT_TRUE(images_pref);
110     const base::DictionaryValue* image_properties = NULL;
111     images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
112     ASSERT_TRUE(image_properties);
113     int actual_image_index;
114     std::string actual_image_path;
115     ASSERT_TRUE(image_properties->GetInteger("index", &actual_image_index) &&
116                 image_properties->GetString("path", &actual_image_path));
117     EXPECT_EQ(image_index, actual_image_index);
118     EXPECT_EQ(image_path.value(), actual_image_path);
119   }
120
121   // Verifies that there is no image info for |username| in dictionary
122   // |images_pref|.
123   void ExpectNoUserImageInfo(const base::DictionaryValue* images_pref,
124                              const std::string& username) {
125     ASSERT_TRUE(images_pref);
126     const base::DictionaryValue* image_properties = NULL;
127     images_pref->GetDictionaryWithoutPathExpansion(username, &image_properties);
128     ASSERT_FALSE(image_properties);
129   }
130
131   // Verifies that old user image info matches |image_index| and |image_path|
132   // and that new user image info does not exist.
133   void ExpectOldUserImageInfo(const std::string& username,
134                               int image_index,
135                               const base::FilePath& image_path) {
136     ExpectUserImageInfo(local_state_->GetDictionary("UserImages"),
137                         username, image_index, image_path);
138     ExpectNoUserImageInfo(local_state_->GetDictionary("user_image_info"),
139                           username);
140   }
141
142   // Verifies that new user image info matches |image_index| and |image_path|
143   // and that old user image info does not exist.
144   void ExpectNewUserImageInfo(const std::string& username,
145                               int image_index,
146                               const base::FilePath& image_path) {
147     ExpectUserImageInfo(local_state_->GetDictionary("user_image_info"),
148                         username, image_index, image_path);
149     ExpectNoUserImageInfo(local_state_->GetDictionary("UserImages"),
150                           username);
151   }
152
153   // Sets bitmap |resource_id| as image for |username| and saves it to disk.
154   void SaveUserImagePNG(const std::string& username,
155                         int resource_id) {
156     base::FilePath image_path = GetUserImagePath(username, "png");
157     scoped_refptr<base::RefCountedStaticMemory> image_data(
158         ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
159             resource_id, ui::SCALE_FACTOR_100P));
160     int written = file_util::WriteFile(
161         image_path,
162         reinterpret_cast<const char*>(image_data->front()),
163         image_data->size());
164     EXPECT_EQ(static_cast<int>(image_data->size()), written);
165     SetOldUserImageInfo(username, User::kExternalImageIndex, image_path);
166   }
167
168   // Returns the image path for user |username| with specified |extension|.
169   base::FilePath GetUserImagePath(const std::string& username,
170                             const std::string& extension) {
171     base::FilePath user_data_dir;
172     PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
173     return user_data_dir.Append(username).AddExtension(extension);
174   }
175
176   UserImageManager* user_image_manager_;
177   PrefService* local_state_;
178   content::NotificationRegistrar registrar_;
179
180  private:
181   DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
182 };
183
184 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_DefaultUserImagePreserved) {
185   // Setup an old default (stock) user image.
186   ScopedUserManagerEnabler(new MockUserManager);
187   SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
188 }
189
190 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DefaultUserImagePreserved) {
191   UserManager::Get()->GetUsers();  // Load users.
192   // Old info preserved.
193   ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
194   LogIn(kTestUser1);
195   // Wait for migration.
196   content::RunMessageLoop();
197   // Image info is migrated now.
198   ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
199 }
200
201 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_OtherUsersUnaffected) {
202   // Setup two users with stock images.
203   ScopedUserManagerEnabler(new MockUserManager);
204   SetOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
205   SetOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
206                       base::FilePath());
207 }
208
209 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, OtherUsersUnaffected) {
210   UserManager::Get()->GetUsers();  // Load users.
211   // Old info preserved.
212   ExpectOldUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
213   ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
214                          base::FilePath());
215   LogIn(kTestUser1);
216   // Wait for migration.
217   content::RunMessageLoop();
218   // Image info is migrated for the first user and unaffected for the rest.
219   ExpectNewUserImageInfo(kTestUser1, kFirstDefaultImageIndex, base::FilePath());
220   ExpectOldUserImageInfo(kTestUser2, kFirstDefaultImageIndex + 1,
221                          base::FilePath());
222 }
223
224 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_PRE_NonJPEGImageFromFile) {
225   // Setup a user with non-JPEG image.
226   ScopedUserManagerEnabler(new MockUserManager);
227   SaveUserImagePNG(
228       kTestUser1, kDefaultImageResourceIDs[kFirstDefaultImageIndex]);
229 }
230
231 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, PRE_NonJPEGImageFromFile) {
232   UserManager::Get()->GetUsers();  // Load users.
233   // Old info preserved.
234   ExpectOldUserImageInfo(kTestUser1, User::kExternalImageIndex,
235                          GetUserImagePath(kTestUser1, "png"));
236   const User* user = UserManager::Get()->FindUser(kTestUser1);
237   EXPECT_TRUE(user->image_is_stub());
238   LogIn(kTestUser1);
239   // Wait for migration.
240   content::RunMessageLoop();
241   // Image info is migrated and the image is converted to JPG.
242   ExpectNewUserImageInfo(kTestUser1, User::kExternalImageIndex,
243                          GetUserImagePath(kTestUser1, "jpg"));
244   user = UserManager::Get()->GetLoggedInUser();
245   ASSERT_TRUE(user);
246   EXPECT_FALSE(user->image_is_safe_format());
247   // Check image dimensions.
248   const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
249   EXPECT_EQ(saved_image.width(), user->image().width());
250   EXPECT_EQ(saved_image.height(), user->image().height());
251 }
252
253 // http://crbug.com/257009.
254 IN_PROC_BROWSER_TEST_F(UserImageManagerTest, DISABLED_NonJPEGImageFromFile) {
255   ExpectImageChange();
256   UserManager::Get()->GetUsers();  // Load users.
257   // Wait for image load.
258   content::RunMessageLoop();
259   // Now the migrated image is used.
260   const User* user = UserManager::Get()->FindUser(kTestUser1);
261   ASSERT_TRUE(user);
262   EXPECT_TRUE(user->image_is_safe_format());
263   // Check image dimensions. Images can't be compared since JPEG is lossy.
264   const gfx::ImageSkia& saved_image = GetDefaultImage(kFirstDefaultImageIndex);
265   EXPECT_EQ(saved_image.width(), user->image().width());
266   EXPECT_EQ(saved_image.height(), user->image().height());
267 }
268
269 }  // namespace chromeos