OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <string> | |
6 #include <vector> | |
7 | |
8 #include "ash/desktop_background/desktop_background_controller.h" | |
9 #include "ash/desktop_background/desktop_background_controller_observer.h" | |
10 #include "ash/shell.h" | |
11 #include "base/basictypes.h" | |
12 #include "base/command_line.h" | |
13 #include "base/compiler_specific.h" | |
14 #include "base/file_util.h" | |
15 #include "base/files/file_path.h" | |
16 #include "base/json/json_writer.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/path_service.h" | |
19 #include "base/run_loop.h" | |
20 #include "chrome/browser/chromeos/login/login_display_host_impl.h" | |
21 #include "chrome/browser/chromeos/login/login_manager_test.h" | |
22 #include "chrome/browser/chromeos/login/startup_utils.h" | |
23 #include "chrome/browser/chromeos/login/user.h" | |
24 #include "chrome/browser/chromeos/login/user_manager.h" | |
25 #include "chrome/browser/chromeos/login/wallpaper_manager.h" | |
26 #include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_u
til.h" | |
27 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" | |
28 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chrom
eos.h" | |
29 #include "chrome/browser/profiles/profile.h" | |
30 #include "chrome/common/chrome_paths.h" | |
31 #include "chrome/common/chrome_switches.h" | |
32 #include "chromeos/chromeos_paths.h" | |
33 #include "chromeos/chromeos_switches.h" | |
34 #include "chromeos/dbus/cryptohome_client.h" | |
35 #include "chromeos/dbus/dbus_thread_manager.h" | |
36 #include "chromeos/dbus/fake_dbus_thread_manager.h" | |
37 #include "chromeos/dbus/fake_session_manager_client.h" | |
38 #include "chromeos/dbus/session_manager_client.h" | |
39 #include "components/policy/core/common/cloud/cloud_policy_core.h" | |
40 #include "components/policy/core/common/cloud/cloud_policy_store.h" | |
41 #include "components/policy/core/common/cloud/cloud_policy_validator.h" | |
42 #include "components/policy/core/common/cloud/policy_builder.h" | |
43 #include "content/public/test/browser_test_utils.h" | |
44 #include "crypto/rsa_private_key.h" | |
45 #include "net/test/embedded_test_server/embedded_test_server.h" | |
46 #include "policy/proto/cloud_policy.pb.h" | |
47 #include "testing/gtest/include/gtest/gtest.h" | |
48 #include "third_party/skia/include/core/SkBitmap.h" | |
49 #include "third_party/skia/include/core/SkColor.h" | |
50 #include "ui/gfx/image/image_skia.h" | |
51 #include "url/gurl.h" | |
52 | |
53 namespace chromeos { | |
54 | |
55 namespace { | |
56 | |
57 const char kTestUsers[2][19] = { "test-0@example.com", "test-1@example.com" }; | |
58 | |
59 const char kRedImageFileName[] = "chromeos/wallpapers/red.jpg"; | |
60 const char kGreenImageFileName[] = "chromeos/wallpapers/green.jpg"; | |
61 const char kBlueImageFileName[] = "chromeos/wallpapers/blue.jpg"; | |
62 | |
63 const SkColor kRedImageColor = SkColorSetARGB(255, 199, 6, 7); | |
64 const SkColor kGreenImageColor = SkColorSetARGB(255, 38, 196, 15); | |
65 | |
66 policy::CloudPolicyStore* GetStoreForUser(const User* user) { | |
67 Profile* profile = UserManager::Get()->GetProfileByUser(user); | |
68 if (!profile) { | |
69 ADD_FAILURE(); | |
70 return NULL; | |
71 } | |
72 policy::UserCloudPolicyManagerChromeOS* policy_manager = | |
73 policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(profile); | |
74 if (!policy_manager) { | |
75 ADD_FAILURE(); | |
76 return NULL; | |
77 } | |
78 return policy_manager->core()->store(); | |
79 } | |
80 | |
81 // Compute the average ARGB color of |bitmap|. | |
82 SkColor ComputeAverageColor(const SkBitmap& bitmap) { | |
83 if (bitmap.empty() || bitmap.width() < 1 || bitmap.height() < 1) { | |
84 ADD_FAILURE() << "Empty or invalid bitmap."; | |
85 return SkColorSetARGB(0, 0, 0, 0); | |
86 } | |
87 if (bitmap.isNull()) { | |
88 ADD_FAILURE() << "Bitmap has no pixelref."; | |
89 return SkColorSetARGB(0, 0, 0, 0); | |
90 } | |
91 if (bitmap.config() == SkBitmap::kNo_Config) { | |
92 ADD_FAILURE() << "Bitmap has not been configured."; | |
93 return SkColorSetARGB(0, 0, 0, 0); | |
94 } | |
95 uint64 a = 0, r = 0, g = 0, b = 0; | |
96 bitmap.lockPixels(); | |
97 for (int x = 0; x < bitmap.width(); ++x) { | |
98 for (int y = 0; y < bitmap.height(); ++y) { | |
99 const SkColor color = bitmap.getColor(x, y); | |
100 a += SkColorGetA(color); | |
101 r += SkColorGetR(color); | |
102 g += SkColorGetG(color); | |
103 b += SkColorGetB(color); | |
104 } | |
105 } | |
106 bitmap.unlockPixels(); | |
107 uint64 pixel_number = bitmap.width() * bitmap.height(); | |
108 return SkColorSetARGB((a + pixel_number / 2) / pixel_number, | |
109 (r + pixel_number / 2) / pixel_number, | |
110 (g + pixel_number / 2) / pixel_number, | |
111 (b + pixel_number / 2) / pixel_number); | |
112 } | |
113 | |
114 // Obtain background image and return its average ARGB color. | |
115 SkColor GetAverageBackgroundColor() { | |
116 const gfx::ImageSkia image = | |
117 ash::Shell::GetInstance()->desktop_background_controller()-> | |
118 GetWallpaper(); | |
119 | |
120 const gfx::ImageSkiaRep& representation = image.GetRepresentation(1.); | |
121 if (representation.is_null()) { | |
122 ADD_FAILURE() << "No image representation."; | |
123 return SkColorSetARGB(0, 0, 0, 0); | |
124 } | |
125 | |
126 const SkBitmap& bitmap = representation.sk_bitmap(); | |
127 return ComputeAverageColor(bitmap); | |
128 } | |
129 | |
130 } // namespace | |
131 | |
132 class WallpaperManagerPolicyTest | |
133 : public LoginManagerTest, | |
134 public ash::DesktopBackgroundControllerObserver, | |
135 public testing::WithParamInterface<bool> { | |
136 protected: | |
137 WallpaperManagerPolicyTest() | |
138 : LoginManagerTest(true), | |
139 wallpaper_change_count_(0), | |
140 fake_dbus_thread_manager_(new FakeDBusThreadManager), | |
141 fake_session_manager_client_(new FakeSessionManagerClient) { | |
142 fake_dbus_thread_manager_->SetFakeClients(); | |
143 fake_dbus_thread_manager_->SetSessionManagerClient( | |
144 scoped_ptr<SessionManagerClient>(fake_session_manager_client_)); | |
145 } | |
146 | |
147 scoped_ptr<policy::UserPolicyBuilder> GetUserPolicyBuilder( | |
148 const std::string& user_id) { | |
149 scoped_ptr<policy::UserPolicyBuilder> | |
150 user_policy_builder(new policy::UserPolicyBuilder()); | |
151 base::FilePath user_keys_dir; | |
152 EXPECT_TRUE(PathService::Get(DIR_USER_POLICY_KEYS, &user_keys_dir)); | |
153 const std::string sanitized_user_id = | |
154 CryptohomeClient::GetStubSanitizedUsername(user_id); | |
155 const base::FilePath user_key_file = | |
156 user_keys_dir.AppendASCII(sanitized_user_id) | |
157 .AppendASCII("policy.pub"); | |
158 std::vector<uint8> user_key_bits; | |
159 EXPECT_TRUE(user_policy_builder->GetSigningKey()-> | |
160 ExportPublicKey(&user_key_bits)); | |
161 EXPECT_TRUE(base::CreateDirectory(user_key_file.DirName())); | |
162 EXPECT_EQ(base::WriteFile( | |
163 user_key_file, | |
164 reinterpret_cast<const char*>(user_key_bits.data()), | |
165 user_key_bits.size()), | |
166 static_cast<int>(user_key_bits.size())); | |
167 user_policy_builder->policy_data().set_username(user_id); | |
168 return user_policy_builder.Pass(); | |
169 } | |
170 | |
171 // LoginManagerTest: | |
172 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | |
173 DBusThreadManager::SetInstanceForTesting(fake_dbus_thread_manager_); | |
174 LoginManagerTest::SetUpInProcessBrowserTestFixture(); | |
175 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); | |
176 } | |
177 | |
178 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
179 // Set the same switches as LoginManagerTest, except that kMultiProfiles is | |
180 // only set when GetParam() is true and except that kLoginProfile is set | |
181 // when GetParam() is false. The latter seems to be required for the sane | |
182 // start-up of user profiles. | |
183 command_line->AppendSwitch(switches::kLoginManager); | |
184 command_line->AppendSwitch(switches::kForceLoginManagerInTests); | |
185 if (GetParam()) | |
186 command_line->AppendSwitch(::switches::kMultiProfiles); | |
187 else | |
188 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); | |
189 } | |
190 | |
191 virtual void SetUpOnMainThread() OVERRIDE { | |
192 LoginManagerTest::SetUpOnMainThread(); | |
193 ash::Shell::GetInstance()-> | |
194 desktop_background_controller()->AddObserver(this); | |
195 | |
196 // Set up policy signing. | |
197 user_policy_builders_[0] = GetUserPolicyBuilder(kTestUsers[0]); | |
198 user_policy_builders_[1] = GetUserPolicyBuilder(kTestUsers[1]); | |
199 | |
200 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); | |
201 } | |
202 | |
203 virtual void TearDownOnMainThread() OVERRIDE { | |
204 ash::Shell::GetInstance()-> | |
205 desktop_background_controller()->RemoveObserver(this); | |
206 LoginManagerTest::TearDownOnMainThread(); | |
207 } | |
208 | |
209 // ash::DesktopBackgroundControllerObserver: | |
210 virtual void OnWallpaperDataChanged() OVERRIDE { | |
211 ++wallpaper_change_count_; | |
212 if (run_loop_) | |
213 run_loop_->Quit(); | |
214 } | |
215 | |
216 // Runs the loop until wallpaper has changed at least |count| times in total. | |
217 void RunUntilWallpaperChangeCount(int count) { | |
218 while (wallpaper_change_count_ < count) { | |
219 run_loop_.reset(new base::RunLoop); | |
220 run_loop_->Run(); | |
221 } | |
222 } | |
223 | |
224 std::string ConstructPolicy(const std::string& relative_path) const { | |
225 std::string image_data; | |
226 if (!base::ReadFileToString(test_data_dir_.Append(relative_path), | |
227 &image_data)) { | |
228 ADD_FAILURE(); | |
229 } | |
230 std::string policy; | |
231 base::JSONWriter::Write(policy::test::ConstructExternalDataReference( | |
232 embedded_test_server()->GetURL(std::string("/") + relative_path).spec(), | |
233 image_data).get(), | |
234 &policy); | |
235 return policy; | |
236 } | |
237 | |
238 // Inject |filename| as wallpaper policy for test user |user_number|. Set | |
239 // empty |filename| to clear policy. | |
240 void InjectPolicy(int user_number, const std::string& filename) { | |
241 ASSERT_TRUE(user_number == 0 || user_number == 1); | |
242 const std::string user_id = kTestUsers[user_number]; | |
243 policy::UserPolicyBuilder* builder = | |
244 user_policy_builders_[user_number].get(); | |
245 if (filename != "") { | |
246 builder->payload(). | |
247 mutable_wallpaperimage()->set_value(ConstructPolicy(filename)); | |
248 } else { | |
249 builder->payload().Clear(); | |
250 } | |
251 builder->Build(); | |
252 fake_session_manager_client_->set_user_policy(user_id, builder->GetBlob()); | |
253 const User* user = UserManager::Get()->FindUser(user_id); | |
254 ASSERT_TRUE(user); | |
255 policy::CloudPolicyStore* store = GetStoreForUser(user); | |
256 ASSERT_TRUE(store); | |
257 store->Load(); | |
258 ASSERT_EQ(policy::CloudPolicyStore::STATUS_OK, store->status()); | |
259 ASSERT_EQ(policy::CloudPolicyValidatorBase::VALIDATION_OK, | |
260 store->validation_status()); | |
261 } | |
262 | |
263 // Obtain WallpaperInfo for |user_number| from WallpaperManager. | |
264 void GetUserWallpaperInfo(int user_number, WallpaperInfo* wallpaper_info) { | |
265 WallpaperManager::Get()-> | |
266 GetUserWallpaperInfo(kTestUsers[user_number], wallpaper_info); | |
267 } | |
268 | |
269 base::FilePath test_data_dir_; | |
270 scoped_ptr<base::RunLoop> run_loop_; | |
271 int wallpaper_change_count_; | |
272 scoped_ptr<policy::UserPolicyBuilder> user_policy_builders_[2]; | |
273 FakeDBusThreadManager* fake_dbus_thread_manager_; | |
274 FakeSessionManagerClient* fake_session_manager_client_; | |
275 | |
276 private: | |
277 DISALLOW_COPY_AND_ASSIGN(WallpaperManagerPolicyTest); | |
278 }; | |
279 | |
280 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_SetResetClear) { | |
281 RegisterUser(kTestUsers[0]); | |
282 RegisterUser(kTestUsers[1]); | |
283 StartupUtils::MarkOobeCompleted(); | |
284 } | |
285 | |
286 // Verifies that the wallpaper can be set and re-set through policy and that | |
287 // setting policy for a user that is not logged in doesn't affect the current | |
288 // user. Also verifies that after the policy has been cleared, the wallpaper | |
289 // reverts to default. | |
290 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, SetResetClear) { | |
291 WallpaperInfo info; | |
292 LoginUser(kTestUsers[0]); | |
293 base::RunLoop().RunUntilIdle(); | |
294 | |
295 // First user: Wait until default wallpaper has been loaded (happens | |
296 // automatically) and store color to recognize it later. | |
297 RunUntilWallpaperChangeCount(1); | |
298 const SkColor original_background_color = GetAverageBackgroundColor(); | |
299 | |
300 // Second user: Set wallpaper policy to blue image. This should not result in | |
301 // a wallpaper change, which is checked at the very end of this test. | |
302 InjectPolicy(1, kBlueImageFileName); | |
303 | |
304 // First user: Set wallpaper policy to red image and verify average color. | |
305 InjectPolicy(0, kRedImageFileName); | |
306 RunUntilWallpaperChangeCount(2); | |
307 GetUserWallpaperInfo(0, &info); | |
308 ASSERT_EQ(User::POLICY, info.type); | |
309 ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor()); | |
310 | |
311 // First user: Set wallpaper policy to green image and verify average color. | |
312 InjectPolicy(0, kGreenImageFileName); | |
313 RunUntilWallpaperChangeCount(3); | |
314 GetUserWallpaperInfo(0, &info); | |
315 ASSERT_EQ(User::POLICY, info.type); | |
316 ASSERT_EQ(kGreenImageColor, GetAverageBackgroundColor()); | |
317 | |
318 // First user: Clear wallpaper policy and verify that the default wallpaper is | |
319 // set again. | |
320 InjectPolicy(0, ""); | |
321 RunUntilWallpaperChangeCount(4); | |
322 GetUserWallpaperInfo(0, &info); | |
323 ASSERT_EQ(User::DEFAULT, info.type); | |
324 ASSERT_EQ(original_background_color, GetAverageBackgroundColor()); | |
325 | |
326 // Check wallpaper change count to ensure that setting the second user's | |
327 // wallpaper didn't have any effect. | |
328 ASSERT_EQ(4, wallpaper_change_count_); | |
329 } | |
330 | |
331 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, | |
332 PRE_PRE_PRE_WallpaperOnLoginScreen) { | |
333 RegisterUser(kTestUsers[0]); | |
334 RegisterUser(kTestUsers[1]); | |
335 StartupUtils::MarkOobeCompleted(); | |
336 } | |
337 | |
338 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, | |
339 PRE_PRE_WallpaperOnLoginScreen) { | |
340 LoginUser(kTestUsers[0]); | |
341 | |
342 // Wait until default wallpaper has been loaded. | |
343 RunUntilWallpaperChangeCount(1); | |
344 | |
345 // Set wallpaper policy to red image. | |
346 InjectPolicy(0, kRedImageFileName); | |
347 | |
348 // Run until wallpaper has changed. | |
349 RunUntilWallpaperChangeCount(2); | |
350 ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor()); | |
351 } | |
352 | |
353 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_WallpaperOnLoginScreen) { | |
354 LoginUser(kTestUsers[1]); | |
355 | |
356 // Wait until default wallpaper has been loaded. | |
357 RunUntilWallpaperChangeCount(1); | |
358 | |
359 // Set wallpaper policy to green image. | |
360 InjectPolicy(1, kGreenImageFileName); | |
361 | |
362 // Run until wallpaper has changed. | |
363 RunUntilWallpaperChangeCount(2); | |
364 ASSERT_EQ(kGreenImageColor, GetAverageBackgroundColor()); | |
365 } | |
366 | |
367 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, WallpaperOnLoginScreen) { | |
368 // Wait for active pod's wallpaper to be loaded. | |
369 RunUntilWallpaperChangeCount(1); | |
370 ASSERT_EQ(kGreenImageColor, GetAverageBackgroundColor()); | |
371 | |
372 // Select the second pod (belonging to user 1). | |
373 ASSERT_TRUE(content::ExecuteScript( | |
374 static_cast<chromeos::LoginDisplayHostImpl*>( | |
375 chromeos::LoginDisplayHostImpl::default_host())->GetOobeUI()-> | |
376 web_ui()->GetWebContents(), | |
377 "document.getElementsByClassName('pod')[1].focus();")); | |
378 RunUntilWallpaperChangeCount(2); | |
379 ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor()); | |
380 } | |
381 | |
382 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_PRE_PersistOverLogout) { | |
383 RegisterUser(kTestUsers[0]); | |
384 StartupUtils::MarkOobeCompleted(); | |
385 } | |
386 | |
387 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_PersistOverLogout) { | |
388 LoginUser(kTestUsers[0]); | |
389 | |
390 // Wait until default wallpaper has been loaded. | |
391 RunUntilWallpaperChangeCount(1); | |
392 | |
393 // Set wallpaper policy to red image. | |
394 InjectPolicy(0, kRedImageFileName); | |
395 | |
396 // Run until wallpaper has changed. | |
397 RunUntilWallpaperChangeCount(2); | |
398 ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor()); | |
399 } | |
400 | |
401 IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PersistOverLogout) { | |
402 LoginUser(kTestUsers[0]); | |
403 | |
404 // Wait until wallpaper has been loaded. | |
405 RunUntilWallpaperChangeCount(1); | |
406 ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor()); | |
407 } | |
408 | |
409 INSTANTIATE_TEST_CASE_P(WallpaperManagerPolicyTestInstantiation, | |
410 WallpaperManagerPolicyTest, testing::Bool()); | |
411 | |
412 } // namespace chromeos | |
OLD | NEW |