| 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 |