// 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 "chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/policy/core/user_cloud_policy_token_forwarder.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/policy/cloud/cloud_policy_test_utils.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
#include "chromeos/ash/components/install_attributes/stub_install_attributes.h"
#include "components/enterprise/browser/reporting/common_pref_names.h"
#include "components/enterprise/browser/reporting/report_scheduler.h"
#include "components/policy/core/common/cloud/cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
#include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/policy/core/common/cloud/mock_device_management_service.h"
#include "components/policy/core/common/external_data_fetcher.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/core/common/schema_registry.h"
#include "components/policy/policy_constants.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/scope_set.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
namespace {
namespace em = ::enterprise_management;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Mock;
using ::testing::SaveArg;
const char kUMAReregistrationResult[] =
"Enterprise.UserPolicyChromeOS.ReregistrationResult";
enum PolicyRequired { POLICY_NOT_REQUIRED, POLICY_REQUIRED };
void SendJobOKNowForBinding(FakeDeviceManagementService* service,
DeviceManagementService::JobForTesting job,
const em::DeviceManagementResponse& response) {
service->SendJobOKNow(&job, response);
}
} // namespace
using PolicyEnforcement = UserCloudPolicyManagerAsh::PolicyEnforcement;
constexpr char kEmail[] = "[email protected]";
constexpr char kTestGaiaId[] = "12345";
constexpr char kEmail2[] = "[email protected]";
constexpr char kTestGaiaId2[] = "123456";
constexpr char kOAuth2AccessTokenData[] = R"(
{
"access_token": "5678",
"expires_in": 3600
})";
constexpr char kOAuthToken[] = "5678";
constexpr char kDMToken[] = "dmtoken123";
constexpr char kDeviceId[] = "id987";
// UserCloudPolicyManagerAsh test class that can be used with different
// feature flags.
class UserCloudPolicyManagerAshTest
: public testing::TestWithParam<std::vector<base::test::FeatureRef>> {
public:
UserCloudPolicyManagerAshTest(const UserCloudPolicyManagerAshTest&) = delete;
UserCloudPolicyManagerAshTest& operator=(
const UserCloudPolicyManagerAshTest&) = delete;
// Note: This method has to be public, so that a pointer to it may be obtained
// in the test.
void MakeManagerWithPreloadedStore(const base::TimeDelta& fetch_timeout) {
std::unique_ptr<MockCloudPolicyStore> store =
std::make_unique<MockCloudPolicyStore>();
store->set_policy_data_for_testing(
std::make_unique<em::PolicyData>(policy_data_));
store->policy_map_ = policy_map_.Clone();
store->NotifyStoreLoaded();
CreateManager(std::move(store), fetch_timeout,
PolicyEnforcement::kPolicyRequired);
// The manager should already be initialized by this point.
EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
protected:
UserCloudPolicyManagerAshTest()
: store_(nullptr),
external_data_manager_(nullptr),
task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()),
profile_(nullptr),
signin_profile_(nullptr),
user_manager_(new ash::FakeChromeUserManager()),
user_manager_enabler_(base::WrapUnique(user_manager_.get())),
test_signin_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_signin_url_loader_factory_)),
test_system_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_system_url_loader_factory_)) {}
void SetUp() override {
ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
scoped_feature_list_.InitWithFeatures(
GetParam() /* enabled_features */,
std::vector<base::test::FeatureRef>() /* disabled_features */);
// The initialization path that blocks on the initial policy fetch requires
// a signin Profile to use its URLRequestContext.
profile_manager_ = std::make_unique<TestingProfileManager>(
TestingBrowserProcess::GetGlobal());
ASSERT_TRUE(profile_manager_->SetUp());
TestingProfile::TestingFactories factories =
IdentityTestEnvironmentProfileAdaptor::
GetIdentityTestEnvironmentFactories();
profile_ = profile_manager_->CreateTestingProfile(
chrome::kInitialProfile,
std::unique_ptr<sync_preferences::PrefServiceSyncable>(), u"", 0,
std::move(factories));
identity_test_env_profile_adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_);
// Usually the signin Profile and the main Profile are separate, but since
// the signin Profile is an OTR Profile then for this test it suffices to
// attach it to the main Profile.
signin_profile_ = TestingProfile::Builder().BuildIncognito(profile_);
ASSERT_EQ(signin_profile_, ash::ProfileHelper::GetSigninProfile());
RegisterLocalState(prefs_.registry());
device_management_service_.ScheduleInitialization(0);
base::RunLoop().RunUntilIdle();
// Set up a policy map for testing.
GetExpectedDefaultPolicy(&policy_map_);
policy_map_.Set(key::kHomepageLocation, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
base::Value("http://chromium.org"), nullptr);
expected_bundle_.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) =
policy_map_.Clone();
// Create fake policy blobs to deliver to the client.
em::DeviceRegisterResponse* register_response =
register_blob_.mutable_register_response();
register_response->set_device_management_token(kDMToken);
em::CloudPolicySettings policy_proto;
policy_proto.mutable_homepagelocation()->set_value("http://chromium.org");
ASSERT_TRUE(
policy_proto.SerializeToString(policy_data_.mutable_policy_value()));
policy_data_.set_policy_type(dm_protocol::kChromeUserPolicyType);
policy_data_.set_device_id(kDeviceId);
policy_data_.set_request_token(kDMToken);
policy_data_.set_device_id("id987");
policy_data_.set_username("[email protected]");
em::PolicyFetchResponse* policy_response =
policy_blob_.mutable_policy_response()->add_responses();
ASSERT_TRUE(
policy_data_.SerializeToString(policy_response->mutable_policy_data()));
AccountId account_id = AccountId::FromUserEmailGaiaId(kEmail, kTestGaiaId);
TestingProfile* profile =
profile_manager_->CreateTestingProfile(account_id.GetUserEmail());
user_manager_->AddUserWithAffiliationAndTypeAndProfile(account_id, false,
user_type_, profile);
user_manager_->SwitchActiveUser(account_id);
ASSERT_TRUE(user_manager_->GetActiveUser());
}
void TearDown() override {
EXPECT_EQ(fatal_error_expected_, fatal_error_encountered_);
if (token_forwarder_)
token_forwarder_->Shutdown();
if (manager_) {
manager_->RemoveObserver(&observer_);
manager_->Shutdown();
}
signin_profile_ = nullptr;
profile_ = nullptr;
identity_test_env_profile_adaptor_.reset();
profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
test_system_shared_loader_factory_->Detach();
test_signin_shared_loader_factory_->Detach();
ash::ConciergeClient::Shutdown();
}
void MakeManagerWithEmptyStore(const base::TimeDelta& fetch_timeout,
PolicyEnforcement enforcement_type) {
std::unique_ptr<MockCloudPolicyStore> store =
std::make_unique<MockCloudPolicyStore>();
EXPECT_CALL(*store, Load());
CreateManager(std::move(store), fetch_timeout, enforcement_type);
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
InitAndConnectManager();
Mock::VerifyAndClearExpectations(store_);
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
}
// Issues the OAuth2 tokens and returns the device management register job
// if the flow succeeded.
DeviceManagementService::JobForTesting IssueOAuthToken(
bool has_request_token) {
em::DeviceManagementRequest dummy;
return IssueOAuthTokenAndCaptureRequest(has_request_token, &dummy);
}
// Issues the OAuth2 tokens,captures the request message, and returns the
// device management register job if the flow succeeded.
DeviceManagementService::JobForTesting IssueOAuthTokenAndCaptureRequest(
bool has_request_token,
em::DeviceManagementRequest* register_request) {
EXPECT_FALSE(manager_->core()->client()->is_registered());
// Issuing this token triggers the callback of the OAuth2PolicyFetcher,
// which triggers the registration request.
DeviceManagementService::JobForTesting job;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(
DoAll(device_management_service_.CaptureRequest(register_request),
SaveArg<0>(&job)));
if (!has_request_token) {
GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
network::URLLoaderCompletionStatus ok_completion_status(net::OK);
auto ok_response = network::CreateURLResponseHead(net::HTTP_OK);
// Issue the access token.
EXPECT_TRUE(
test_system_url_loader_factory_.SimulateResponseForPendingRequest(
gaia_urls->oauth2_token_url(), ok_completion_status,
std::move(ok_response), kOAuth2AccessTokenData));
} else {
// Since the refresh token is available, IdentityManager was used
// to request the access token and not UserCloudPolicyTokenForwarder.
// Issue the access token with the former.
signin::ScopeSet scopes;
scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
identity_test_env()
->WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
kOAuthToken,
base::Time::Now() + base::Seconds(3600) /*expiration*/,
std::string() /*id_token*/, scopes);
}
EXPECT_TRUE(job.IsActive());
EXPECT_FALSE(manager_->core()->client()->is_registered());
Mock::VerifyAndClearExpectations(&device_management_service_);
return job;
}
// Expects a policy fetch request to be issued after invoking |trigger_fetch|.
// This method replies to that fetch request and verifies that the manager
// handled the response.
void FetchPolicy(base::OnceClosure trigger_fetch, bool timeout) {
DeviceManagementService::JobForTesting job;
DeviceManagementService::JobConfiguration::JobType job_type;
DeviceManagementService::JobConfiguration::ParameterMap params;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type),
device_management_service_.CaptureQueryParams(¶ms),
SaveArg<0>(&job)));
std::move(trigger_fetch).Run();
ASSERT_TRUE(job.IsActive());
ASSERT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
job_type);
bool is_oauth_token_passed =
user_type_ == user_manager::UserType::kChild &&
base::FeatureList::IsEnabled(features::kDMServerOAuthForChildUser);
EXPECT_EQ(is_oauth_token_passed ? kOAuthToken : "",
params[dm_protocol::kParamOAuthToken]);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
Mock::VerifyAndClearExpectations(&device_management_service_);
if (timeout) {
manager_->ForceTimeoutForTest();
} else {
// Send the initial policy back. This completes the initialization flow.
EXPECT_CALL(*store_, Store(_));
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kSuccess, policy_blob_);
EXPECT_FALSE(job.IsActive());
Mock::VerifyAndClearExpectations(store_);
// Notifying that the store has cached the fetched policy completes the
// process, and initializes the manager.
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->policy_map_ = policy_map_.Clone();
store_->NotifyStoreLoaded();
}
EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(manager_->policies().Equals(expected_bundle_));
}
// Required by the refresh scheduler that's created by the manager and
// for the cleanup of URLRequestContextGetter in the |signin_profile_|.
content::BrowserTaskEnvironment task_environment_;
// Convenience policy objects.
em::PolicyData policy_data_;
em::DeviceManagementResponse register_blob_;
em::DeviceManagementResponse policy_blob_;
PolicyMap policy_map_;
PolicyBundle expected_bundle_;
// Policy infrastructure.
TestingPrefServiceSimple prefs_;
MockConfigurationPolicyObserver observer_;
testing::StrictMock<MockJobCreationHandler> job_creation_handler_;
FakeDeviceManagementService device_management_service_{
&job_creation_handler_};
raw_ptr<MockCloudPolicyStore, DanglingUntriaged> store_; // Not owned.
raw_ptr<MockCloudExternalDataManager, DanglingUntriaged>
external_data_manager_; // Not owned.
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
SchemaRegistry schema_registry_;
std::unique_ptr<UserCloudPolicyManagerAsh> manager_;
std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder_;
// Required by ProfileHelper to get the signin Profile context.
std::unique_ptr<TestingProfileManager> profile_manager_;
raw_ptr<TestingProfile> profile_;
raw_ptr<TestingProfile> signin_profile_;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_env_profile_adaptor_;
user_manager::UserType user_type_ = user_manager::UserType::kRegular;
raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_;
user_manager::ScopedUserManager user_manager_enabler_;
// This is automatically checked in TearDown() to ensure that we get a
// fatal error iff |fatal_error_expected_| is true.
bool fatal_error_expected_ = false;
void CreateManager(std::unique_ptr<MockCloudPolicyStore> store,
const base::TimeDelta& fetch_timeout,
PolicyEnforcement enforcement_type) {
store_ = store.get();
external_data_manager_ = new MockCloudExternalDataManager;
external_data_manager_->SetPolicyStore(store_);
const user_manager::User* active_user = user_manager_->GetActiveUser();
manager_ = std::make_unique<UserCloudPolicyManagerAsh>(
ash::ProfileHelper::Get()->GetProfileByUser(active_user),
std::move(store),
base::WrapUnique<MockCloudExternalDataManager>(
external_data_manager_.get()),
base::FilePath(), enforcement_type, &prefs_, fetch_timeout,
base::BindOnce(&UserCloudPolicyManagerAshTest::OnFatalErrorEncountered,
base::Unretained(this)),
active_user->GetAccountId(), task_runner_);
manager_->AddObserver(&observer_);
manager_->SetSignInURLLoaderFactoryForTests(
test_signin_shared_loader_factory_);
manager_->SetSystemURLLoaderFactoryForTests(
test_system_shared_loader_factory_);
manager_->SetUserContextRefreshTokenForTests("fake-user-context-rt");
}
void InitAndConnectManager() {
manager_->Init(&schema_registry_);
manager_->ConnectManagementService(&device_management_service_,
/*system_url_loader_factory=*/nullptr);
// Create the UserCloudPolicyTokenForwarder, which fetches the access
// token using the IdentityManager and forwards it to the
// UserCloudPolicyManagerAsh. This service is automatically created
// for regular Profiles but not for testing Profiles.
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile_);
ASSERT_TRUE(identity_manager);
token_forwarder_ = std::make_unique<UserCloudPolicyTokenForwarder>(
manager_.get(), identity_test_env()->identity_manager());
token_forwarder_->OverrideTimeForTesting(task_runner_->GetMockClock(),
task_runner_->GetMockTickClock(),
task_runner_);
}
network::TestURLLoaderFactory* test_signin_url_loader_factory() {
return &test_signin_url_loader_factory_;
}
network::TestURLLoaderFactory* test_system_url_loader_factory() {
return &test_system_url_loader_factory_;
}
signin::IdentityTestEnvironment* identity_test_env() {
return identity_test_env_profile_adaptor_->identity_test_env();
}
base::test::ScopedFeatureList* scoped_feature_list() {
return &scoped_feature_list_;
}
private:
// Invoked when a fatal error is encountered.
void OnFatalErrorEncountered() { fatal_error_encountered_ = true; }
bool fatal_error_encountered_ = false;
network::TestURLLoaderFactory test_signin_url_loader_factory_;
network::TestURLLoaderFactory test_system_url_loader_factory_;
scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
test_signin_shared_loader_factory_;
scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
test_system_shared_loader_factory_;
base::test::ScopedFeatureList scoped_feature_list_;
};
// TODO(agawronska): Remove test instantiation with kDMServerOAuthForChildUser
// once it is enabled by default.
INSTANTIATE_TEST_SUITE_P(
/* no prefix */,
UserCloudPolicyManagerAshTest,
testing::Values(std::vector<base::test::FeatureRef>(),
std::vector<base::test::FeatureRef>{
features::kDMServerOAuthForChildUser}));
TEST_P(UserCloudPolicyManagerAshTest, BlockingFirstFetch) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the policy cache is empty.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Reply with a valid registration response. This triggers the initial policy
// fetch.
FetchPolicy(base::BindOnce(&SendJobOKNowForBinding,
base::Unretained(&device_management_service_), job,
register_blob_),
false);
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingRefreshFetch) {
// Tests the initialization of a manager whose Profile is waiting for the
// refresh fetch, when a previously cached policy and DMToken already exist.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(1000), PolicyEnforcement::kPolicyRequired));
// Set the initially cached data and initialize the CloudPolicyService.
// The initial policy fetch is issued using the cached DMToken.
store_->set_policy_data_for_testing(
std::make_unique<em::PolicyData>(policy_data_));
FetchPolicy(base::BindOnce(&MockCloudPolicyStore::NotifyStoreLoaded,
base::Unretained(store_)),
false);
}
TEST_P(UserCloudPolicyManagerAshTest, SynchronousLoadWithEmptyStore) {
// Tests the initialization of a manager who requires policy, but who
// has no policy stored on disk. The manager should abort and exit the
// session.
fatal_error_expected_ = true;
std::unique_ptr<MockCloudPolicyStore> store =
std::make_unique<MockCloudPolicyStore>();
// Tell the store it couldn't load data.
store->NotifyStoreError();
CreateManager(std::move(store), base::TimeDelta(),
PolicyEnforcement::kPolicyRequired);
InitAndConnectManager();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingFetchStoreError) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the initial store load fails.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreError();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Reply with a valid registration response. This triggers the initial policy
// fetch.
FetchPolicy(base::BindOnce(&SendJobOKNowForBinding,
base::Unretained(&device_management_service_), job,
register_blob_),
false);
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingFetchOAuthError) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the OAuth2 token fetch fails. This should result in a
// fatal error.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
// The PolicyOAuth2TokenFetcher posts delayed retries on some errors. This
// data will make it fail immediately.
EXPECT_TRUE(
test_system_url_loader_factory()->SimulateResponseForPendingRequest(
GaiaUrls::GetInstance()->oauth2_token_url(),
network::URLLoaderCompletionStatus(net::OK),
network::CreateURLResponseHead(net::HTTP_BAD_REQUEST),
"Error=BadAuthentication"));
// Server check failed, so profile should not be initialized.
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
Mock::VerifyAndClearExpectations(&observer_);
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingFetchRegisterError) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the device management registration fails.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreError();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Now make it fail.
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get())).Times(0);
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kServiceUnavailable,
em::DeviceManagementResponse());
EXPECT_FALSE(job.IsActive());
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
Mock::VerifyAndClearExpectations(&observer_);
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingFetchPolicyFetchError) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the policy fetch request fails.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Reply with a valid registration response. This triggers the initial policy
// fetch.
DeviceManagementService::JobForTesting policy_job;
DeviceManagementService::JobConfiguration::JobType job_type;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type),
SaveArg<0>(&policy_job)));
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kSuccess, register_blob_);
EXPECT_FALSE(job.IsActive());
Mock::VerifyAndClearExpectations(&device_management_service_);
ASSERT_TRUE(policy_job.IsActive());
ASSERT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
job_type);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
// Make the policy fetch fail. The observer gets 2 notifications: one from the
// RefreshPolicies callback, and another from the OnClientError callback.
// A single notification suffices for this edge case, but this behavior is
// also correct and makes the implementation simpler.
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get())).Times(0);
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
device_management_service_.SendJobResponseNow(
&policy_job, net::OK, DeviceManagementService::kServiceUnavailable,
register_blob_);
EXPECT_FALSE(policy_job.IsActive());
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
}
TEST_P(UserCloudPolicyManagerAshTest,
NoCacheButPolicyExpectedRegistrationError) {
// Tests the case where we have no local policy and the policy fetch
// request fails, but we think we should have policy - this covers the
// situation where local policy cache is lost due to disk corruption and
// we can't access the server.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta::Max(), PolicyEnforcement::kPolicyRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Make the registration attempt fail.
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kServiceUnavailable,
register_blob_);
EXPECT_FALSE(job.IsActive());
Mock::VerifyAndClearExpectations(&device_management_service_);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
}
TEST_P(UserCloudPolicyManagerAshTest, NoCacheButPolicyExpectedFetchError) {
// Tests the case where we have no local policy and the policy fetch
// request fails, but we think we should have policy - this covers the
// situation where local policy cache is lost due to disk corruption and
// we can't access the server.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta::Max(), PolicyEnforcement::kPolicyRequired));
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Reply with a valid registration response. This triggers the initial policy
// fetch.
DeviceManagementService::JobForTesting policy_job;
DeviceManagementService::JobConfiguration::JobType job_type;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type),
SaveArg<0>(&policy_job)));
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kSuccess, register_blob_);
EXPECT_FALSE(job.IsActive());
Mock::VerifyAndClearExpectations(&device_management_service_);
ASSERT_TRUE(policy_job.IsActive());
ASSERT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
job_type);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
// Make the policy fetch fail. The observer gets 2 notifications: one from the
// RefreshPolicies callback, and another from the OnClientError callback.
// A single notification suffices for this edge case, but this behavior is
// also correct and makes the implementation simpler.
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
device_management_service_.SendJobResponseNow(
&policy_job, net::OK, DeviceManagementService::kServiceUnavailable,
em::DeviceManagementResponse());
EXPECT_FALSE(policy_job.IsActive());
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_TRUE(PolicyBundle().Equals(manager_->policies()));
}
TEST_P(UserCloudPolicyManagerAshTest, NonBlockingFirstFetch) {
// Tests the first policy fetch request by a Profile that isn't managed.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kPolicyOptional));
// Initialize the CloudPolicyService without any stored data. Since the
// manager is not waiting for the initial fetch, it will become initialized
// once the store is loaded.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->NotifyStoreLoaded();
Mock::VerifyAndClearExpectations(&observer_);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(manager_->core()->client()->is_registered());
AccountInfo account_info = identity_test_env()->MakePrimaryAccountAvailable(
kEmail, signin::ConsentLevel::kSignin);
EXPECT_TRUE(
identity_test_env()->identity_manager()->HasAccountWithRefreshToken(
account_info.account_id));
// That should have notified the manager, which now issues the request for the
// policy oauth token.
DeviceManagementService::JobForTesting job = IssueOAuthToken(true);
ASSERT_TRUE(job.IsActive());
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kSuccess, register_blob_);
EXPECT_FALSE(job.IsActive());
// The refresh scheduler takes care of the initial fetch for unmanaged users.
// Running the task runner issues the initial fetch.
FetchPolicy(
base::BindOnce(&base::TestMockTimeTaskRunner::RunUntilIdle, task_runner_),
false);
}
TEST_P(UserCloudPolicyManagerAshTest, BlockingRefreshFetchWithTimeout) {
// Tests the case where a profile has policy, but the refresh policy fetch
// fails (times out) - ensures that we don't mark the profile as initialized
// until after the timeout.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(1000), PolicyEnforcement::kPolicyRequired));
// Set the initially cached data and initialize the CloudPolicyService.
// The initial policy fetch is issued using the cached DMToken.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get()));
store_->set_policy_data_for_testing(
std::make_unique<em::PolicyData>(policy_data_));
store_->policy_map_ = policy_map_.Clone();
// Mock out the initial policy fetch and have it trigger a timeout.
FetchPolicy(base::BindOnce(&MockCloudPolicyStore::NotifyStoreLoaded,
base::Unretained(store_)),
true);
Mock::VerifyAndClearExpectations(&observer_);
}
TEST_P(UserCloudPolicyManagerAshTest, SynchronousLoadWithPreloadedStore) {
// Tests the initialization of a manager with non-blocking initial policy
// fetch, when a previously cached policy and DMToken are already loaded
// before the manager is constructed (this simulates synchronously
// initializing a profile during a crash restart). The manager gets
// initialized straight away after the construction.
MakeManagerWithPreloadedStore(base::TimeDelta());
InitAndConnectManager();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->policies().Equals(expected_bundle_));
}
TEST_P(UserCloudPolicyManagerAshTest, TestLifetimeReportingRegular) {
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(1000), PolicyEnforcement::kPolicyRequired));
store_->NotifyStoreLoaded();
em::DeviceManagementRequest register_request;
DeviceManagementService::JobForTesting job =
IssueOAuthTokenAndCaptureRequest(false, ®ister_request);
ASSERT_TRUE(job.IsActive());
Mock::VerifyAndClearExpectations(&device_management_service_);
ASSERT_TRUE(register_request.has_register_request());
ASSERT_TRUE(register_request.register_request().has_lifetime());
ASSERT_EQ(em::DeviceRegisterRequest::LIFETIME_INDEFINITE,
register_request.register_request().lifetime());
}
TEST_P(UserCloudPolicyManagerAshTest, TestLifetimeReportingEphemeralUser) {
user_manager_->set_current_user_ephemeral(true);
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(1000), PolicyEnforcement::kPolicyRequired));
store_->NotifyStoreLoaded();
em::DeviceManagementRequest register_request;
DeviceManagementService::JobForTesting job =
IssueOAuthTokenAndCaptureRequest(false, ®ister_request);
ASSERT_TRUE(job.IsActive());
Mock::VerifyAndClearExpectations(&device_management_service_);
ASSERT_TRUE(register_request.has_register_request());
ASSERT_TRUE(register_request.register_request().has_lifetime());
ASSERT_EQ(em::DeviceRegisterRequest::LIFETIME_EPHEMERAL_USER,
register_request.register_request().lifetime());
}
TEST_P(UserCloudPolicyManagerAshTest, TestHasAppInstallEventLogUploader) {
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kPolicyRequired));
EXPECT_TRUE(manager_->GetAppInstallEventLogUploader());
}
TEST_P(UserCloudPolicyManagerAshTest, TestReportSchedulerCreation) {
// Open policy and feature flag to enable report scheduler.
g_browser_process->local_state()->SetBoolean(
enterprise_reporting::kCloudReportingEnabled, true);
// Log in an user account, and set it as primary.
AccountId account_id = AccountId::FromUserEmailGaiaId(kEmail, kTestGaiaId);
user_manager_->LoginUser(account_id);
ASSERT_TRUE(user_manager_->GetPrimaryUser());
// Before UserCloudPolicyManagerAsh is initialized, report scheduler is
// not existing.
MakeManagerWithPreloadedStore(base::TimeDelta());
EXPECT_FALSE(manager_->core()->service());
EXPECT_FALSE(manager_->core()->client());
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// After UserCloudPolicyManagerAsh is initialized, report scheduler is
// created with valid |client_id| and |dm token|.
InitAndConnectManager();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
EXPECT_EQ(kDeviceId, manager_->core()->client()->client_id());
EXPECT_EQ(kDMToken, manager_->core()->client()->dm_token());
EXPECT_TRUE(manager_->GetReportSchedulerForTesting());
// Make sure the |report_scheduler| submit the request to DM Server.
EXPECT_TRUE(manager_->GetReportSchedulerForTesting()
->IsNextReportScheduledForTesting());
}
TEST_P(UserCloudPolicyManagerAshTest, TestReportSchedulerDelayedCreation) {
// Open policy and feature flag to enable report scheduler.
g_browser_process->local_state()->SetBoolean(
enterprise_reporting::kCloudReportingEnabled, true);
// To simulate an intermediate status in user session, log in an user account
// as primiary but set |profile_is_created_| as false.
AccountId account_id = AccountId::FromUserEmailGaiaId(kEmail, kTestGaiaId);
user_manager_->LoginUser(account_id, false /* set_profile_created_flag */);
ASSERT_TRUE(user_manager_->GetPrimaryUser());
ASSERT_FALSE(user_manager_->GetPrimaryUser()->is_profile_created());
// Before UserCloudPolicyManagerAsh is initialized, report scheduler is
// not existing.
MakeManagerWithPreloadedStore(base::TimeDelta());
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// After UserCloudPolicyManagerAsh is initialized, report scheduler is
// still not created because the profile of primary user hasn't been created.
session_manager::SessionManager session_manager;
InitAndConnectManager();
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// The notification has no effect if the primary use keep not created status.
session_manager.NotifyUserProfileLoaded(account_id);
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// The notification has no effect if the account id is another one.
AccountId account_id2 = AccountId::FromUserEmailGaiaId(kEmail2, kTestGaiaId2);
session_manager.NotifyUserProfileLoaded(account_id2);
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// After the profile of primary user is created successfully, the delegate
// will be notified to create report scheduler.
user_manager_->SimulateUserProfileLoad(account_id);
session_manager.NotifyUserProfileLoaded(account_id);
EXPECT_TRUE(manager_->GetReportSchedulerForTesting());
// Make sure the |report_scheduler| submit the request to DM Server.
EXPECT_TRUE(manager_->GetReportSchedulerForTesting()
->IsNextReportScheduledForTesting());
}
TEST_P(UserCloudPolicyManagerAshTest, TestSkipReportSchedulerCreation) {
// Open policy and feature flag to enable report scheduler.
g_browser_process->local_state()->SetBoolean(
enterprise_reporting::kCloudReportingEnabled, true);
// No primary user is specified.
ASSERT_FALSE(user_manager_->GetPrimaryUser());
// Before UserCloudPolicyManagerAsh is initialized, report scheduler is
// not existing.
MakeManagerWithPreloadedStore(base::TimeDelta());
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
// After UserCloudPolicyManagerAsh is initialized, report scheduler is
// still not existing because there is no valid primary user.
InitAndConnectManager();
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
}
TEST_P(UserCloudPolicyManagerAshTest, EnterpriseReportingInChromeOSDisabled) {
// Open policy but close the feature flag for Chrome OS to disable report
// scheduler.
g_browser_process->local_state()->SetBoolean(
enterprise_reporting::kCloudReportingEnabled, true);
// Report scheduler won't be created.
MakeManagerWithPreloadedStore(base::TimeDelta());
InitAndConnectManager();
EXPECT_FALSE(manager_->GetReportSchedulerForTesting());
}
TEST_P(UserCloudPolicyManagerAshTest, Reregistration) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the policy cache is empty.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
base::HistogramTester histogram_tester;
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting job = IssueOAuthToken(false);
ASSERT_TRUE(job.IsActive());
// Register.
DeviceManagementService::JobForTesting policy_job;
DeviceManagementService::JobConfiguration::JobType job_type;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type),
SaveArg<0>(&policy_job)));
device_management_service_.SendJobResponseNow(
&job, net::OK, DeviceManagementService::kSuccess, register_blob_);
EXPECT_FALSE(job.IsActive());
// Validate registered state.
ASSERT_TRUE(policy_job.IsActive());
ASSERT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
job_type);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
EXPECT_FALSE(user_manager_->GetActiveUser()->force_online_signin());
// Simulate policy fetch fail (error code 410), which should trigger the
// re-registration flow (FetchPolicyOAuthToken()).
DeviceManagementService::JobForTesting reregister_job;
em::DeviceManagementRequest register_request;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(
DoAll(device_management_service_.CaptureRequest(®ister_request),
SaveArg<0>(&reregister_job)));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get())).Times(0);
device_management_service_.SendJobResponseNow(
&policy_job, net::OK, DeviceManagementService::kDeviceNotFound,
em::DeviceManagementResponse());
EXPECT_FALSE(policy_job.IsActive());
histogram_tester.ExpectUniqueSample(kUMAReregistrationResult, 0, 1);
// Copy register request (used to check correct re-registration parameters are
// submitted).
// Simulate OAuth token fetch.
GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
network::URLLoaderCompletionStatus ok_completion_status(net::OK);
auto ok_response = network::CreateURLResponseHead(net::HTTP_OK);
EXPECT_TRUE(
test_system_url_loader_factory()->SimulateResponseForPendingRequest(
gaia_urls->oauth2_token_url(), ok_completion_status,
std::move(ok_response), kOAuth2AccessTokenData));
// Validate that re-registration sends the correct parameters.
EXPECT_TRUE(register_request.register_request().reregister());
EXPECT_EQ(kDMToken,
register_request.register_request().reregistration_dm_token());
// Validate re-registration state.
ASSERT_TRUE(reregister_job.IsActive());
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
EXPECT_FALSE(user_manager_->GetActiveUser()->force_online_signin());
// Validate successful re-registration.
policy_job.Deactivate();
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(SaveArg<0>(&policy_job));
device_management_service_.SendJobResponseNow(
&reregister_job, net::OK, DeviceManagementService::kSuccess,
register_blob_);
EXPECT_FALSE(reregister_job.IsActive());
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
EXPECT_FALSE(user_manager_->GetActiveUser()->force_online_signin());
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 0, 1);
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 1, 1);
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 2, 0);
histogram_tester.ExpectTotalCount(kUMAReregistrationResult, 2);
}
TEST_P(UserCloudPolicyManagerAshTest, ReregistrationFails) {
// Tests the initialization of a manager whose Profile is waiting for the
// initial fetch, when the policy cache is empty.
fatal_error_expected_ = true;
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::TimeDelta(), PolicyEnforcement::kServerCheckRequired));
base::HistogramTester histogram_tester;
// Initialize the CloudPolicyService without any stored data.
EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
// This starts the OAuth2 policy token fetcher using the signin Profile.
// The manager will then issue the registration request.
DeviceManagementService::JobForTesting register_job = IssueOAuthToken(false);
ASSERT_TRUE(register_job.IsActive());
// Register.
DeviceManagementService::JobForTesting policy_job;
DeviceManagementService::JobConfiguration::JobType job_type;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(DoAll(device_management_service_.CaptureJobType(&job_type),
SaveArg<0>(&policy_job)));
device_management_service_.SendJobResponseNow(
®ister_job, net::OK, DeviceManagementService::kSuccess,
register_blob_);
EXPECT_FALSE(register_job.IsActive());
// Validate registered state.
ASSERT_TRUE(policy_job.IsActive());
ASSERT_EQ(DeviceManagementService::JobConfiguration::TYPE_POLICY_FETCH,
job_type);
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_TRUE(manager_->core()->client()->is_registered());
EXPECT_FALSE(user_manager_->GetActiveUser()->force_online_signin());
// Simulate policy fetch fail (error code 410), which should trigger the
// re-registration flow (FetchPolicyOAuthToken()).
DeviceManagementService::JobForTesting reregister_job;
EXPECT_CALL(job_creation_handler_, OnJobCreation)
.WillOnce(SaveArg<0>(&reregister_job));
EXPECT_CALL(observer_, OnUpdatePolicy(manager_.get())).Times(0);
device_management_service_.SendJobResponseNow(
&policy_job, net::OK, DeviceManagementService::kDeviceNotFound,
em::DeviceManagementResponse());
EXPECT_FALSE(policy_job.IsActive());
histogram_tester.ExpectUniqueSample(kUMAReregistrationResult, 0, 1);
// Simulate OAuth token fetch.
GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
network::URLLoaderCompletionStatus ok_completion_status(net::OK);
auto ok_response = network::CreateURLResponseHead(net::HTTP_OK);
EXPECT_TRUE(
test_system_url_loader_factory()->SimulateResponseForPendingRequest(
gaia_urls->oauth2_token_url(), ok_completion_status,
std::move(ok_response), kOAuth2AccessTokenData));
// Validate re-registration state.
ASSERT_TRUE(reregister_job.IsActive());
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
EXPECT_FALSE(user_manager_->GetActiveUser()->force_online_signin());
// Validate unsuccessful re-registration.
device_management_service_.SendJobResponseNow(
&reregister_job, net::OK, DeviceManagementService::kServiceUnavailable,
register_blob_);
EXPECT_FALSE(reregister_job.IsActive());
EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
EXPECT_FALSE(manager_->core()->client()->is_registered());
EXPECT_TRUE(user_manager_->GetActiveUser()->force_online_signin());
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 0, 1);
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 1, 0);
histogram_tester.ExpectBucketCount(kUMAReregistrationResult, 2, 1);
histogram_tester.ExpectTotalCount(kUMAReregistrationResult, 2);
}
// Tests UserCloudPolicyManagerAsh for child user.
class UserCloudPolicyManagerAshChildTest
: public UserCloudPolicyManagerAshTest {
public:
UserCloudPolicyManagerAshChildTest(
const UserCloudPolicyManagerAshChildTest&) = delete;
UserCloudPolicyManagerAshChildTest& operator=(
const UserCloudPolicyManagerAshChildTest&) = delete;
// Issues OAuthToken for device management scopes.
void IssueOAuth2AccessToken(base::TimeDelta token_lifetime) {
signin::ScopeSet scopes;
scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
scopes.insert(GaiaConstants::kGoogleUserInfoEmail);
identity_test_env()
->WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
kOAuthToken, task_runner_->Now() + token_lifetime,
std::string() /*id_token*/, scopes);
}
protected:
UserCloudPolicyManagerAshChildTest() {
user_type_ = user_manager::UserType::kChild;
}
~UserCloudPolicyManagerAshChildTest() override = default;
// UserCloudPolicyManagerAshTest:
void SetUp() override {
UserCloudPolicyManagerAshTest::SetUp();
identity_test_env()->MakePrimaryAccountAvailable(
kEmail, signin::ConsentLevel::kSignin);
}
// Sets the initially cached data and initializes the CloudPolicyService.
void LoadStoreWithCachedData() {
store_->set_policy_data_for_testing(
std::make_unique<em::PolicyData>(policy_data_));
store_->policy_map_ = policy_map_.Clone();
store_->NotifyStoreLoaded();
EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
};
// TODO(agawronska): Remove test instantiation with kDMServerOAuthForChildUser
// once it is enabled by default.
INSTANTIATE_TEST_SUITE_P(
/* no prefix */,
UserCloudPolicyManagerAshChildTest,
testing::Values(std::vector<base::test::FeatureRef>{
features::kDMServerOAuthForChildUser}));
TEST_P(UserCloudPolicyManagerAshChildTest, RefreshFetchDoesNotBlock) {
// Tests the profile initialization is not blocked on policy refresh.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(0), PolicyEnforcement::kPolicyRequired));
EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
LoadStoreWithCachedData();
EXPECT_TRUE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
}
TEST_P(UserCloudPolicyManagerAshChildTest, RefreshSchedulerStart) {
// Tests that refresh scheduler is started after OAuth token is available.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(0), PolicyEnforcement::kPolicyRequired));
LoadStoreWithCachedData();
EXPECT_FALSE(manager_->core()->refresh_scheduler());
IssueOAuth2AccessToken(base::Seconds(3600));
EXPECT_TRUE(manager_->core()->refresh_scheduler());
}
TEST_P(UserCloudPolicyManagerAshChildTest, RefreshScheduler) {
// Tests that refresh schedule isn't affected by periodic OAuth token updates.
ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(
base::Seconds(0), PolicyEnforcement::kPolicyRequired));
LoadStoreWithCachedData();
// This starts refresh scheduler.
const base::TimeDelta token_lifetime = base::Minutes(50);
IssueOAuth2AccessToken(token_lifetime);
// First refresh is scheduled with delay of 0s - let it execute.
FetchPolicy(
base::BindOnce(&base::TestMockTimeTaskRunner::RunUntilIdle, task_runner_),
false);
// Assert that the initial delay (right now 3h) is at least |iterations| times
// longer than token lifetime. If default delay changes and is lesser the rest
// of the test will work incorrectly and should be updated.
const int iterations = 3;
base::TimeDelta refresh_delay = base::Milliseconds(
manager_->core()->refresh_scheduler()->GetActualRefreshDelay() +
manager_->core()->refresh_scheduler()->GetSaltDelayForTesting());
ASSERT_GT(refresh_delay, iterations * token_lifetime);
// Advancing the clock will trigger delivery of new tokens. It should not
// trigger policy refresh nor affect scheduled refresh.
for (int i = 0; i < iterations; ++i) {
task_runner_->FastForwardBy(token_lifetime);
refresh_delay -= token_lifetime;
IssueOAuth2AccessToken(token_lifetime);
}
// Advance the clock by the remaining time to get scheduled policy refresh.
FetchPolicy(base::BindOnce(&base::TestMockTimeTaskRunner::FastForwardBy,
task_runner_, refresh_delay),
false);
}
} // namespace policy