blob: 7a10dc361f183a0d402c6cd68496542d130b9986 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/policy/machine_level_user_cloud_policy_controller.h"
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/browser_dm_token_storage.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h"
#include "chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h"
#include "chrome/common/chrome_paths.h"
#include "components/policy/core/common/cloud/cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_metrics.h"
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#if defined(OS_WIN)
#include "chrome/install_static/install_util.h"
#endif
namespace policy {
namespace {
void RecordEnrollmentResult(
MachineLevelUserCloudPolicyEnrollmentResult result) {
UMA_HISTOGRAM_ENUMERATION(
"Enterprise.MachineLevelUserCloudPolicyEnrollment.Result", result);
}
} // namespace
const base::FilePath::CharType
MachineLevelUserCloudPolicyController::kPolicyDir[] =
FILE_PATH_LITERAL("Policy");
MachineLevelUserCloudPolicyController::MachineLevelUserCloudPolicyController() {
}
MachineLevelUserCloudPolicyController::
~MachineLevelUserCloudPolicyController() {}
// static
std::unique_ptr<MachineLevelUserCloudPolicyManager>
MachineLevelUserCloudPolicyController::CreatePolicyManager() {
std::string enrollment_token =
BrowserDMTokenStorage::Get()->RetrieveEnrollmentToken();
std::string dm_token = BrowserDMTokenStorage::Get()->RetrieveDMToken();
std::string client_id = BrowserDMTokenStorage::Get()->RetrieveClientId();
if (enrollment_token.empty() && dm_token.empty())
return nullptr;
base::FilePath user_data_dir;
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
return nullptr;
DVLOG(1) << "Creating machine level cloud policy manager";
base::FilePath policy_dir =
user_data_dir.Append(MachineLevelUserCloudPolicyController::kPolicyDir);
std::unique_ptr<MachineLevelUserCloudPolicyStore> policy_store =
MachineLevelUserCloudPolicyStore::Create(
dm_token, client_id, policy_dir,
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND}));
return std::make_unique<MachineLevelUserCloudPolicyManager>(
std::move(policy_store), nullptr, policy_dir,
base::ThreadTaskRunnerHandle::Get(),
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::IO));
}
void MachineLevelUserCloudPolicyController::Init(
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> request_context) {
MachineLevelUserCloudPolicyManager* policy_manager =
g_browser_process->browser_policy_connector()
->machine_level_user_cloud_policy_manager();
DeviceManagementService* device_management_service =
g_browser_process->browser_policy_connector()
->device_management_service();
if (!policy_manager)
return;
// If there exists an enrollment token, then there are two states:
// 1/ There also exists a DM token. This machine is already registeted, so
// the next step is to fetch policies.
// 2/ There is no DM token. In this case the machine is not already
// registered and needs to request a DM token.
std::string enrollment_token;
std::string client_id;
if (!GetEnrollmentTokenAndClientId(&enrollment_token, &client_id))
return;
DCHECK(!enrollment_token.empty());
DCHECK(!client_id.empty());
DVLOG(1) << "Enrollment token = " << enrollment_token;
DVLOG(1) << "Client ID = " << client_id;
policy_registrar_ = std::make_unique<MachineLevelUserCloudPolicyRegistrar>(
device_management_service, request_context);
policy_fetcher_ = std::make_unique<MachineLevelUserCloudPolicyFetcher>(
policy_manager, local_state, device_management_service, request_context);
policy_register_watcher_ =
std::make_unique<MachineLevelUserCloudPolicyRegisterWatcher>(this);
std::string dm_token = BrowserDMTokenStorage::Get()->RetrieveDMToken();
DVLOG(1) << "DM token = " << (dm_token.empty() ? "none" : "from persistence");
if (dm_token.empty()) {
// Not registered already, so do it now.
policy_registrar_->RegisterForPolicyWithEnrollmentToken(
enrollment_token, client_id,
base::Bind(&MachineLevelUserCloudPolicyController::
RegisterForPolicyWithEnrollmentTokenCallback,
base::Unretained(this)));
#if defined(OS_WIN)
// This metric is only published on Windows to indicate how many user level
// install Chrome try to enroll the policy which can't store the DM token
// in the Registry in the end of enrollment. Mac and Linux does not need
// this metric for now as they might use different token storage mechanism
// in the future.
UMA_HISTOGRAM_BOOLEAN(
"Enterprise.MachineLevelUserCloudPolicyEnrollment.InstallLevel_Win",
install_static::IsSystemInstall());
#endif
}
}
MachineLevelUserCloudPolicyController::RegisterResult
MachineLevelUserCloudPolicyController::WaitUntilPolicyEnrollmentFinished() {
if (policy_register_watcher_) {
return policy_register_watcher_->WaitUntilCloudPolicyEnrollmentFinished();
}
return RegisterResult::kNoEnrollmentNeeded;
}
void MachineLevelUserCloudPolicyController::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void MachineLevelUserCloudPolicyController::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void MachineLevelUserCloudPolicyController::NotifyPolicyRegisterFinished(
bool succeeded) {
for (auto& observer : observers_) {
observer.OnPolicyRegisterFinished(succeeded);
}
}
bool MachineLevelUserCloudPolicyController::GetEnrollmentTokenAndClientId(
std::string* enrollment_token,
std::string* client_id) {
*client_id = BrowserDMTokenStorage::Get()->RetrieveClientId();
if (client_id->empty())
return false;
*enrollment_token = BrowserDMTokenStorage::Get()->RetrieveEnrollmentToken();
return !enrollment_token->empty();
}
void MachineLevelUserCloudPolicyController::
RegisterForPolicyWithEnrollmentTokenCallback(const std::string& dm_token,
const std::string& client_id) {
if (dm_token.empty()) {
DVLOG(1) << "No DM token returned from browser registration";
RecordEnrollmentResult(
MachineLevelUserCloudPolicyEnrollmentResult::kFailedToFetch);
NotifyPolicyRegisterFinished(false);
return;
}
DVLOG(1) << "DM token = retrieved from server";
// TODO(alito): Log failures to store the DM token. Should we try again later?
BrowserDMTokenStorage::Get()->StoreDMToken(
dm_token, base::BindOnce([](bool success) {
if (!success) {
DVLOG(1) << "Failed to store the DM token";
RecordEnrollmentResult(
MachineLevelUserCloudPolicyEnrollmentResult::kFailedToStore);
} else {
DVLOG(1) << "Successfully stored the DM token";
RecordEnrollmentResult(
MachineLevelUserCloudPolicyEnrollmentResult::kSuccess);
}
}));
// Start fetching policies.
policy_fetcher_->SetupRegistrationAndFetchPolicy(dm_token, client_id);
NotifyPolicyRegisterFinished(true);
}
} // namespace policy