summaryrefslogtreecommitdiffstats
path: root/chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc')
-rw-r--r--chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc350
1 files changed, 350 insertions, 0 deletions
diff --git a/chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc b/chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc
new file mode 100644
index 00000000000..219f5b61aaf
--- /dev/null
+++ b/chromium/components/policy/core/browser/cloud/user_policy_signin_service_base.cc
@@ -0,0 +1,350 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/policy/core/browser/cloud/user_policy_signin_service_base.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/dcheck_is_on.h"
+#include "base/location.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h"
+#include "components/policy/core/common/cloud/device_management_service.h"
+#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace em = enterprise_management;
+
+namespace {
+
+#if BUILDFLAG(IS_ANDROID)
+const em::DeviceRegisterRequest::Type kCloudPolicyRegistrationType =
+ em::DeviceRegisterRequest::ANDROID_BROWSER;
+#elif BUILDFLAG(IS_IOS)
+// TODO(crbug.com/1312263): Use em::DeviceRegisterRequest::IOS_BROWSER when
+// supported in the dmserver. The type for Desktop is temporarily used on iOS
+// to allow early testing of the feature before the DMServer can support iOS
+// User Policy.
+const em::DeviceRegisterRequest::Type kCloudPolicyRegistrationType =
+ em::DeviceRegisterRequest::BROWSER;
+#else
+const em::DeviceRegisterRequest::Type kCloudPolicyRegistrationType =
+ em::DeviceRegisterRequest::BROWSER;
+#endif
+
+} // namespace
+
+namespace policy {
+
+UserPolicySigninServiceBase::UserPolicySigninServiceBase(
+ PrefService* local_state,
+ DeviceManagementService* device_management_service,
+ UserCloudPolicyManager* policy_manager,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory)
+ : policy_manager_(policy_manager),
+ identity_manager_(identity_manager),
+ local_state_(local_state),
+ device_management_service_(device_management_service),
+ system_url_loader_factory_(system_url_loader_factory) {}
+
+UserPolicySigninServiceBase::~UserPolicySigninServiceBase() {}
+
+void UserPolicySigninServiceBase::FetchPolicyForSignedInUser(
+ const AccountId& account_id,
+ const std::string& dm_token,
+ const std::string& client_id,
+ scoped_refptr<network::SharedURLLoaderFactory> profile_url_loader_factory,
+ PolicyFetchCallback callback) {
+ UserCloudPolicyManager* manager = policy_manager();
+ DCHECK(manager);
+
+ // Initialize the cloud policy manager there was no prior initialization.
+ if (!manager->core()->client()) {
+ std::unique_ptr<CloudPolicyClient> client =
+ UserCloudPolicyManager::CreateCloudPolicyClient(
+ device_management_service_, profile_url_loader_factory);
+ client->SetupRegistration(
+ dm_token, client_id,
+ std::vector<std::string>() /* user_affiliation_ids */);
+ DCHECK(client->is_registered());
+ DCHECK(!manager->core()->client());
+ InitializeUserCloudPolicyManager(account_id, std::move(client));
+ }
+
+ DCHECK(manager->IsClientRegistered());
+
+ // Now initiate a policy fetch.
+ manager->core()->service()->RefreshPolicy(std::move(callback));
+}
+
+void UserPolicySigninServiceBase::OnPolicyFetched(CloudPolicyClient* client) {}
+
+void UserPolicySigninServiceBase::OnRegistrationStateChanged(
+ CloudPolicyClient* client) {}
+
+void UserPolicySigninServiceBase::OnClientError(CloudPolicyClient* client) {
+ if (client->is_registered()) {
+ // If the client is already registered, it means this error must have
+ // come from a policy fetch.
+ if (client->status() == DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED) {
+ // OK, policy fetch failed with MANAGEMENT_NOT_SUPPORTED - this is our
+ // trigger to revert to "unmanaged" mode (we will check for management
+ // being re-enabled on the next restart and/or login).
+ DVLOG(1) << "DMServer returned NOT_SUPPORTED error - removing policy";
+
+ // Can't shutdown now because we're in the middle of a callback from
+ // the CloudPolicyClient, so queue up a task to do the shutdown.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ DVLOG(1) << "Error fetching policy: " << client->status();
+ }
+ }
+}
+
+void UserPolicySigninServiceBase::Shutdown() {
+ PrepareForUserCloudPolicyManagerShutdown();
+}
+
+void UserPolicySigninServiceBase::PrepareForUserCloudPolicyManagerShutdown() {
+ registration_helper_.reset();
+ UserCloudPolicyManager* manager = policy_manager();
+ if (manager && manager->core()->client())
+ manager->core()->client()->RemoveObserver(this);
+ if (manager && manager->core()->service())
+ manager->core()->service()->RemoveObserver(this);
+}
+
+std::unique_ptr<CloudPolicyClient>
+UserPolicySigninServiceBase::CreateClientForRegistrationOnly(
+ const std::string& username) {
+ DCHECK(!username.empty());
+ // We should not be called with a client already initialized.
+ DCHECK(!policy_manager() || !policy_manager()->core()->client());
+
+ // If the user should not get policy, just bail out.
+ if (!policy_manager() || !ShouldLoadPolicyForUser(username)) {
+ DVLOG(1) << "Signed in user is not in the allowlist";
+ return nullptr;
+ }
+
+ // If the DeviceManagementService is not yet initialized, start it up now.
+ device_management_service_->ScheduleInitialization(0);
+
+ // Create a new CloudPolicyClient for fetching the DMToken.
+ return UserCloudPolicyManager::CreateCloudPolicyClient(
+ device_management_service_, system_url_loader_factory_);
+}
+
+bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
+ const std::string& username) {
+ if (username.empty())
+ return false; // Not signed in.
+
+ return !BrowserPolicyConnector::IsNonEnterpriseUser(username);
+}
+
+void UserPolicySigninServiceBase::InitializeForSignedInUser(
+ const AccountId& account_id,
+ scoped_refptr<network::SharedURLLoaderFactory> profile_url_loader_factory) {
+ DCHECK(account_id.is_valid());
+ UserCloudPolicyManager* manager = policy_manager();
+ if (!ShouldLoadPolicyForUser(account_id.GetUserEmail())) {
+ manager->SetPoliciesRequired(false);
+ DVLOG(1) << "Policy load not enabled for user: "
+ << account_id.GetUserEmail();
+ return;
+ }
+
+ // Initialize the UCPM if it is not already initialized.
+ if (!manager->core()->service()) {
+ // If there is no cached DMToken then we can detect this when the
+ // OnCloudPolicyServiceInitializationCompleted() callback is invoked and
+ // this will initiate a policy fetch.
+ InitializeUserCloudPolicyManager(
+ account_id,
+ UserCloudPolicyManager::CreateCloudPolicyClient(
+ device_management_service_, profile_url_loader_factory));
+ } else {
+ manager->SetSigninAccountId(account_id);
+ }
+
+ // If the CloudPolicyService is initialized, kick off registration.
+ // Otherwise OnCloudPolicyServiceInitializationCompleted is invoked as soon as
+ // the service finishes its initialization.
+ if (manager->core()->service()->IsInitializationComplete())
+ OnCloudPolicyServiceInitializationCompleted();
+}
+
+void UserPolicySigninServiceBase::InitializeUserCloudPolicyManager(
+ const AccountId& account_id,
+ std::unique_ptr<CloudPolicyClient> client) {
+ DCHECK(client);
+ UserCloudPolicyManager* manager = policy_manager();
+ manager->SetSigninAccountId(account_id);
+ DCHECK(!manager->core()->client());
+ manager->Connect(local_state_, std::move(client));
+ DCHECK(manager->core()->service());
+
+ // Observe the client to detect errors fetching policy.
+ manager->core()->client()->AddObserver(this);
+ // Observe the service to determine when it's initialized.
+ manager->core()->service()->AddObserver(this);
+}
+
+void UserPolicySigninServiceBase::ShutdownUserCloudPolicyManager() {
+ PrepareForUserCloudPolicyManagerShutdown();
+ UserCloudPolicyManager* manager = policy_manager();
+ if (manager)
+ manager->DisconnectAndRemovePolicy();
+}
+
+void UserPolicySigninServiceBase::CancelPendingRegistration() {
+ weak_factory_for_registration_.InvalidateWeakPtrs();
+ registration_helper_.reset();
+}
+
+void UserPolicySigninServiceBase::CallPolicyRegistrationCallback(
+ std::unique_ptr<CloudPolicyClient> client,
+ PolicyRegistrationCallback callback) {
+ registration_helper_.reset();
+ std::move(callback).Run(client->dm_token(), client->client_id());
+}
+
+void UserPolicySigninServiceBase::RegisterForPolicyWithAccountId(
+ const std::string& username,
+ const CoreAccountId& account_id,
+ PolicyRegistrationCallback callback) {
+ DCHECK(!account_id.empty());
+
+ if (policy_manager() && policy_manager()->IsClientRegistered()) {
+ // Reuse the already fetched DM token if the client of the manager is
+ // already registered.
+ std::move(callback).Run(policy_manager()->core()->client()->dm_token(),
+ policy_manager()->core()->client()->client_id());
+ return;
+ }
+
+ // Create a new CloudPolicyClient for fetching the DMToken. This is a
+ // different client from the one used by the manager.
+ std::unique_ptr<CloudPolicyClient> policy_client =
+ CreateClientForRegistrationOnly(username);
+ if (!policy_client) {
+ std::move(callback).Run(std::string(), std::string());
+ return;
+ }
+
+ CancelPendingRegistration();
+
+ // Fire off the registration process. Callback owns and keeps the
+ // CloudPolicyClient alive for the length of the registration process.
+ registration_helper_ = std::make_unique<CloudPolicyClientRegistrationHelper>(
+ policy_client.get(), kCloudPolicyRegistrationType);
+
+ // Using a raw pointer to |this| is okay, because the service owns
+ // |registration_helper_|.
+ auto registration_callback = base::BindOnce(
+ &UserPolicySigninServiceBase::CallPolicyRegistrationCallback,
+ base::Unretained(this), std::move(policy_client), std::move(callback));
+ registration_helper_->StartRegistration(identity_manager(), account_id,
+ std::move(registration_callback));
+}
+
+void UserPolicySigninServiceBase::RegisterCloudPolicyService() {
+ DCHECK(
+ identity_manager()->HasPrimaryAccount(GetConsentLevelForRegistration()));
+ DCHECK(policy_manager()->core()->client());
+ DCHECK(!policy_manager()->IsClientRegistered());
+
+ DVLOG(1) << "Fetching new DM Token";
+
+ // Do nothing if already starting the registration process in which case there
+ // will be an instance of |registration_helper_|.
+ if (registration_helper_)
+ return;
+
+ UpdateLastPolicyCheckTime();
+
+ // Start the process of registering the CloudPolicyClient. Once it completes,
+ // policy fetch will automatically happen.
+ registration_helper_ = std::make_unique<CloudPolicyClientRegistrationHelper>(
+ policy_manager()->core()->client(), kCloudPolicyRegistrationType);
+ registration_helper_->StartRegistration(
+ identity_manager(),
+ identity_manager()->GetPrimaryAccountId(GetConsentLevelForRegistration()),
+ base::BindOnce(&UserPolicySigninServiceBase::OnRegistrationComplete,
+ base::Unretained(this)));
+}
+
+void UserPolicySigninServiceBase::OnRegistrationComplete() {
+ ProhibitSignoutIfNeeded();
+ registration_helper_.reset();
+}
+
+base::TimeDelta UserPolicySigninServiceBase::GetTryRegistrationDelay() {
+ return base::TimeDelta();
+}
+
+void UserPolicySigninServiceBase::
+ OnCloudPolicyServiceInitializationCompleted() {
+ UserCloudPolicyManager* manager = policy_manager();
+ DCHECK(manager->core()->service()->IsInitializationComplete());
+ // The service is now initialized - if the client is not yet registered, then
+ // it means that there is no cached policy and so we need to initiate a new
+ // client registration.
+ if (manager->IsClientRegistered()) {
+ DVLOG(1) << "Client already registered - not fetching DMToken";
+ ProhibitSignoutIfNeeded();
+ return;
+ }
+
+ if (!CanApplyPolicies(/*check_for_refresh_token=*/true)) {
+ // No token yet. This can only happen on Desktop platforms which should
+ // listen to OnRefreshTokenUpdatedForAccount() and will re-attempt
+ // registration once the token is available.
+ DLOG(WARNING) << "No OAuth Refresh Token - delaying policy download";
+ return;
+ }
+
+ base::TimeDelta try_registration_delay = GetTryRegistrationDelay();
+ if (try_registration_delay.is_zero()) {
+ // If the try registration delay is 0, register the cloud policy service
+ // immediately without queueing a task. This is the case for Desktop.
+ RegisterCloudPolicyService();
+ } else {
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&UserPolicySigninServiceBase::RegisterCloudPolicyService,
+ weak_factory_for_registration_.GetWeakPtr()),
+ try_registration_delay);
+ }
+
+ ProhibitSignoutIfNeeded();
+}
+
+void UserPolicySigninServiceBase::ProhibitSignoutIfNeeded() {}
+
+bool UserPolicySigninServiceBase::CanApplyPolicies(
+ bool check_for_refresh_token) {
+ return false;
+}
+
+void UserPolicySigninServiceBase::UpdateLastPolicyCheckTime() {}
+
+signin::ConsentLevel
+UserPolicySigninServiceBase::GetConsentLevelForRegistration() {
+ return signin::ConsentLevel::kSignin;
+}
+
+} // namespace policy