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 "chrome/browser/chromeos/policy/consumer_management_service.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback.h" 10 #include "base/prefs/pref_registry_simple.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/prefs/testing_pref_service.h" 13 #include "base/run_loop.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process_platform_part.h" 16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/chromeos/login/users/mock_user_manager.h" 18 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" 19 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 20 #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h" 21 #include "chrome/browser/chromeos/policy/device_policy_builder.h" 22 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h" 23 #include "chrome/browser/chromeos/policy/fake_device_cloud_policy_initializer.h" 24 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" 25 #include "chrome/browser/notifications/notification_ui_manager.h" 26 #include "chrome/browser/profiles/profile.h" 27 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 28 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 29 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 30 #include "chrome/browser/signin/signin_manager_factory.h" 31 #include "chrome/common/pref_names.h" 32 #include "chrome/test/base/browser_with_test_window_test.h" 33 #include "chrome/test/base/scoped_testing_local_state.h" 34 #include "chrome/test/base/testing_browser_process.h" 35 #include "chrome/test/base/testing_profile.h" 36 #include "chrome/test/base/testing_profile_manager.h" 37 #include "chromeos/dbus/cryptohome/rpc.pb.h" 38 #include "chromeos/dbus/cryptohome_client.h" 39 #include "chromeos/dbus/mock_cryptohome_client.h" 40 #include "components/signin/core/browser/profile_oauth2_token_service.h" 41 #include "components/signin/core/browser/signin_manager_base.h" 42 #include "content/public/browser/notification_details.h" 43 #include "content/public/browser/notification_source.h" 44 #include "google_apis/gaia/google_service_auth_error.h" 45 #include "policy/proto/device_management_backend.pb.h" 46 #include "testing/gmock/include/gmock/gmock.h" 47 #include "testing/gtest/include/gtest/gtest.h" 48 49 using testing::Invoke; 50 using testing::NiceMock; 51 using testing::Return; 52 using testing::_; 53 54 namespace em = enterprise_management; 55 56 namespace { 57 const char* kAttributeOwnerId = "consumer_management.owner_id"; 58 const char* kTestOwner = "test (at) chromium.org.test"; 59 } 60 61 namespace policy { 62 63 class ConsumerManagementServiceTest : public BrowserWithTestWindowTest { 64 public: 65 ConsumerManagementServiceTest() 66 : cryptohome_result_(false), 67 set_owner_status_(false) { 68 ON_CALL(mock_cryptohome_client_, GetBootAttribute(_, _)) 69 .WillByDefault( 70 Invoke(this, &ConsumerManagementServiceTest::MockGetBootAttribute)); 71 ON_CALL(mock_cryptohome_client_, SetBootAttribute(_, _)) 72 .WillByDefault( 73 Invoke(this, &ConsumerManagementServiceTest::MockSetBootAttribute)); 74 ON_CALL(mock_cryptohome_client_, FlushAndSignBootAttributes(_, _)) 75 .WillByDefault( 76 Invoke(this, 77 &ConsumerManagementServiceTest:: 78 MockFlushAndSignBootAttributes)); 79 } 80 81 virtual void SetUp() OVERRIDE { 82 BrowserWithTestWindowTest::SetUp(); 83 84 testing_profile_manager_.reset(new TestingProfileManager( 85 TestingBrowserProcess::GetGlobal())); 86 ASSERT_TRUE(testing_profile_manager_->SetUp()); 87 88 service_.reset(new ConsumerManagementService(&mock_cryptohome_client_, 89 NULL)); 90 } 91 92 virtual void TearDown() OVERRIDE { 93 testing_profile_manager_.reset(); 94 95 service_.reset(); 96 97 BrowserWithTestWindowTest::TearDown(); 98 } 99 100 ConsumerManagementService::EnrollmentStage GetEnrollmentStage() { 101 return static_cast<ConsumerManagementService::EnrollmentStage>( 102 g_browser_process->local_state()->GetInteger( 103 prefs::kConsumerManagementEnrollmentStage)); 104 } 105 106 void SetEnrollmentStage(ConsumerManagementService::EnrollmentStage stage) { 107 g_browser_process->local_state()->SetInteger( 108 prefs::kConsumerManagementEnrollmentStage, stage); 109 } 110 111 void MockGetBootAttribute( 112 const cryptohome::GetBootAttributeRequest& request, 113 const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) { 114 get_boot_attribute_request_ = request; 115 callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_); 116 } 117 118 void MockSetBootAttribute( 119 const cryptohome::SetBootAttributeRequest& request, 120 const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) { 121 set_boot_attribute_request_ = request; 122 callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_); 123 } 124 125 void MockFlushAndSignBootAttributes( 126 const cryptohome::FlushAndSignBootAttributesRequest& request, 127 const chromeos::CryptohomeClient::ProtobufMethodCallback& callback) { 128 callback.Run(cryptohome_status_, cryptohome_result_, cryptohome_reply_); 129 } 130 131 void OnGetOwnerDone(const std::string& owner) { 132 owner_ = owner; 133 } 134 135 void OnSetOwnerDone(bool status) { 136 set_owner_status_ = status; 137 } 138 139 // Variables for building the service. 140 NiceMock<chromeos::MockCryptohomeClient> mock_cryptohome_client_; 141 scoped_ptr<ConsumerManagementService> service_; 142 143 scoped_ptr<TestingProfileManager> testing_profile_manager_; 144 145 // Variables for setting the return value or catching the arguments of mock 146 // functions. 147 chromeos::DBusMethodCallStatus cryptohome_status_; 148 bool cryptohome_result_; 149 cryptohome::BaseReply cryptohome_reply_; 150 cryptohome::GetBootAttributeRequest get_boot_attribute_request_; 151 cryptohome::SetBootAttributeRequest set_boot_attribute_request_; 152 std::string owner_; 153 bool set_owner_status_; 154 }; 155 156 TEST_F(ConsumerManagementServiceTest, CanGetEnrollmentStage) { 157 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_NONE, 158 service_->GetEnrollmentStage()); 159 160 SetEnrollmentStage(ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED); 161 162 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED, 163 service_->GetEnrollmentStage()); 164 } 165 166 TEST_F(ConsumerManagementServiceTest, CanSetEnrollmentStage) { 167 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_NONE, 168 GetEnrollmentStage()); 169 170 service_->SetEnrollmentStage( 171 ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED); 172 173 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED, 174 GetEnrollmentStage()); 175 } 176 177 TEST_F(ConsumerManagementServiceTest, CanGetOwner) { 178 cryptohome_status_ = chromeos::DBUS_METHOD_CALL_SUCCESS; 179 cryptohome_result_ = true; 180 cryptohome_reply_.MutableExtension(cryptohome::GetBootAttributeReply::reply)-> 181 set_value(kTestOwner); 182 183 service_->GetOwner(base::Bind(&ConsumerManagementServiceTest::OnGetOwnerDone, 184 base::Unretained(this))); 185 186 EXPECT_EQ(kAttributeOwnerId, get_boot_attribute_request_.name()); 187 EXPECT_EQ(kTestOwner, owner_); 188 } 189 190 TEST_F(ConsumerManagementServiceTest, GetOwnerReturnsAnEmptyStringWhenItFails) { 191 cryptohome_status_ = chromeos::DBUS_METHOD_CALL_FAILURE; 192 cryptohome_result_ = false; 193 cryptohome_reply_.MutableExtension(cryptohome::GetBootAttributeReply::reply)-> 194 set_value(kTestOwner); 195 196 service_->GetOwner(base::Bind(&ConsumerManagementServiceTest::OnGetOwnerDone, 197 base::Unretained(this))); 198 199 EXPECT_EQ("", owner_); 200 } 201 202 TEST_F(ConsumerManagementServiceTest, CanSetOwner) { 203 cryptohome_status_ = chromeos::DBUS_METHOD_CALL_SUCCESS; 204 cryptohome_result_ = true; 205 206 service_->SetOwner(kTestOwner, 207 base::Bind(&ConsumerManagementServiceTest::OnSetOwnerDone, 208 base::Unretained(this))); 209 210 EXPECT_EQ(kAttributeOwnerId, set_boot_attribute_request_.name()); 211 EXPECT_EQ(kTestOwner, set_boot_attribute_request_.value()); 212 EXPECT_TRUE(set_owner_status_); 213 } 214 215 TEST_F(ConsumerManagementServiceTest, SetOwnerReturnsFalseWhenItFails) { 216 cryptohome_status_ = chromeos::DBUS_METHOD_CALL_FAILURE; 217 cryptohome_result_ = false; 218 219 service_->SetOwner(kTestOwner, 220 base::Bind(&ConsumerManagementServiceTest::OnSetOwnerDone, 221 base::Unretained(this))); 222 223 EXPECT_FALSE(set_owner_status_); 224 } 225 226 class ConsumerManagementServiceEnrollmentTest 227 : public ConsumerManagementServiceTest { 228 public: 229 ConsumerManagementServiceEnrollmentTest() 230 : mock_user_manager_(new NiceMock<chromeos::MockUserManager>()), 231 scoped_user_manager_enabler_(mock_user_manager_), 232 fake_initializer_(new FakeDeviceCloudPolicyInitializer()), 233 enrollment_status_(EnrollmentStatus::ForStatus( 234 EnrollmentStatus::STATUS_SUCCESS)) { 235 // Set up MockUserManager. The first user will be the owner. 236 mock_user_manager_->AddUser(kTestOwner); 237 238 // Return false for IsCurrentUserOwner() so that the enrollment stage is not 239 // reset. 240 ON_CALL(*mock_user_manager_, IsCurrentUserOwner()) 241 .WillByDefault(Return(false)); 242 243 // Inject FakeDeviceCloudPolicyInitializer. 244 BrowserPolicyConnectorChromeOS* connector = 245 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 246 connector->SetDeviceCloudPolicyInitializerForTesting( 247 scoped_ptr<DeviceCloudPolicyInitializer>(fake_initializer_)); 248 } 249 250 virtual void SetUp() OVERRIDE { 251 ConsumerManagementServiceTest::SetUp(); 252 253 // Set up the testing profile. 254 profile()->set_profile_name(kTestOwner); 255 256 // Set up FakeProfileOAuth2TokenService and issue a fake refresh token. 257 ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory( 258 profile(), &BuildAutoIssuingFakeProfileOAuth2TokenService); 259 GetFakeProfileOAuth2TokenService()-> 260 IssueRefreshTokenForUser(kTestOwner, "fake_token"); 261 262 // Set up the authenticated user name and ID. 263 SigninManagerFactory::GetForProfile(profile())-> 264 SetAuthenticatedUsername(kTestOwner); 265 266 // The service should continue the enrollment process if the stage is 267 // ENROLLMENT_STAGE_OWNER_STORED. 268 SetEnrollmentStage( 269 ConsumerManagementService::ENROLLMENT_STAGE_OWNER_STORED); 270 } 271 272 virtual void TearDown() OVERRIDE { 273 g_browser_process->notification_ui_manager()->CancelAll(); 274 275 ConsumerManagementServiceTest::TearDown(); 276 } 277 278 FakeProfileOAuth2TokenService* GetFakeProfileOAuth2TokenService() { 279 return static_cast<FakeProfileOAuth2TokenService*>( 280 ProfileOAuth2TokenServiceFactory::GetForProfile(profile())); 281 } 282 283 bool HasEnrollmentNotification() { 284 return g_browser_process->notification_ui_manager()-> 285 FindById("consumer_management.enroll"); 286 } 287 288 void RunEnrollmentTest() { 289 // Send the profile prepared notification to continue the enrollment. 290 service_->Observe(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, 291 content::Source<void>(NULL), // Not used. 292 content::Details<Profile>(profile())); 293 base::RunLoop().RunUntilIdle(); 294 } 295 296 NiceMock<chromeos::MockUserManager>* mock_user_manager_; 297 chromeos::ScopedUserManagerEnabler scoped_user_manager_enabler_; 298 FakeDeviceCloudPolicyInitializer* fake_initializer_; 299 EnrollmentStatus enrollment_status_; 300 }; 301 302 TEST_F(ConsumerManagementServiceEnrollmentTest, EnrollsSuccessfully) { 303 EXPECT_FALSE(fake_initializer_->was_start_enrollment_called()); 304 305 RunEnrollmentTest(); 306 307 EXPECT_TRUE(fake_initializer_->was_start_enrollment_called()); 308 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_SUCCESS, 309 GetEnrollmentStage()); 310 EXPECT_FALSE(HasEnrollmentNotification()); 311 } 312 313 TEST_F(ConsumerManagementServiceEnrollmentTest, 314 ShowsDesktopNotificationAndResetsEnrollmentStageIfCurrentUserIsOwner) { 315 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_OWNER_STORED, 316 GetEnrollmentStage()); 317 EXPECT_FALSE(HasEnrollmentNotification()); 318 EXPECT_CALL(*mock_user_manager_, IsCurrentUserOwner()) 319 .WillOnce(Return(true)); 320 321 RunEnrollmentTest(); 322 323 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_NONE, 324 GetEnrollmentStage()); 325 EXPECT_TRUE(HasEnrollmentNotification()); 326 } 327 328 TEST_F(ConsumerManagementServiceEnrollmentTest, FailsToGetAccessToken) { 329 // Disable auto-posting so that RunEnrollmentTest() should stop and wait for 330 // the access token to be available. 331 GetFakeProfileOAuth2TokenService()-> 332 set_auto_post_fetch_response_on_message_loop(false); 333 334 RunEnrollmentTest(); 335 336 // The service should have a pending token request. 337 OAuth2TokenService::Request* token_request = 338 service_->GetTokenRequestForTesting(); 339 EXPECT_TRUE(token_request); 340 341 // Tell the service that the access token is not available because of some 342 // backend issue. 343 service_->OnGetTokenFailure( 344 token_request, 345 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR)); 346 347 EXPECT_FALSE(fake_initializer_->was_start_enrollment_called()); 348 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_GET_TOKEN_FAILED, 349 GetEnrollmentStage()); 350 } 351 352 TEST_F(ConsumerManagementServiceEnrollmentTest, FailsToRegister) { 353 EXPECT_FALSE(fake_initializer_->was_start_enrollment_called()); 354 fake_initializer_->set_enrollment_status(EnrollmentStatus::ForStatus( 355 EnrollmentStatus::STATUS_REGISTRATION_FAILED)); 356 357 RunEnrollmentTest(); 358 359 EXPECT_TRUE(fake_initializer_->was_start_enrollment_called()); 360 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_DM_SERVER_FAILED, 361 GetEnrollmentStage()); 362 } 363 364 TEST_F(ConsumerManagementServiceEnrollmentTest, 365 ShowsDesktopNotificationOnlyIfEnrollmentIsAlreadyCompleted) { 366 SetEnrollmentStage(ConsumerManagementService::ENROLLMENT_STAGE_CANCELED); 367 EXPECT_FALSE(HasEnrollmentNotification()); 368 369 RunEnrollmentTest(); 370 371 EXPECT_FALSE(fake_initializer_->was_start_enrollment_called()); 372 EXPECT_EQ(ConsumerManagementService::ENROLLMENT_STAGE_NONE, 373 GetEnrollmentStage()); 374 EXPECT_TRUE(HasEnrollmentNotification()); 375 } 376 377 class ConsumerManagementServiceStatusTest 378 : public chromeos::DeviceSettingsTestBase { 379 public: 380 ConsumerManagementServiceStatusTest() 381 : testing_local_state_(TestingBrowserProcess::GetGlobal()), 382 service_(NULL, &device_settings_service_) { 383 } 384 385 void SetEnrollmentStage(ConsumerManagementService::EnrollmentStage stage) { 386 testing_local_state_.Get()->SetInteger( 387 prefs::kConsumerManagementEnrollmentStage, stage); 388 } 389 390 void SetManagementMode(em::PolicyData::ManagementMode mode) { 391 device_policy_.policy_data().set_management_mode(mode); 392 device_policy_.Build(); 393 device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); 394 ReloadDeviceSettings(); 395 } 396 397 ScopedTestingLocalState testing_local_state_; 398 ConsumerManagementService service_; 399 }; 400 401 TEST_F(ConsumerManagementServiceStatusTest, GetStatusAndGetStatusStringWork) { 402 EXPECT_EQ(ConsumerManagementService::STATUS_UNKNOWN, service_.GetStatus()); 403 EXPECT_EQ("StatusUnknown", service_.GetStatusString()); 404 405 SetManagementMode(em::PolicyData::NOT_MANAGED); 406 SetEnrollmentStage(ConsumerManagementService::ENROLLMENT_STAGE_NONE); 407 408 EXPECT_EQ(ConsumerManagementService::STATUS_UNENROLLED, service_.GetStatus()); 409 EXPECT_EQ("StatusUnenrolled", service_.GetStatusString()); 410 411 SetEnrollmentStage(ConsumerManagementService::ENROLLMENT_STAGE_REQUESTED); 412 413 EXPECT_EQ(ConsumerManagementService::STATUS_ENROLLING, service_.GetStatus()); 414 EXPECT_EQ("StatusEnrolling", service_.GetStatusString()); 415 416 SetManagementMode(em::PolicyData::CONSUMER_MANAGED); 417 SetEnrollmentStage(ConsumerManagementService::ENROLLMENT_STAGE_SUCCESS); 418 419 EXPECT_EQ(ConsumerManagementService::STATUS_ENROLLED, service_.GetStatus()); 420 EXPECT_EQ("StatusEnrolled", service_.GetStatusString()); 421 422 // TODO(davidyu): Test for STATUS_UNENROLLING when it is implemented. 423 // http://crbug.com/353050. 424 } 425 426 } // namespace policy 427