| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/files/file_path.h" |
| #include "base/functional/bind.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/test/bind.h" |
| #include "base/test/mock_callback.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/test_future.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/enterprise/remote_commands/user_remote_commands_service_factory.h" |
| #include "chrome/browser/policy/chrome_browser_policy_connector.h" |
| #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h" |
| #include "chrome/browser/policy/device_management_service_configuration.h" |
| #include "chrome/browser/prefs/browser_prefs.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/signin/chrome_signin_client_factory.h" |
| #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" |
| #include "chrome/browser/signin/signin_util.h" |
| #include "chrome/browser/signin/test_signin_client_builder.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/account_id/account_id.h" |
| #include "components/policy/core/browser/browser_policy_connector.h" |
| #include "components/policy/core/common/cloud/cloud_external_data_manager.h" |
| #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| #include "components/policy/core/common/cloud/mock_device_management_service.h" |
| #include "components/policy/core/common/cloud/mock_user_cloud_policy_store.h" |
| #include "components/policy/core/common/cloud/test/policy_builder.h" |
| #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" |
| #include "components/policy/core/common/schema_registry.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "net/base/net_errors.h" |
| #include "net/http/http_status_code.h" |
| #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" |
| #include "services/network/test/test_network_connection_tracker.h" |
| #include "services/network/test/test_url_loader_factory.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| #include "chromeos/lacros/lacros_test_helper.h" |
| #endif |
| |
| #if BUILDFLAG(IS_ANDROID) |
| #include "chrome/browser/policy/cloud/user_policy_signin_service_mobile.h" |
| #else |
| #include "chrome/browser/policy/cloud/user_policy_signin_service.h" |
| #endif |
| |
| namespace em = enterprise_management; |
| |
| using testing::_; |
| using testing::AnyNumber; |
| using testing::Mock; |
| using testing::Return; |
| using testing::SaveArg; |
| |
| namespace policy { |
| |
| namespace { |
| |
| constexpr char kTestUser[] = "testuser@test.com"; |
| |
| constexpr char kHostedDomainResponse[] = R"( |
| { |
| "hd": "test.com" |
| })"; |
| |
| std::unique_ptr<UserCloudPolicyManager> BuildCloudPolicyManager() { |
| auto store = std::make_unique<MockUserCloudPolicyStore>(); |
| EXPECT_CALL(*store, Load()).Times(AnyNumber()); |
| |
| return std::make_unique<UserCloudPolicyManager>( |
| std::move(store), base::FilePath(), |
| /*cloud_external_data_manager=*/nullptr, |
| base::SingleThreadTaskRunner::GetCurrentDefault(), |
| network::TestNetworkConnectionTracker::CreateGetter()); |
| } |
| |
| class UserPolicySigninServiceTest : public testing::Test { |
| public: |
| UserPolicySigninServiceTest() |
| : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), |
| test_account_id_(AccountId::FromUserEmailGaiaId( |
| kTestUser, |
| signin::GetTestGaiaIdForEmail(kTestUser))), |
| register_completed_(false) { |
| scoped_feature_list_.InitAndEnableFeature( |
| enterprise_commands::kUserRemoteCommands); |
| } |
| |
| MOCK_METHOD1(OnPolicyRefresh, void(bool)); |
| |
| void OnRegisterCompleted( |
| const std::string& dm_token, |
| const std::string& client_id, |
| const std::vector<std::string>& user_affiliation_ids) { |
| register_completed_ = true; |
| dm_token_ = dm_token; |
| client_id_ = client_id; |
| user_affiliation_ids_ = user_affiliation_ids; |
| } |
| |
| void RegisterPolicyClientWithCallback(UserPolicySigninService* service) { |
| UserPolicySigninServiceBase::PolicyRegistrationCallback callback = |
| base::BindOnce(&UserPolicySigninServiceTest::OnRegisterCompleted, |
| base::Unretained(this)); |
| AccountInfo account_info = |
| identity_test_env() |
| ->identity_manager() |
| ->FindExtendedAccountInfoByEmailAddress(kTestUser); |
| if (account_info.IsEmpty()) { |
| account_info = identity_test_env()->MakeAccountAvailable(kTestUser); |
| } |
| DCHECK(!account_info.IsEmpty()); |
| service->RegisterForPolicyWithAccountId(kTestUser, account_info.account_id, |
| std::move(callback)); |
| ASSERT_TRUE(IsRequestActive()); |
| } |
| |
| void SetUp() override { |
| device_management_service_.ScheduleInitialization(0); |
| base::RunLoop().RunUntilIdle(); |
| |
| UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting( |
| &device_management_service_); |
| |
| local_state_ = std::make_unique<TestingPrefServiceSimple>(); |
| RegisterLocalState(local_state_->registry()); |
| TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get()); |
| TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( |
| test_url_loader_factory_.GetSafeWeakWrapper()); |
| |
| g_browser_process->browser_policy_connector()->Init( |
| local_state_.get(), test_url_loader_factory_.GetSafeWeakWrapper()); |
| |
| // Create a testing profile with cloud-policy-on-signin enabled, and bring |
| // up a UserCloudPolicyManager with a MockUserCloudPolicyStore. |
| std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs( |
| new sync_preferences::TestingPrefServiceSyncable()); |
| RegisterUserProfilePrefs(prefs->registry()); |
| |
| TestingProfile::Builder builder; |
| builder.SetPrefService( |
| std::unique_ptr<sync_preferences::PrefServiceSyncable>( |
| std::move(prefs))); |
| builder.AddTestingFactory( |
| ChromeSigninClientFactory::GetInstance(), |
| base::BindRepeating(&signin::BuildTestSigninClient)); |
| builder.SetUserCloudPolicyManager(BuildCloudPolicyManager()); |
| profile_ = IdentityTestEnvironmentProfileAdaptor:: |
| CreateProfileForIdentityTestEnvironment(builder); |
| |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()) |
| ->set_profile_can_be_managed_for_testing(true); |
| identity_test_env_adaptor_ = |
| std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get()); |
| |
| manager_ = profile_->GetUserCloudPolicyManager(); |
| DCHECK(manager_); |
| manager_->Init(&schema_registry_); |
| mock_store_ = |
| static_cast<MockUserCloudPolicyStore*>(manager_->core()->store()); |
| DCHECK(mock_store_); |
| AddProfile(); |
| |
| Mock::VerifyAndClearExpectations(mock_store_); |
| } |
| |
| void TearDown() override { |
| UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting(NULL); |
| |
| // Free the profile before we clear out the browser prefs. |
| identity_test_env_adaptor_.reset(); |
| profile_.reset(); |
| TestingBrowserProcess* testing_browser_process = |
| TestingBrowserProcess::GetGlobal(); |
| testing_browser_process->SetLocalState(NULL); |
| local_state_.reset(); |
| testing_browser_process->ShutdownBrowserPolicyConnector(); |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| |
| virtual void AddProfile() { |
| // For this test, the user should not be signed in yet. |
| DCHECK(!identity_test_env()->identity_manager()->HasPrimaryAccount( |
| signin::ConsentLevel::kSignin)); |
| |
| // Initializing UserPolicySigninService while the user is not signed in |
| // should result in the store being cleared to remove any lingering policy. |
| EXPECT_CALL(*mock_store_, Clear()); |
| |
| // Let the SigninService know that the profile has been created. |
| #if BUILDFLAG(IS_ANDROID) |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()) |
| ->OnProfileAdded(profile_.get()); |
| #else |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()) |
| ->OnProfileReady(profile_.get()); |
| #endif // BUILDFLAG(IS_ANDROID) |
| } |
| |
| bool IsRequestActive() { |
| if (identity_test_env()->IsAccessTokenRequestPending()) |
| return true; |
| return test_url_loader_factory_.NumPending() > 0; |
| } |
| |
| void MakeOAuthTokenFetchSucceed() { |
| ASSERT_TRUE(IsRequestActive()); |
| identity_test_env() |
| ->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( |
| "access_token", base::Time::Now()); |
| } |
| |
| void MakeOAuthTokenFetchFail() { |
| ASSERT_TRUE(identity_test_env()->IsAccessTokenRequestPending()); |
| identity_test_env() |
| ->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( |
| GoogleServiceAuthError::FromServiceError("fail")); |
| } |
| |
| void ReportHostedDomainStatus(bool is_hosted_domain) { |
| ASSERT_TRUE(IsRequestActive()); |
| ASSERT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( |
| GaiaUrls::GetInstance()->oauth_user_info_url().spec(), |
| is_hosted_domain ? kHostedDomainResponse : "{}")); |
| } |
| |
| void TestSuccessfulSignin() { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| EXPECT_CALL(*this, OnPolicyRefresh(true)).Times(0); |
| RegisterPolicyClientWithCallback(signin_service); |
| |
| // Sign in to Chrome. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Mimic successful oauth token fetch. |
| MakeOAuthTokenFetchSucceed(); |
| |
| // When the user is from a hosted domain, this should kick off client |
| // registration. |
| DeviceManagementService::JobConfiguration::JobType job_type = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type), |
| SaveArg<0>(&job))); |
| |
| // Now mimic the user being a hosted domain - this should cause a Register() |
| // call. |
| ReportHostedDomainStatus(true); |
| |
| // Should have no more outstanding requests. |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(this); |
| ASSERT_TRUE(job.IsActive()); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REGISTRATION, |
| job_type); |
| |
| std::string expected_dm_token = "dm_token"; |
| std::string expected_user_affiliation_id = "affiliation_id"; |
| em::DeviceManagementResponse dm_response; |
| auto* register_response = dm_response.mutable_register_response(); |
| register_response->set_device_management_token(expected_dm_token); |
| register_response->set_enrollment_type( |
| em::DeviceRegisterResponse::ENTERPRISE); |
| register_response->add_user_affiliation_ids(expected_user_affiliation_id); |
| device_management_service_.SendJobOKNow(&job, dm_response); |
| |
| EXPECT_TRUE(register_completed_); |
| EXPECT_EQ(dm_token_, expected_dm_token); |
| std::vector<std::string> expected_user_affiliation_ids = { |
| expected_user_affiliation_id}; |
| EXPECT_EQ(user_affiliation_ids_, expected_user_affiliation_ids); |
| } |
| |
| signin::IdentityTestEnvironment* identity_test_env() { |
| return identity_test_env_adaptor_->identity_test_env(); |
| } |
| |
| protected: |
| std::unique_ptr<TestingProfile> profile_; |
| std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> |
| identity_test_env_adaptor_; |
| raw_ptr<MockUserCloudPolicyStore, DanglingUntriaged> mock_store_ = |
| nullptr; // Not owned. |
| SchemaRegistry schema_registry_; |
| raw_ptr<UserCloudPolicyManager, DanglingUntriaged> manager_ = |
| nullptr; // Not owned. |
| |
| // BrowserPolicyConnector and UrlFetcherFactory want to initialize and free |
| // various components asynchronously via tasks, so create fake threads here. |
| content::BrowserTaskEnvironment task_environment_; |
| |
| // Used in conjunction with OnRegisterCompleted() to test client registration |
| // callbacks. |
| std::string dm_token_; |
| std::string client_id_; |
| std::vector<std::string> user_affiliation_ids_; |
| |
| // AccountId for the test user. |
| AccountId test_account_id_; |
| |
| // True if OnRegisterCompleted() was called. |
| bool register_completed_; |
| |
| testing::StrictMock<MockJobCreationHandler> job_creation_handler_; |
| FakeDeviceManagementService device_management_service_{ |
| &job_creation_handler_}; |
| |
| std::unique_ptr<TestingPrefServiceSimple> local_state_; |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| chromeos::ScopedLacrosServiceTestHelper test_helper; |
| #endif |
| |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| class UserPolicySigninServiceSignedInTest : public UserPolicySigninServiceTest { |
| public: |
| void AddProfile() override { |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Set the user as signed in. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Let the SigninService know that the profile has been created. |
| #if BUILDFLAG(IS_ANDROID) |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()) |
| ->OnProfileAdded(profile_.get()); |
| #else |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()) |
| ->OnProfileReady(profile_.get()); |
| #endif // BUILDFLAG(IS_ANDROID) |
| } |
| }; |
| |
| TEST_F(UserPolicySigninServiceTest, InitWhileSignedOut) { |
| // Make sure user is not signed in. |
| ASSERT_FALSE(identity_test_env()->identity_manager()->HasPrimaryAccount( |
| signin::ConsentLevel::kSignin)); |
| |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| EXPECT_FALSE(manager_->ArePoliciesRequired()); |
| } |
| |
| // TODO(crbug.com/40831734): Extend the test coverage by merging tests from |
| // ios/chrome/browser/policy/cloud/user_policy_signin_service_unittest.mm here. |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| TEST_F(UserPolicySigninServiceTest, InitRefreshTokenAvailableBeforeSignin) { |
| // Make sure user is not signed in. |
| ASSERT_FALSE(identity_test_env()->identity_manager()->HasPrimaryAccount( |
| signin::ConsentLevel::kSignin)); |
| |
| // No oauth access token yet, so client registration should be deferred. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // Make oauth token available. |
| identity_test_env()->MakeAccountAvailable(kTestUser); |
| |
| // Not signed in yet, so client registration should be deferred. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // Sign in to Chrome. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // Client registration should be in progress since we now have an oauth token |
| // for the authenticated account id. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(IsRequestActive()); |
| EXPECT_TRUE(manager_->ArePoliciesRequired()); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| // TODO(joaodasilva): these tests rely on issuing the OAuth2 login refresh |
| // token after signin. Revisit this after figuring how to handle that on |
| // Android. |
| #if !BUILDFLAG(IS_ANDROID) |
| |
| TEST_F(UserPolicySigninServiceSignedInTest, InitWhileSignedIn) { |
| // UserCloudPolicyManager should be initialized. |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // No oauth access token yet, so client registration should be deferred. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // Client registration should be in progress since we now have an oauth token. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(IsRequestActive()); |
| EXPECT_TRUE(manager_->ArePoliciesRequired()); |
| } |
| |
| TEST_F(UserPolicySigninServiceSignedInTest, InitWhileSignedInOAuthError) { |
| // UserCloudPolicyManager should be initialized. |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // No oauth access token yet, so client registration should be deferred. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // Client registration should be in progress since we now have an oauth token. |
| ASSERT_TRUE(IsRequestActive()); |
| |
| // Now fail the access token fetch. |
| GoogleServiceAuthError error( |
| GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
| identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( |
| error); |
| ASSERT_FALSE(IsRequestActive()); |
| EXPECT_TRUE(manager_->ArePoliciesRequired()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, SignInAfterInit) { |
| // UserCloudPolicyManager should not be initialized since there is no |
| // signed-in user. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Now sign in the user. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Client registration should be in progress since we have an oauth token. |
| ASSERT_TRUE(IsRequestActive()); |
| EXPECT_TRUE(manager_->ArePoliciesRequired()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, SignInWithNonEnterpriseUser) { |
| // UserCloudPolicyManager should not be initialized since there is no |
| // signed-in user. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Now sign in a non-enterprise user (gmail.com domain). |
| identity_test_env()->SetPrimaryAccount("non_enterprise_user@gmail.com", |
| signin::ConsentLevel::kSync); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // UserCloudPolicyManager should not be initialized and there should be no |
| // DMToken request active. |
| ASSERT_TRUE(!manager_->core()->service()); |
| ASSERT_FALSE(IsRequestActive()); |
| EXPECT_FALSE(manager_->ArePoliciesRequired()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, UnregisteredClient) { |
| // UserCloudPolicyManager should not be initialized since there is no |
| // signed-in user. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Now sign in the user. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Client registration should not be in progress since the store is not |
| // yet initialized. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // Complete initialization of the store with no policy (unregistered client). |
| mock_store_->NotifyStoreLoaded(); |
| |
| // Client registration should be in progress since we have an oauth token. |
| ASSERT_TRUE(IsRequestActive()); |
| EXPECT_TRUE(manager_->ArePoliciesRequired()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, RegisteredClient) { |
| // UserCloudPolicyManager should not be initialized since there is no |
| // signed-in user. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Now sign in the user. |
| identity_test_env()->SetPrimaryAccount(kTestUser, |
| signin::ConsentLevel::kSync); |
| |
| // Make oauth token available. |
| identity_test_env()->SetRefreshTokenForPrimaryAccount(); |
| |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Client registration should not be in progress since the store is not |
| // yet initialized. |
| ASSERT_FALSE(manager_->IsClientRegistered()); |
| ASSERT_FALSE(IsRequestActive()); |
| |
| auto data = std::make_unique<enterprise_management::PolicyData>(); |
| data->set_request_token("fake token"); |
| data->set_device_id("fake client id"); |
| mock_store_->set_policy_data_for_testing(std::move(data)); |
| |
| // Since there is a signed-in user expect a policy fetch to be started to |
| // refresh the policy for the user. |
| DeviceManagementService::JobConfiguration::JobType job_type_1 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobConfiguration::JobType job_type_2 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .Times(2) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_1), |
| SaveArg<0>(&job))) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_2), |
| SaveArg<0>(&job))); |
| |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| |
| // Client registration should not be in progress since the client should be |
| // already registered. |
| ASSERT_TRUE(manager_->IsClientRegistered()); |
| ASSERT_FALSE(IsRequestActive()); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REMOTE_COMMANDS, |
| job_type_1); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH, |
| job_type_2); |
| } |
| |
| // Tests that the explicit policy registration can coexist with registration |
| // triggered by sign-in. |
| TEST_F(UserPolicySigninServiceTest, |
| InitializeForSignedInUserWhileRegisteringForPolicy) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| |
| // Start registration process in a temporary client. |
| RegisterPolicyClientWithCallback(signin_service); |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| // Complete several registration steps. |
| MakeOAuthTokenFetchSucceed(); |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation).WillOnce(SaveArg<0>(&job)); |
| ReportHostedDomainStatus(true); |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| ASSERT_TRUE(job.IsActive()); |
| EXPECT_FALSE(register_completed_); |
| |
| // Add a primary account now. This should trigger the UserCloudPolicyManager |
| // initialization. |
| identity_test_env()->MakePrimaryAccountAvailable( |
| kTestUser, signin::ConsentLevel::kSignin); |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| ASSERT_TRUE(manager_->core()->client()); |
| ASSERT_FALSE(manager_->IsClientRegistered()); |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| // New access token request has been sent. |
| ASSERT_TRUE(IsRequestActive()); |
| |
| // Complete registration in the temporary client. |
| em::DeviceManagementResponse registration_response; |
| std::string expected_dm_token = "dm_token"; |
| registration_response.mutable_register_response() |
| ->set_device_management_token(expected_dm_token); |
| registration_response.mutable_register_response()->set_enrollment_type( |
| em::DeviceRegisterResponse::ENTERPRISE); |
| device_management_service_.SendJobOKNow(&job, registration_response); |
| EXPECT_TRUE(register_completed_); |
| EXPECT_EQ(dm_token_, expected_dm_token); |
| } |
| |
| // Tests that the explicit policy registration can coexist with registration |
| // triggered by sign-in. |
| TEST_F(UserPolicySigninServiceTest, |
| RegisterForPolicyWhileInitializingForSignedInUser) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| |
| // Register a primary account now. This should trigger UserCloudPolicyManager |
| // initialization. |
| identity_test_env()->MakePrimaryAccountAvailable( |
| kTestUser, signin::ConsentLevel::kSignin); |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| ASSERT_TRUE(manager_->core()->client()); |
| ASSERT_FALSE(manager_->IsClientRegistered()); |
| // Complete initialization of the store. |
| mock_store_->NotifyStoreLoaded(); |
| // New access token request has been sent. |
| ASSERT_TRUE(IsRequestActive()); |
| // Mimic successful oauth token fetch. |
| MakeOAuthTokenFetchSucceed(); |
| // Request is not active because UserPolicySigninService doesn't use |
| // `test_url_loader_factory_`. |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Start and complete registration in a temporary client. |
| RegisterPolicyClientWithCallback(signin_service); |
| EXPECT_FALSE(register_completed_); |
| ASSERT_TRUE(IsRequestActive()); |
| MakeOAuthTokenFetchSucceed(); |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation).WillOnce(SaveArg<0>(&job)); |
| ReportHostedDomainStatus(true); |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| ASSERT_TRUE(job.IsActive()); |
| em::DeviceManagementResponse registration_response; |
| std::string expected_dm_token = "dm_token"; |
| registration_response.mutable_register_response() |
| ->set_device_management_token(expected_dm_token); |
| registration_response.mutable_register_response()->set_enrollment_type( |
| em::DeviceRegisterResponse::ENTERPRISE); |
| device_management_service_.SendJobOKNow(&job, registration_response); |
| EXPECT_TRUE(register_completed_); |
| EXPECT_EQ(dm_token_, expected_dm_token); |
| } |
| |
| // Tests that `FetchPolicyForSignedInUser()` can be called in the middle of a |
| // client registration. |
| TEST_F(UserPolicySigninServiceTest, |
| FetchPolicyForSignedInUserWhileUnregisteredClient) { |
| identity_test_env()->MakePrimaryAccountAvailable( |
| kTestUser, signin::ConsentLevel::kSignin); |
| |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| ASSERT_FALSE(manager_->IsClientRegistered()); |
| // Client registration should not be in progress since the store is not |
| // yet initialized. |
| ASSERT_FALSE(IsRequestActive()); |
| |
| // `FetchPolicyForSignedInUser()` will notify the callback after the client |
| // registers and fetches policies. |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| network::TestURLLoaderFactory fetch_policy_url_loader_factory; |
| base::test::TestFuture<bool> future; |
| signin_service->FetchPolicyForSignedInUser( |
| test_account_id_, "dm_token", "client-id", std::vector<std::string>(), |
| fetch_policy_url_loader_factory.GetSafeWeakWrapper(), |
| future.GetCallback()); |
| |
| // Complete the store initialization with the registration info. |
| auto data = std::make_unique<enterprise_management::PolicyData>(); |
| data->set_request_token("fake token"); |
| data->set_device_id("fake client id"); |
| mock_store_->set_policy_data_for_testing(std::move(data)); |
| |
| // Since there is a signed-in user expect a policy fetch to be started to |
| // refresh the policy for the user. |
| DeviceManagementService::JobConfiguration::JobType job_type_1 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobConfiguration::JobType job_type_2 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_1), |
| SaveArg<0>(&job))) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_2), |
| SaveArg<0>(&job))); |
| // A task to trigger policy fetch should have been posted to the task queue. |
| |
| mock_store_->NotifyStoreLoaded(); |
| // The client should be registered. |
| ASSERT_TRUE(manager_->IsClientRegistered()); |
| |
| base::RunLoop().RunUntilIdle(); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REMOTE_COMMANDS, |
| job_type_1); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH, |
| job_type_2); |
| |
| EXPECT_CALL(*mock_store_, Store(_)); |
| // Complete the policy fetch request. |
| em::DeviceManagementResponse policy_fetch_response; |
| UserPolicyBuilder policy_builder; |
| policy_builder.Build(); |
| policy_fetch_response.mutable_policy_response()->add_responses()->CopyFrom( |
| policy_builder.policy()); |
| device_management_service_.SendJobOKNow(&job, policy_fetch_response); |
| // The callback isn't called until `Store()` completes. |
| ASSERT_FALSE(future.IsReady()); |
| Mock::VerifyAndClearExpectations(mock_store_); |
| |
| mock_store_->NotifyStoreLoaded(); |
| // `FetchPolicyForSignedInUser()` callback should be executed. |
| ASSERT_TRUE(future.IsReady()); |
| EXPECT_TRUE(future.Get()); |
| } |
| |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| TEST_F(UserPolicySigninServiceSignedInTest, SignOutAfterInit) { |
| // UserCloudPolicyManager should be initialized. |
| EXPECT_EQ(mock_store_->signin_account_id(), test_account_id_); |
| ASSERT_TRUE(manager_->core()->service()); |
| |
| // Signing out will clear the policy from the store. |
| EXPECT_CALL(*mock_store_, Clear()); |
| |
| // Now sign out. |
| identity_test_env()->ClearPrimaryAccount(); |
| |
| // UserCloudPolicyManager should be shut down. |
| ASSERT_FALSE(manager_->core()->service()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientOAuthFailure) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| RegisterPolicyClientWithCallback(signin_service); |
| Mock::VerifyAndClearExpectations(this); |
| |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| ASSERT_TRUE(IsRequestActive()); |
| EXPECT_FALSE(register_completed_); |
| |
| // Cause the access token fetch to fail - callback should be invoked. |
| MakeOAuthTokenFetchFail(); |
| |
| EXPECT_TRUE(register_completed_); |
| EXPECT_TRUE(dm_token_.empty()); |
| ASSERT_FALSE(IsRequestActive()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientNonHostedDomain) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| RegisterPolicyClientWithCallback(signin_service); |
| |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| ASSERT_TRUE(IsRequestActive()); |
| |
| // Cause the access token request to succeed. |
| MakeOAuthTokenFetchSucceed(); |
| |
| // Should be a follow-up fetch to check the hosted-domain status. |
| ASSERT_TRUE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(this); |
| |
| EXPECT_FALSE(register_completed_); |
| |
| // Report that the user is not on a hosted domain - callback should be |
| // invoked reporting a failed fetch. |
| ReportHostedDomainStatus(false); |
| |
| // Since this is not a hosted domain, we should not issue a request for a |
| // DMToken. |
| EXPECT_TRUE(register_completed_); |
| EXPECT_TRUE(dm_token_.empty()); |
| ASSERT_FALSE(IsRequestActive()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientFailedRegistration) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| RegisterPolicyClientWithCallback(signin_service); |
| |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Mimic successful oauth token fetch. |
| MakeOAuthTokenFetchSucceed(); |
| EXPECT_FALSE(register_completed_); |
| |
| // When the user is from a hosted domain, this should kick off client |
| // registration. |
| DeviceManagementService::JobConfiguration::JobType job_type = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type), |
| SaveArg<0>(&job))); |
| |
| // Now mimic the user being a hosted domain - this should cause a Register() |
| // call. |
| ReportHostedDomainStatus(true); |
| |
| // Should have no more outstanding requests. |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| ASSERT_TRUE(job.IsActive()); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REGISTRATION, |
| job_type); |
| EXPECT_FALSE(register_completed_); |
| |
| // Make client registration fail (hosted domain user that is not managed). |
| device_management_service_.SendJobResponseNow( |
| &job, net::OK, DeviceManagementService::kDeviceManagementNotAllowed, |
| em::DeviceManagementResponse()); |
| |
| EXPECT_TRUE(register_completed_); |
| EXPECT_TRUE(dm_token_.empty()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientSucceeded) { |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| RegisterPolicyClientWithCallback(signin_service); |
| |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Mimic successful oauth token fetch. |
| MakeOAuthTokenFetchSucceed(); |
| |
| // When the user is from a hosted domain, this should kick off client |
| // registration. |
| DeviceManagementService::JobConfiguration::JobType job_type = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobForTesting job; |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type), |
| SaveArg<0>(&job))); |
| |
| // Now mimic the user being a hosted domain - this should cause a Register() |
| // call. |
| ReportHostedDomainStatus(true); |
| |
| // Should have no more outstanding requests. |
| ASSERT_FALSE(IsRequestActive()); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| ASSERT_TRUE(job.IsActive()); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REGISTRATION, |
| job_type); |
| EXPECT_FALSE(register_completed_); |
| |
| em::DeviceManagementResponse registration_response; |
| std::string expected_dm_token = "dm_token"; |
| registration_response.mutable_register_response() |
| ->set_device_management_token(expected_dm_token); |
| registration_response.mutable_register_response()->set_enrollment_type( |
| em::DeviceRegisterResponse::ENTERPRISE); |
| device_management_service_.SendJobOKNow(&job, registration_response); |
| |
| EXPECT_TRUE(register_completed_); |
| EXPECT_EQ(dm_token_, expected_dm_token); |
| // UserCloudPolicyManager should not be initialized. |
| ASSERT_FALSE(manager_->core()->service()); |
| } |
| |
| // Tests `FetchPolicyForSignedInUser()` with no active client. |
| TEST_F(UserPolicySigninServiceTest, FetchPolicyForSignedInUser) { |
| mock_store_->NotifyStoreLoaded(); |
| identity_test_env()->MakeAccountAvailable(kTestUser); |
| |
| // `FetchPolicyForSignedInUser()` will create a new registered client and |
| // fetch policies with it. |
| DeviceManagementService::JobConfiguration::JobType job_type_1 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| DeviceManagementService::JobConfiguration::JobType job_type_2 = |
| DeviceManagementService::JobConfiguration::TYPE_INVALID; |
| em::DeviceManagementRequest policy_fetch_request; |
| DeviceManagementService::JobForTesting job; |
| base::MockCallback<CloudPolicyClient::DeviceDMTokenCallback> |
| device_dm_token_callback; |
| std::string device_dm_token = "device-dm-token"; |
| std::string user_affiliation_id = "user-affiliation_id"; |
| |
| EXPECT_CALL(job_creation_handler_, OnJobCreation) |
| .WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type_1), |
| SaveArg<0>(&job))) |
| .WillOnce(DoAll( |
| device_management_service_.CaptureJobType(&job_type_2), |
| device_management_service_.CaptureRequest(&policy_fetch_request), |
| SaveArg<0>(&job))); |
| EXPECT_CALL(device_dm_token_callback, |
| Run(::testing::ElementsAre(user_affiliation_id))) |
| .WillOnce(Return(device_dm_token)); |
| |
| UserPolicySigninService* signin_service = |
| UserPolicySigninServiceFactory::GetForProfile(profile_.get()); |
| network::TestURLLoaderFactory fetch_policy_url_loader_factory; |
| base::test::TestFuture<bool> future; |
| |
| signin_service->SetDeviceDMTokenCallbackForTesting( |
| device_dm_token_callback.Get()); |
| signin_service->FetchPolicyForSignedInUser( |
| test_account_id_, "dm_token", "client-id", {user_affiliation_id}, |
| fetch_policy_url_loader_factory.GetSafeWeakWrapper(), |
| future.GetCallback()); |
| // The client should be registered. |
| ASSERT_TRUE(manager_->IsClientRegistered()); |
| // A task to trigger policy fetch should have been posted to the task queue. |
| // Let it execute. |
| base::RunLoop().RunUntilIdle(); |
| Mock::VerifyAndClearExpectations(&job_creation_handler_); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_REMOTE_COMMANDS, |
| job_type_1); |
| EXPECT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH, |
| job_type_2); |
| |
| EXPECT_EQ( |
| device_dm_token, |
| policy_fetch_request.policy_request().requests(0).device_dm_token()); |
| |
| // Complete the policy fetch request. |
| EXPECT_CALL(*mock_store_, Store(_)); |
| em::DeviceManagementResponse policy_fetch_response; |
| UserPolicyBuilder policy_builder; |
| policy_builder.Build(); |
| policy_fetch_response.mutable_policy_response()->add_responses()->CopyFrom( |
| policy_builder.policy()); |
| device_management_service_.SendJobOKNow(&job, policy_fetch_response); |
| // The callback isn't called until `Store()` completes. |
| ASSERT_FALSE(future.IsReady()); |
| Mock::VerifyAndClearExpectations(mock_store_); |
| |
| mock_store_->NotifyStoreLoaded(); |
| // `FetchPolicyForSignedInUser()` callback should be executed. |
| ASSERT_TRUE(future.IsReady()); |
| EXPECT_TRUE(future.Get()); |
| } |
| |
| TEST_F(UserPolicySigninServiceTest, SignOutThenSignInAgain) { |
| // Explicitly forcing this call is necessary for the clearing of the primary |
| // account to result in the account being fully removed in this testing |
| // context |
| identity_test_env()->EnableRemovalOfExtendedAccountInfo(); |
| |
| ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin()); |
| |
| EXPECT_CALL(*mock_store_, Clear()); |
| |
| identity_test_env()->ClearPrimaryAccount(); |
| ASSERT_FALSE(manager_->core()->service()); |
| |
| // Now sign in again. |
| ASSERT_NO_FATAL_FAILURE(TestSuccessfulSignin()); |
| } |
| |
| } // namespace |
| |
| } // namespace policy |