blob: 553d5cf7077bbf5a85842aea0691389ddf1f3d3e [file] [log] [blame]
// Copyright (c) 2012 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/device_local_account_policy_store.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/values.h"
#include "chrome/browser/policy/cloud/device_management_service.h"
#include "chrome/browser/policy/external_data_fetcher.h"
#include "chrome/browser/policy/policy_types.h"
#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
#include "chromeos/dbus/power_policy_controller.h"
#include "chromeos/dbus/session_manager_client.h"
#include "policy/policy_constants.h"
#include "policy/proto/cloud_policy.pb.h"
namespace em = enterprise_management;
namespace policy {
DeviceLocalAccountPolicyStore::DeviceLocalAccountPolicyStore(
const std::string& account_id,
chromeos::SessionManagerClient* session_manager_client,
chromeos::DeviceSettingsService* device_settings_service,
scoped_refptr<base::SequencedTaskRunner> background_task_runner)
: UserCloudPolicyStoreBase(background_task_runner),
account_id_(account_id),
session_manager_client_(session_manager_client),
device_settings_service_(device_settings_service),
weak_factory_(this) {}
DeviceLocalAccountPolicyStore::~DeviceLocalAccountPolicyStore() {}
void DeviceLocalAccountPolicyStore::Load() {
weak_factory_.InvalidateWeakPtrs();
session_manager_client_->RetrieveDeviceLocalAccountPolicy(
account_id_,
base::Bind(&DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob,
weak_factory_.GetWeakPtr()));
}
void DeviceLocalAccountPolicyStore::Store(
const em::PolicyFetchResponse& policy) {
weak_factory_.InvalidateWeakPtrs();
CheckKeyAndValidate(
make_scoped_ptr(new em::PolicyFetchResponse(policy)),
base::Bind(&DeviceLocalAccountPolicyStore::StoreValidatedPolicy,
weak_factory_.GetWeakPtr()));
}
void DeviceLocalAccountPolicyStore::ValidateLoadedPolicyBlob(
const std::string& policy_blob) {
if (policy_blob.empty()) {
status_ = CloudPolicyStore::STATUS_LOAD_ERROR;
NotifyStoreError();
} else {
scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
if (policy->ParseFromString(policy_blob)) {
CheckKeyAndValidate(
policy.Pass(),
base::Bind(&DeviceLocalAccountPolicyStore::UpdatePolicy,
weak_factory_.GetWeakPtr()));
} else {
status_ = CloudPolicyStore::STATUS_PARSE_ERROR;
NotifyStoreError();
}
}
}
void DeviceLocalAccountPolicyStore::UpdatePolicy(
UserCloudPolicyValidator* validator) {
validation_status_ = validator->status();
if (!validator->success()) {
status_ = STATUS_VALIDATION_ERROR;
NotifyStoreError();
return;
}
InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
// Exit the session when the lid is closed. The default behavior is to
// suspend while leaving the session running, which is not desirable for
// public sessions.
policy_map_.Set(key::kLidCloseAction,
POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER,
base::Value::CreateIntegerValue(
chromeos::PowerPolicyController::ACTION_STOP_SESSION),
NULL);
// Force the |ShelfAutoHideBehavior| policy to |Never|, ensuring that the ash
// shelf does not auto-hide.
policy_map_.Set(key::kShelfAutoHideBehavior,
POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER,
Value::CreateStringValue("Never"),
NULL);
// Force the |ShowLogoutButtonInTray| policy to |true|, ensuring that a big,
// red logout button is shown in the ash system tray.
policy_map_.Set(key::kShowLogoutButtonInTray,
POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER,
Value::CreateBooleanValue(true),
NULL);
// Force the |FullscreenAllowed| policy to |false|, ensuring that the ash
// shelf cannot be hidden by entering fullscreen mode.
policy_map_.Set(key::kFullscreenAllowed,
POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER,
Value::CreateBooleanValue(false),
NULL);
status_ = STATUS_OK;
NotifyStoreLoaded();
}
void DeviceLocalAccountPolicyStore::StoreValidatedPolicy(
UserCloudPolicyValidator* validator) {
if (!validator->success()) {
status_ = CloudPolicyStore::STATUS_VALIDATION_ERROR;
validation_status_ = validator->status();
NotifyStoreError();
return;
}
std::string policy_blob;
if (!validator->policy()->SerializeToString(&policy_blob)) {
status_ = CloudPolicyStore::STATUS_SERIALIZE_ERROR;
NotifyStoreError();
return;
}
session_manager_client_->StoreDeviceLocalAccountPolicy(
account_id_,
policy_blob,
base::Bind(&DeviceLocalAccountPolicyStore::HandleStoreResult,
weak_factory_.GetWeakPtr()));
}
void DeviceLocalAccountPolicyStore::HandleStoreResult(bool success) {
if (!success) {
status_ = CloudPolicyStore::STATUS_STORE_ERROR;
NotifyStoreError();
} else {
Load();
}
}
void DeviceLocalAccountPolicyStore::CheckKeyAndValidate(
scoped_ptr<em::PolicyFetchResponse> policy,
const UserCloudPolicyValidator::CompletionCallback& callback) {
device_settings_service_->GetOwnershipStatusAsync(
base::Bind(&DeviceLocalAccountPolicyStore::Validate,
weak_factory_.GetWeakPtr(),
base::Passed(&policy),
callback));
}
void DeviceLocalAccountPolicyStore::Validate(
scoped_ptr<em::PolicyFetchResponse> policy_response,
const UserCloudPolicyValidator::CompletionCallback& callback,
chromeos::DeviceSettingsService::OwnershipStatus ownership_status) {
DCHECK_NE(chromeos::DeviceSettingsService::OWNERSHIP_UNKNOWN,
ownership_status);
scoped_refptr<chromeos::OwnerKey> key =
device_settings_service_->GetOwnerKey();
if (!key.get() || !key->public_key()) {
status_ = CloudPolicyStore::STATUS_BAD_STATE;
NotifyStoreLoaded();
return;
}
scoped_ptr<UserCloudPolicyValidator> validator(
UserCloudPolicyValidator::Create(policy_response.Pass(),
background_task_runner()));
validator->ValidateUsername(account_id_);
validator->ValidatePolicyType(dm_protocol::kChromePublicAccountPolicyType);
validator->ValidateAgainstCurrentPolicy(
policy(),
CloudPolicyValidatorBase::TIMESTAMP_REQUIRED,
CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
validator->ValidatePayload();
validator->ValidateSignature(*key->public_key(), false);
validator.release()->StartValidation(callback);
}
} // namespace policy