blob: 9d0d75bdd3dfc53b5fc31b177a3ba6ff7da83a8e [file] [log] [blame]
// Copyright 2014 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/chromeos/policy/consumer_management_service.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/pref_names.h"
#include "chromeos/dbus/cryptohome/rpc.pb.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "policy/proto/device_management_backend.pb.h"
namespace em = enterprise_management;
namespace {
// Boot atttributes ID.
const char kAttributeOwnerId[] = "consumer_management.owner_id";
// The string of Status enum.
const char* kStatusString[] = {
"StatusUnknown",
"StatusEnrolled",
"StatusEnrolling",
"StatusUnenrolled",
"StatusUnenrolling",
};
COMPILE_ASSERT(
arraysize(kStatusString) == policy::ConsumerManagementService::STATUS_LAST,
"invalid kStatusString array size.");
} // namespace
namespace policy {
ConsumerManagementService::ConsumerManagementService(
chromeos::CryptohomeClient* client,
chromeos::DeviceSettingsService* device_settings_service)
: client_(client),
device_settings_service_(device_settings_service),
weak_ptr_factory_(this) {
// A NULL value may be passed in tests.
if (device_settings_service_)
device_settings_service_->AddObserver(this);
}
ConsumerManagementService::~ConsumerManagementService() {
if (device_settings_service_)
device_settings_service_->RemoveObserver(this);
}
// static
void ConsumerManagementService::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
prefs::kConsumerManagementEnrollmentStage, ENROLLMENT_STAGE_NONE);
}
void ConsumerManagementService::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void ConsumerManagementService::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
ConsumerManagementService::Status
ConsumerManagementService::GetStatus() const {
if (!device_settings_service_)
return STATUS_UNKNOWN;
const em::PolicyData* policy_data = device_settings_service_->policy_data();
if (!policy_data)
return STATUS_UNKNOWN;
if (policy_data->management_mode() == em::PolicyData::CONSUMER_MANAGED) {
// TODO(davidyu): Check if unenrollment is in progress.
// http://crbug.com/353050.
return STATUS_ENROLLED;
}
EnrollmentStage stage = GetEnrollmentStage();
if (stage > ENROLLMENT_STAGE_NONE && stage < ENROLLMENT_STAGE_SUCCESS)
return STATUS_ENROLLING;
return STATUS_UNENROLLED;
}
std::string ConsumerManagementService::GetStatusString() const {
return kStatusString[GetStatus()];
}
bool ConsumerManagementService::HasPendingEnrollmentNotification() const {
EnrollmentStage stage = GetEnrollmentStage();
return stage >= ENROLLMENT_STAGE_SUCCESS && stage < ENROLLMENT_STAGE_LAST;
}
ConsumerManagementService::EnrollmentStage
ConsumerManagementService::GetEnrollmentStage() const {
const PrefService* prefs = g_browser_process->local_state();
int stage = prefs->GetInteger(prefs::kConsumerManagementEnrollmentStage);
if (stage < 0 || stage >= ENROLLMENT_STAGE_LAST) {
LOG(ERROR) << "Unknown enrollment stage: " << stage;
stage = 0;
}
return static_cast<EnrollmentStage>(stage);
}
void ConsumerManagementService::SetEnrollmentStage(EnrollmentStage stage) {
PrefService* prefs = g_browser_process->local_state();
prefs->SetInteger(prefs::kConsumerManagementEnrollmentStage, stage);
NotifyStatusChanged();
}
void ConsumerManagementService::GetOwner(const GetOwnerCallback& callback) {
cryptohome::GetBootAttributeRequest request;
request.set_name(kAttributeOwnerId);
client_->GetBootAttribute(
request,
base::Bind(&ConsumerManagementService::OnGetBootAttributeDone,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void ConsumerManagementService::SetOwner(const std::string& user_id,
const SetOwnerCallback& callback) {
cryptohome::SetBootAttributeRequest request;
request.set_name(kAttributeOwnerId);
request.set_value(user_id.data(), user_id.size());
client_->SetBootAttribute(
request,
base::Bind(&ConsumerManagementService::OnSetBootAttributeDone,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void ConsumerManagementService::OwnershipStatusChanged() {
}
void ConsumerManagementService::DeviceSettingsUpdated() {
NotifyStatusChanged();
}
void ConsumerManagementService::OnDeviceSettingsServiceShutdown() {
device_settings_service_ = nullptr;
}
void ConsumerManagementService::OnGetBootAttributeDone(
const GetOwnerCallback& callback,
chromeos::DBusMethodCallStatus call_status,
bool dbus_success,
const cryptohome::BaseReply& reply) {
if (!dbus_success || reply.error() != 0) {
LOG(ERROR) << "Failed to get the owner info from boot lockbox.";
callback.Run("");
return;
}
callback.Run(
reply.GetExtension(cryptohome::GetBootAttributeReply::reply).value());
}
void ConsumerManagementService::OnSetBootAttributeDone(
const SetOwnerCallback& callback,
chromeos::DBusMethodCallStatus call_status,
bool dbus_success,
const cryptohome::BaseReply& reply) {
if (!dbus_success || reply.error() != 0) {
LOG(ERROR) << "Failed to set owner info in boot lockbox.";
callback.Run(false);
return;
}
cryptohome::FlushAndSignBootAttributesRequest request;
client_->FlushAndSignBootAttributes(
request,
base::Bind(&ConsumerManagementService::OnFlushAndSignBootAttributesDone,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void ConsumerManagementService::OnFlushAndSignBootAttributesDone(
const SetOwnerCallback& callback,
chromeos::DBusMethodCallStatus call_status,
bool dbus_success,
const cryptohome::BaseReply& reply) {
if (!dbus_success || reply.error() != 0) {
LOG(ERROR) << "Failed to flush and sign boot lockbox.";
callback.Run(false);
return;
}
callback.Run(true);
}
void ConsumerManagementService::NotifyStatusChanged() {
FOR_EACH_OBSERVER(Observer, observers_, OnConsumerManagementStatusChanged());
}
} // namespace policy