Commit 5fa0ee22 authored by ygorshenin's avatar ygorshenin Committed by Commit bot

Implemented OwnerSettingsService::Set() method.

BUG=230018
TEST=unit_tests:OwnerSettingsServiceChromeOSTest.*

Review URL: https://codereview.chromium.org/654263003

Cr-Commit-Position: refs/heads/master@{#301132}
parent 98f956e5
......@@ -5,12 +5,12 @@
#ifndef CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_CHROMEOS_H_
#define CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_CHROMEOS_H_
#include <deque>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/keyed_service/core/keyed_service.h"
......@@ -27,8 +27,6 @@ class OwnerKeyUtil;
namespace chromeos {
class SessionManagerOperation;
// The class is a profile-keyed service which holds public/private
// keypair corresponds to a profile. The keypair is reloaded automatically when
// profile is created and TPM token is ready. Note that the private part of a
......@@ -38,16 +36,19 @@ class SessionManagerOperation;
// (crbug.com/230018).
class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
public content::NotificationObserver,
public SessionManagerClient::Observer {
public SessionManagerClient::Observer,
public DeviceSettingsService::Observer {
public:
virtual ~OwnerSettingsServiceChromeOS();
void OnTPMTokenReady(bool tpm_token_enabled);
// ownership::OwnerSettingsService implementation:
virtual void SignAndStorePolicyAsync(
scoped_ptr<enterprise_management::PolicyData> policy,
const base::Closure& callback) override;
virtual bool HandlesSetting(const std::string& setting) override;
virtual bool Set(const std::string& setting,
const base::Value& value) override;
virtual bool CommitTentativeDeviceSettings(
scoped_ptr<enterprise_management::PolicyData> policy) override;
// NotificationObserver implementation:
virtual void Observe(int type,
......@@ -57,6 +58,10 @@ class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
// SessionManagerClient::Observer:
virtual void OwnerKeySet(bool success) override;
// DeviceSettingsService::Observer:
virtual void OwnershipStatusChanged() override;
virtual void DeviceSettingsUpdated() override;
// Checks if the user is the device owner, without the user profile having to
// been initialized. Should be used only if login state is in safe mode.
static void IsOwnerForSafeModeAsync(
......@@ -64,13 +69,26 @@ class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util,
const IsOwnerCallback& callback);
static void SetDeviceSettingsServiceForTesting(
DeviceSettingsService* device_settings_service);
// Assembles PolicyData based on |settings|, |policy_data| and
// |user_id|.
static scoped_ptr<enterprise_management::PolicyData> AssemblePolicy(
const std::string& user_id,
const enterprise_management::PolicyData* policy_data,
const enterprise_management::ChromeDeviceSettingsProto* settings);
// Updates device |settings|.
static void UpdateDeviceSettings(
const std::string& path,
const base::Value& value,
enterprise_management::ChromeDeviceSettingsProto& settings);
bool has_pending_changes() const { return has_pending_changes_; }
private:
friend class OwnerSettingsServiceChromeOSFactory;
OwnerSettingsServiceChromeOS(
DeviceSettingsService* device_settings_service,
Profile* profile,
const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util);
......@@ -85,13 +103,26 @@ class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
// Possibly notifies DeviceSettingsService that owner's keypair is loaded.
virtual void OnPostKeypairLoadedActions() override;
// Performs next operation in the queue.
void StartNextOperation();
// Tries to sign store current device settings if there're pending
// changes in device settings and no active previous call to
// DeviceSettingsService::Store().
void StoreDeviceSettings();
// Called when current device settings are successfully signed.
// Sends signed settings for storage.
void OnPolicyAssembledAndSigned(
scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response);
// Called when sign-and-store operation completes it's work.
void HandleCompletedOperation(const base::Closure& callback,
SessionManagerOperation* operation,
DeviceSettingsService::Status status);
// Called by DeviceSettingsService when modified and signed device
// settings are stored. Notifies observers and tries to store device
// settings again.
void OnSignedPolicyStored(bool success);
// Fetches device settings from DeviceSettingsService and merges
// them with local device settings.
bool UpdateFromService();
DeviceSettingsService* device_settings_service_;
// Profile this service instance belongs to.
Profile* profile_;
......@@ -105,14 +136,22 @@ class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
// Whether TPM token still needs to be initialized.
bool waiting_for_tpm_token_;
// The queue of pending sign-and-store operations. The first operation on the
// queue is currently active; it gets removed and destroyed once it completes.
std::deque<SessionManagerOperation*> pending_operations_;
// The device settings. This may be different from the actual
// current device settings (which can be obtained from
// DeviceSettingsService) in case the device does not have an owner
// yet or there are pending changes that have not yet been written
// to session_manager.
enterprise_management::ChromeDeviceSettingsProto device_settings_;
// True if some settings were changed but not stored.
bool has_pending_changes_;
content::NotificationRegistrar registrar_;
base::WeakPtrFactory<OwnerSettingsServiceChromeOS> weak_factory_;
base::WeakPtrFactory<OwnerSettingsServiceChromeOS> store_settings_factory_;
DISALLOW_COPY_AND_ASSIGN(OwnerSettingsServiceChromeOS);
};
......
......@@ -7,6 +7,7 @@
#include "base/path_service.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/chromeos_paths.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
......@@ -15,6 +16,19 @@
namespace chromeos {
namespace {
DeviceSettingsService* g_device_settings_service_for_testing_ = nullptr;
DeviceSettingsService* GetDeviceSettingsService() {
if (g_device_settings_service_for_testing_)
return g_device_settings_service_for_testing_;
return DeviceSettingsService::IsInitialized() ? DeviceSettingsService::Get()
: nullptr;
}
} // namespace
OwnerSettingsServiceChromeOSFactory::OwnerSettingsServiceChromeOSFactory()
: BrowserContextKeyedServiceFactory(
"OwnerSettingsService",
......@@ -37,6 +51,12 @@ OwnerSettingsServiceChromeOSFactory::GetInstance() {
return Singleton<OwnerSettingsServiceChromeOSFactory>::get();
}
// static
void OwnerSettingsServiceChromeOSFactory::SetDeviceSettingsServiceForTesting(
DeviceSettingsService* device_settings_service) {
g_device_settings_service_for_testing_ = device_settings_service;
}
scoped_refptr<ownership::OwnerKeyUtil>
OwnerSettingsServiceChromeOSFactory::GetOwnerKeyUtil() {
if (owner_key_util_.get())
......@@ -59,8 +79,10 @@ KeyedService* OwnerSettingsServiceChromeOSFactory::BuildInstanceFor(
Profile* profile = static_cast<Profile*>(browser_context);
if (profile->IsGuestSession() || ProfileHelper::IsSigninProfile(profile))
return NULL;
return new OwnerSettingsServiceChromeOS(profile,
GetInstance()->GetOwnerKeyUtil());
return new OwnerSettingsServiceChromeOS(
GetDeviceSettingsService(),
profile,
GetInstance()->GetOwnerKeyUtil());
}
bool OwnerSettingsServiceChromeOSFactory::ServiceIsCreatedWithBrowserContext()
......
......@@ -20,6 +20,7 @@ class OwnerKeyUtil;
namespace chromeos {
class DeviceSettingsService;
class OwnerSettingsServiceChromeOS;
class OwnerSettingsServiceChromeOSFactory
......@@ -29,6 +30,9 @@ class OwnerSettingsServiceChromeOSFactory
static OwnerSettingsServiceChromeOSFactory* GetInstance();
static void SetDeviceSettingsServiceForTesting(
DeviceSettingsService* device_settings_service);
scoped_refptr<ownership::OwnerKeyUtil> GetOwnerKeyUtil();
void SetOwnerKeyUtilForTesting(
......
// 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 <queue>
#include <utility>
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/test/scoped_path_override.h"
#include "base/values.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/settings/device_settings_provider.h"
#include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/settings/cros_settings_names.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
void OnPrefChanged(const std::string& /* setting */) {
}
class PrefsChecker : public ownership::OwnerSettingsService::Observer {
public:
PrefsChecker(OwnerSettingsServiceChromeOS* service,
DeviceSettingsProvider* provider)
: service_(service), provider_(provider) {
CHECK(service_);
CHECK(provider_);
service_->AddObserver(this);
}
virtual ~PrefsChecker() { service_->RemoveObserver(this); }
// OwnerSettingsService::Observer implementation:
virtual void OnSignedPolicyStored(bool success) override {
CHECK(success);
if (service_->has_pending_changes())
return;
while (!set_requests_.empty()) {
SetRequest request = set_requests_.front();
set_requests_.pop();
const base::Value* value = provider_->Get(request.first);
ASSERT_TRUE(request.second->Equals(value));
}
loop_.Quit();
}
void Set(const std::string& setting, const base::Value& value) {
service_->Set(setting, value);
set_requests_.push(
SetRequest(setting, linked_ptr<base::Value>(value.DeepCopy())));
}
void Wait() { loop_.Run(); }
private:
OwnerSettingsServiceChromeOS* service_;
DeviceSettingsProvider* provider_;
base::RunLoop loop_;
typedef std::pair<std::string, linked_ptr<base::Value>> SetRequest;
std::queue<SetRequest> set_requests_;
DISALLOW_COPY_AND_ASSIGN(PrefsChecker);
};
} // namespace
class OwnerSettingsServiceChromeOSTest : public DeviceSettingsTestBase {
public:
OwnerSettingsServiceChromeOSTest()
: local_state_(TestingBrowserProcess::GetGlobal()),
user_data_dir_override_(chrome::DIR_USER_DATA) {}
virtual void SetUp() override {
DeviceSettingsTestBase::SetUp();
provider_.reset(new DeviceSettingsProvider(base::Bind(&OnPrefChanged),
&device_settings_service_));
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
InitOwner(device_policy_.policy_data().username(), true);
FlushDeviceSettings();
}
virtual void TearDown() override { DeviceSettingsTestBase::TearDown(); }
void TestSingleSet(OwnerSettingsServiceChromeOS* service,
const std::string& setting,
const base::Value& in_value) {
PrefsChecker checker(service, provider_.get());
checker.Set(setting, in_value);
FlushDeviceSettings();
checker.Wait();
}
ScopedTestingLocalState local_state_;
scoped_ptr<DeviceSettingsProvider> provider_;
base::ScopedPathOverride user_data_dir_override_;
private:
DISALLOW_COPY_AND_ASSIGN(OwnerSettingsServiceChromeOSTest);
};
TEST_F(OwnerSettingsServiceChromeOSTest, SingleSetTest) {
OwnerSettingsServiceChromeOS* service =
OwnerSettingsServiceChromeOSFactory::GetForProfile(profile_.get());
ASSERT_TRUE(service);
ASSERT_TRUE(service->IsOwner());
TestSingleSet(service, kReleaseChannel, base::StringValue("dev-channel"));
TestSingleSet(service, kReleaseChannel, base::StringValue("beta-channel"));
TestSingleSet(service, kReleaseChannel, base::StringValue("stable-channel"));
}
TEST_F(OwnerSettingsServiceChromeOSTest, MultipleSetTest) {
OwnerSettingsServiceChromeOS* service =
OwnerSettingsServiceChromeOSFactory::GetForProfile(profile_.get());
ASSERT_TRUE(service);
ASSERT_TRUE(service->IsOwner());
base::FundamentalValue allow_guest(false);
base::StringValue release_channel("stable-channel");
base::FundamentalValue show_user_names(true);
PrefsChecker checker(service, provider_.get());
checker.Set(kAccountsPrefAllowGuest, allow_guest);
checker.Set(kReleaseChannel, release_channel);
checker.Set(kAccountsPrefShowUserNamesOnSignIn, show_user_names);
FlushDeviceSettings();
checker.Wait();
}
} // namespace chromeos
......@@ -100,7 +100,6 @@ class DeviceCloudPolicyInvalidatorTest : public testing::Test {
private:
content::TestBrowserThreadBundle thread_bundle_;
scoped_refptr<net::URLRequestContextGetter> system_request_context_;
TestingProfileManager profile_manager_;
chromeos::FakeUserManager* fake_user_manager_;
chromeos::ScopedUserManagerEnabler user_manager_enabler_;
ScopedStubEnterpriseInstallAttributes install_attributes_;
......@@ -108,6 +107,7 @@ class DeviceCloudPolicyInvalidatorTest : public testing::Test {
test_device_settings_service_;
scoped_ptr<chromeos::ScopedTestCrosSettings> test_cros_settings_;
chromeos::DeviceSettingsTestHelper device_settings_test_helper_;
TestingProfileManager profile_manager_;
scoped_ptr<DeviceCloudPolicyInvalidator> invalidator_;
};
......@@ -116,13 +116,13 @@ DeviceCloudPolicyInvalidatorTest::DeviceCloudPolicyInvalidatorTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
system_request_context_(new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current())),
profile_manager_(TestingBrowserProcess::GetGlobal()),
fake_user_manager_(new chromeos::FakeUserManager),
user_manager_enabler_(fake_user_manager_),
install_attributes_("example.com",
"user@example.com",
"device_id",
DEVICE_MODE_ENTERPRISE) {
DEVICE_MODE_ENTERPRISE),
profile_manager_(TestingBrowserProcess::GetGlobal()) {
}
DeviceCloudPolicyInvalidatorTest::~DeviceCloudPolicyInvalidatorTest() {
......
......@@ -5,9 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_PROVIDER_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_PROVIDER_H_
#include <deque>
#include <string>
#include <utility>
#include <vector>
#include "base/basictypes.h"
......@@ -18,6 +16,7 @@
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chromeos/settings/cros_settings_provider.h"
#include "components/ownership/owner_settings_service.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
namespace base {
......@@ -31,8 +30,13 @@ class ChromeDeviceSettingsProto;
namespace chromeos {
// CrosSettingsProvider implementation that works with device settings.
class DeviceSettingsProvider : public CrosSettingsProvider,
public DeviceSettingsService::Observer {
//
// Note that the write path is in the process of being migrated to
// OwnerSettingsServiceChromeOS (crbug.com/230018).
class DeviceSettingsProvider
: public CrosSettingsProvider,
public DeviceSettingsService::Observer,
public ownership::OwnerSettingsService::Observer {
public:
// The callback type that is called to get the device mode.
typedef base::Callback<policy::DeviceMode(void)> GetDeviceModeCallback;
......@@ -59,16 +63,15 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
virtual void OwnershipStatusChanged() override;
virtual void DeviceSettingsUpdated() override;
// ownership::OwnerSettingsService::Observer implementation:
virtual void OnTentativeChangesInPolicy(
const enterprise_management::PolicyData& policy_data) override;
// Populates in-memory cache from the local_state cache that is used to store
// device settings before the device is owned and to speed up policy
// availability before the policy blob is fetched on boot.
void RetrieveCachedData();
// Stores a value from the |pending_changes_| queue in the device settings.
// If the device is not owned yet the data ends up only in the local_state
// cache and is serialized once ownership is acquired.
void SetInPolicy();
// Parses the policy data and fills in |values_cache_|.
void UpdateValuesCache(
const enterprise_management::PolicyData& policy_data,
......@@ -107,10 +110,6 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
// if new settings have been loaded.
bool UpdateFromService();
// Sends |device_settings_| to |device_settings_service_| for signing and
// storage in session_manager.
void StoreDeviceSettings();
// Checks the current ownership status to see whether the device owner is
// logged in and writes the data accumulated in |migration_values_| to proper
// device settings.
......@@ -125,22 +124,19 @@ class DeviceSettingsProvider : public CrosSettingsProvider,
TrustedStatus trusted_status_;
DeviceSettingsService::OwnershipStatus ownership_status_;
// The device settings as currently reported through the CrosSettingsProvider
// interface. This may be different from the actual current device settings
// (which can be obtained from |device_settings_service_|) in case the device
// does not have an owner yet or there are pending changes that have not yet
// been written to session_manager.
// The device settings as currently reported through the
// CrosSettingsProvider interface. This may be different from the
// actual current device settings (which can be obtained from
// |device_settings_service_|) in case the device does not have an
// owner yet. As soon as ownership of the device will be taken,
// |device_settings_| will stored on disk and won't be used.
enterprise_management::ChromeDeviceSettingsProto device_settings_;
// A cache of values, indexed by the settings keys served through the
// CrosSettingsProvider interface. This is always kept in sync with the raw
// data found in |device_settings_|.
// CrosSettingsProvider interface. This is always kept in sync with the
// current device settings.
PrefValueMap values_cache_;
// This is a queue for set requests, because those need to be sequential.
typedef std::pair<std::string, base::Value*> PendingQueueElement;
std::deque<PendingQueueElement> pending_changes_;
// Weak pointer factory for creating store operation callbacks.
base::WeakPtrFactory<DeviceSettingsProvider> store_callback_factory_;
......
......@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/session_manager_operation.h"
#include "components/ownership/owner_key_util.h"
......@@ -35,36 +36,6 @@ int kLoadRetryDelayMs = 1000 * 5;
// of retry time.
int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
// Assembles PolicyData based on |settings|, |policy_data| and
// |user_id|.
scoped_ptr<em::PolicyData> AssemblePolicy(
const std::string& user_id,
const em::PolicyData* policy_data,
const em::ChromeDeviceSettingsProto* settings) {
scoped_ptr<em::PolicyData> policy(new em::PolicyData());
if (policy_data) {
// Preserve management settings.
if (policy_data->has_management_mode())
policy->set_management_mode(policy_data->management_mode());
if (policy_data->has_request_token())
policy->set_request_token(policy_data->request_token());
if (policy_data->has_device_id())
policy->set_device_id(policy_data->device_id());
} else {
// If there's no previous policy data, this is the first time the device
// setting is set. We set the management mode to NOT_MANAGED initially.
policy->set_management_mode(em::PolicyData::NOT_MANAGED);
}
policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
policy->set_timestamp(
(base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
policy->set_username(user_id);
if (!settings->SerializeToString(policy->mutable_policy_value()))
return scoped_ptr<em::PolicyData>();
return policy.Pass();
}
// Returns true if it is okay to transfer from the current mode to the new
// mode. This function should be called in SetManagementMode().
bool CheckManagementModeTransition(em::PolicyData::ManagementMode current_mode,
......@@ -151,8 +122,6 @@ void DeviceSettingsService::SetSessionManager(
}
void DeviceSettingsService::UnsetSessionManager() {
STLDeleteContainerPointers(pending_operations_.begin(),
pending_operations_.end());
pending_operations_.clear();
if (session_manager_client_)
......@@ -172,18 +141,10 @@ void DeviceSettingsService::Load() {
void DeviceSettingsService::SignAndStore(
scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
const base::Closure& callback) {
if (!owner_settings_service_) {
HandleError(STORE_KEY_UNAVAILABLE, callback);
return;
}
scoped_ptr<em::PolicyData> policy =
AssemblePolicy(GetUsername(), policy_data(), new_settings.get());
if (!policy) {
HandleError(STORE_POLICY_ERROR, callback);
return;
}
owner_settings_service_->SignAndStorePolicyAsync(policy.Pass(), callback);
OwnerSettingsServiceChromeOS::AssemblePolicy(
GetUsername(), policy_data(), new_settings.get());
EnqueueSignAndStore(policy.Pass(), callback);
}
void DeviceSettingsService::SetManagementSettings(
......@@ -208,7 +169,8 @@ void DeviceSettingsService::SetManagementSettings(
}
scoped_ptr<em::PolicyData> policy =
AssemblePolicy(GetUsername(), policy_data(), device_settings());
OwnerSettingsServiceChromeOS::AssemblePolicy(
GetUsername(), policy_data(), device_settings());
if (!policy) {
HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
return;
......@@ -218,17 +180,16 @@ void DeviceSettingsService::SetManagementSettings(
policy->set_request_token(request_token);
policy->set_device_id(device_id);
owner_settings_service_->SignAndStorePolicyAsync(policy.Pass(), callback);
EnqueueSignAndStore(policy.Pass(), callback);
}
void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
const base::Closure& callback) {
Enqueue(
new StoreSettingsOperation(
base::Bind(&DeviceSettingsService::HandleCompletedOperation,
weak_factory_.GetWeakPtr(),
callback),
policy.Pass()));
Enqueue(linked_ptr<SessionManagerOperation>(new StoreSettingsOperation(
base::Bind(&DeviceSettingsService::HandleCompletedOperation,
weak_factory_.GetWeakPtr(),
callback),
policy.Pass())));
}
DeviceSettingsService::OwnershipStatus
......@@ -276,6 +237,11 @@ const std::string& DeviceSettingsService::GetUsername() const {
return username_;
}
ownership::OwnerSettingsService*
DeviceSettingsService::GetOwnerSettingsService() const {
return owner_settings_service_.get();
}
void DeviceSettingsService::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
......@@ -303,24 +269,37 @@ void DeviceSettingsService::PropertyChangeComplete(bool success) {
EnsureReload(false);
}
void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
void DeviceSettingsService::Enqueue(
const linked_ptr<SessionManagerOperation>& operation) {
pending_operations_.push_back(operation);
if (pending_operations_.front() == operation)
if (pending_operations_.front().get() == operation.get())
StartNextOperation();
}
void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
SessionManagerOperation* operation =
new LoadSettingsOperation(
base::Bind(&DeviceSettingsService::HandleCompletedOperation,
weak_factory_.GetWeakPtr(),
base::Closure()));
linked_ptr<SessionManagerOperation> operation(new LoadSettingsOperation(
base::Bind(&DeviceSettingsService::HandleCompletedOperation,
weak_factory_.GetWeakPtr(),
base::Closure())));
operation->set_force_key_load(force_key_load);
operation->set_username(username_);
operation->set_owner_settings_service(owner_settings_service_);
Enqueue(operation);
}
void DeviceSettingsService::EnqueueSignAndStore(
scoped_ptr<enterprise_management::PolicyData> policy,
const base::Closure& callback) {
linked_ptr<SessionManagerOperation> operation(
new SignAndStoreSettingsOperation(
base::Bind(&DeviceSettingsService::HandleCompletedOperation,
weak_factory_.GetWeakPtr(),
callback),
policy.Pass()));
operation->set_owner_settings_service(owner_settings_service_);
Enqueue(operation);
}
void DeviceSettingsService::EnsureReload(bool force_key_load) {
if (!pending_operations_.empty()) {
pending_operations_.front()->set_username(username_);
......@@ -333,8 +312,7 @@ void DeviceSettingsService::EnsureReload(bool force_key_load) {
}
void DeviceSettingsService::StartNextOperation() {
if (!pending_operations_.empty() &&
session_manager_client_ &&
if (!pending_operations_.empty() && session_manager_client_ &&
owner_key_util_.get()) {
pending_operations_.front()->Start(
session_manager_client_, owner_key_util_, public_key_);
......@@ -345,7 +323,7 @@ void DeviceSettingsService::HandleCompletedOperation(
const base::Closure& callback,
SessionManagerOperation* operation,
Status status) {
DCHECK_EQ(operation, pending_operations_.front());
DCHECK_EQ(operation, pending_operations_.front().get());
store_status_ = status;
OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
......@@ -412,7 +390,6 @@ void DeviceSettingsService::HandleCompletedOperation(
// Only remove the pending operation here, so new operations triggered by any
// of the callbacks above are queued up properly.
pending_operations_.pop_front();
delete operation;
StartNextOperation();
}
......@@ -431,11 +408,6 @@ void DeviceSettingsService::HandleError(Status status,
callback.Run();
}
void DeviceSettingsService::OnSignAndStoreOperationCompleted(Status status) {
store_status_ = status;
FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
}
ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
DeviceSettingsService::Initialize();
}
......
......@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
......@@ -138,6 +139,9 @@ class DeviceSettingsService : public SessionManagerClient::Observer {
const base::Closure& callback);
// Sets the management related settings in PolicyData.
//
// TODO (ygorshenin@, crbug.com/230018): move this to the
// OwnerSettingsService.
void SetManagementSettings(
enterprise_management::PolicyData::ManagementMode management_mode,
const std::string& request_token,
......@@ -169,6 +173,8 @@ class DeviceSettingsService : public SessionManagerClient::Observer {
const std::string& GetUsername() const;
ownership::OwnerSettingsService* GetOwnerSettingsService() const;
// Adds an observer.
void AddObserver(Observer* observer);
// Removes an observer.
......@@ -183,11 +189,15 @@ class DeviceSettingsService : public SessionManagerClient::Observer {
// Enqueues a new operation. Takes ownership of |operation| and starts it
// right away if there is no active operation currently.
void Enqueue(SessionManagerOperation* operation);
void Enqueue(const linked_ptr<SessionManagerOperation>& operation);
// Enqueues a load operation.
void EnqueueLoad(bool force_key_load);
// Enqueues a sign and store operation.
void EnqueueSignAndStore(scoped_ptr<enterprise_management::PolicyData> policy,
const base::Closure& callback);
// Makes sure there's a reload operation so changes to the settings (and key,
// in case force_key_load is set) are getting picked up.
void EnsureReload(bool force_key_load);
......@@ -204,19 +214,6 @@ class DeviceSettingsService : public SessionManagerClient::Observer {
// Updates status and invokes the callback immediately.
void HandleError(Status status, const base::Closure& callback);
// Called by OwnerSettingsService when sign-and-store operation completes.
void OnSignAndStoreOperationCompleted(Status status);
void set_policy_data(
scoped_ptr<enterprise_management::PolicyData> policy_data) {
policy_data_ = policy_data.Pass();
}
void set_device_settings(scoped_ptr<
enterprise_management::ChromeDeviceSettingsProto> device_settings) {
device_settings_ = device_settings.Pass();
}
SessionManagerClient* session_manager_client_;
scoped_refptr<ownership::OwnerKeyUtil> owner_key_util_;
......@@ -233,9 +230,9 @@ class DeviceSettingsService : public SessionManagerClient::Observer {
// The queue of pending operations. The first operation on the queue is
// currently active; it gets removed and destroyed once it completes.
std::deque<SessionManagerOperation*> pending_operations_;
std::deque<linked_ptr<SessionManagerOperation>> pending_operations_;
ObserverList<Observer, true> observers_;
ObserverList<Observer> observers_;
// For recoverable load errors how many retries are left before we give up.
int load_retries_left_;
......
......@@ -197,6 +197,8 @@ DeviceSettingsTestBase::DeviceSettingsTestBase()
: user_manager_(new FakeUserManager()),
user_manager_enabler_(user_manager_),
owner_key_util_(new ownership::MockOwnerKeyUtil()) {
OwnerSettingsServiceChromeOSFactory::SetDeviceSettingsServiceForTesting(
&device_settings_service_);
OwnerSettingsServiceChromeOSFactory::GetInstance()->SetOwnerKeyUtilForTesting(
owner_key_util_);
}
......@@ -218,13 +220,11 @@ void DeviceSettingsTestBase::SetUp() {
device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob());
device_settings_service_.SetSessionManager(&device_settings_test_helper_,
owner_key_util_);
OwnerSettingsServiceChromeOS::SetDeviceSettingsServiceForTesting(
&device_settings_service_);
profile_.reset(new TestingProfile());
}
void DeviceSettingsTestBase::TearDown() {
OwnerSettingsServiceChromeOS::SetDeviceSettingsServiceForTesting(NULL);
OwnerSettingsServiceChromeOSFactory::SetDeviceSettingsServiceForTesting(NULL);
FlushDeviceSettings();
device_settings_service_.UnsetSessionManager();
DBusThreadManager::Shutdown();
......
......@@ -185,11 +185,11 @@ class DeviceSettingsTestBase : public testing::Test {
// tested classes depend on implicitly.
FakeUserManager* user_manager_;
ScopedUserManagerEnabler user_manager_enabler_;
scoped_ptr<TestingProfile> profile_;
scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
// Local DeviceSettingsService instance for tests. Avoid using in combination
// with the global instance (DeviceSettingsService::Get()).
DeviceSettingsService device_settings_service_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<DBusThreadManagerSetter> dbus_setter_;
......
......@@ -245,12 +245,15 @@ SignAndStoreSettingsOperation::SignAndStoreSettingsOperation(
: SessionManagerOperation(callback),
new_policy_(new_policy.Pass()),
weak_factory_(this) {
DCHECK(new_policy_);
}
SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
void SignAndStoreSettingsOperation::Run() {
if (!new_policy_) {
ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
return;
}
if (!owner_settings_service_) {
ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
return;
......@@ -269,7 +272,7 @@ void SignAndStoreSettingsOperation::StartSigning(bool is_owner) {
bool rv = owner_settings_service_->AssembleAndSignPolicyAsync(
content::BrowserThread::GetBlockingPool(),
new_policy_.Pass(),
base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob,
base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettings,
weak_factory_.GetWeakPtr()));
if (!rv) {
ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
......@@ -277,15 +280,15 @@ void SignAndStoreSettingsOperation::StartSigning(bool is_owner) {
}
}
void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob(
std::string device_settings_blob) {
if (device_settings_blob.empty()) {
void SignAndStoreSettingsOperation::StoreDeviceSettings(
scoped_ptr<em::PolicyFetchResponse> policy_response) {
if (!policy_response.get()) {
ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
return;
}
session_manager_client()->StoreDevicePolicy(
device_settings_blob,
policy_response->SerializeAsString(),
base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult,
weak_factory_.GetWeakPtr()));
}
......
......@@ -189,7 +189,8 @@ class SignAndStoreSettingsOperation : public SessionManagerOperation {
void StartSigning(bool has_private_key);
// Stores the signed device settings blob.
void StoreDeviceSettingsBlob(std::string device_settings_blob);
void StoreDeviceSettings(
scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response);
// Handles the result of the store operation and triggers the load.
void HandleStoreResult(bool success);
......
......@@ -219,6 +219,7 @@
'browser/chromeos/net/onc_utils_unittest.cc',
'browser/chromeos/offline/offline_load_page_unittest.cc',
'browser/chromeos/options/network_property_ui_data_unittest.cc',
'browser/chromeos/ownership/owner_settings_service_chromeos_unittest.cc',
'browser/chromeos/policy/auto_enrollment_client_unittest.cc',
'browser/chromeos/policy/cloud_external_data_manager_base_unittest.cc',
'browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc',
......
......@@ -12,6 +12,7 @@
#include "base/message_loop/message_loop.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
#include "base/values.h"
#include "components/ownership/owner_key_util.h"
#include "crypto/signature_creator.h"
......@@ -21,13 +22,15 @@ namespace ownership {
namespace {
std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
crypto::RSAPrivateKey* private_key) {
scoped_ptr<em::PolicyFetchResponse> AssembleAndSignPolicy(
scoped_ptr<em::PolicyData> policy,
crypto::RSAPrivateKey* private_key) {
// Assemble the policy.
em::PolicyFetchResponse policy_response;
if (!policy->SerializeToString(policy_response.mutable_policy_data())) {
scoped_ptr<em::PolicyFetchResponse> policy_response(
new em::PolicyFetchResponse());
if (!policy->SerializeToString(policy_response->mutable_policy_data())) {
LOG(ERROR) << "Failed to encode policy payload.";
return std::string();
return scoped_ptr<em::PolicyFetchResponse>(nullptr).Pass();
}
// Generate the signature.
......@@ -35,19 +38,19 @@ std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
crypto::SignatureCreator::Create(private_key,
crypto::SignatureCreator::SHA1));
signature_creator->Update(
reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
policy_response.policy_data().size());
reinterpret_cast<const uint8*>(policy_response->policy_data().c_str()),
policy_response->policy_data().size());
std::vector<uint8> signature_bytes;
std::string policy_blob;
if (!signature_creator->Final(&signature_bytes)) {
LOG(ERROR) << "Failed to create policy signature.";
return std::string();
return scoped_ptr<em::PolicyFetchResponse>(nullptr).Pass();
}
policy_response.mutable_policy_data_signature()->assign(
policy_response->mutable_policy_data_signature()->assign(
reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
signature_bytes.size());
return policy_response.SerializeAsString();
return policy_response.Pass();
}
} // namepace
......@@ -61,6 +64,15 @@ OwnerSettingsService::~OwnerSettingsService() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void OwnerSettingsService::AddObserver(Observer* observer) {
if (observer && !observers_.HasObserver(observer))
observers_.AddObserver(observer);
}
void OwnerSettingsService::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
bool OwnerSettingsService::IsOwner() {
DCHECK(thread_checker_.CalledOnValidThread());
return private_key_.get() && private_key_->key();
......@@ -91,6 +103,31 @@ bool OwnerSettingsService::AssembleAndSignPolicyAsync(
callback);
}
bool OwnerSettingsService::SetBoolean(const std::string& setting, bool value) {
DCHECK(thread_checker_.CalledOnValidThread());
base::FundamentalValue in_value(value);
return Set(setting, in_value);
}
bool OwnerSettingsService::SetInteger(const std::string& setting, int value) {
DCHECK(thread_checker_.CalledOnValidThread());
base::FundamentalValue in_value(value);
return Set(setting, in_value);
}
bool OwnerSettingsService::SetDouble(const std::string& setting, double value) {
DCHECK(thread_checker_.CalledOnValidThread());
base::FundamentalValue in_value(value);
return Set(setting, in_value);
}
bool OwnerSettingsService::SetString(const std::string& setting,
const std::string& value) {
DCHECK(thread_checker_.CalledOnValidThread());
base::StringValue in_value(value);
return Set(setting, in_value);
}
void OwnerSettingsService::ReloadKeypair() {
ReloadKeypairImpl(
base::Bind(&OwnerSettingsService::OnKeypairLoaded, as_weak_ptr()));
......
......@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/ownership/ownership_export.h"
......@@ -20,6 +21,7 @@
namespace base {
class TaskRunner;
class Value;
}
namespace ownership {
......@@ -31,19 +33,42 @@ class PublicKey;
// which deal with ownership, keypairs and owner-related settings.
class OWNERSHIP_EXPORT OwnerSettingsService : public KeyedService {
public:
typedef base::Callback<void(std::string policy_blob)>
class Observer {
public:
virtual ~Observer() {}
// Called when signed policy was stored, or when an error happed during
// policy storage..
virtual void OnSignedPolicyStored(bool success) {}
// Called when tentative changes were made to policy, but the policy still
// not signed and stored.
//
// TODO (ygorshenin@, crbug.com/230018): get rid of the method
// since it creates DeviceSettingsService's dependency on
// OwnerSettingsService.
virtual void OnTentativeChangesInPolicy(
const enterprise_management::PolicyData& policy_data) {}
};
typedef base::Callback<void(
scoped_ptr<enterprise_management::PolicyFetchResponse> policy_response)>
AssembleAndSignPolicyAsyncCallback;
typedef base::Callback<void(bool is_owner)> IsOwnerCallback;
explicit OwnerSettingsService(
const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util);
~OwnerSettingsService() override;
virtual ~OwnerSettingsService();
base::WeakPtr<OwnerSettingsService> as_weak_ptr() {
return weak_factory_.GetWeakPtr();
}
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Returns whether current user is owner or not. When this method
// is called too early, incorrect result can be returned because
// private key loading may be in progress.
......@@ -60,12 +85,24 @@ class OWNERSHIP_EXPORT OwnerSettingsService : public KeyedService {
scoped_ptr<enterprise_management::PolicyData> policy,
const AssembleAndSignPolicyAsyncCallback& callback);
// Signs |settings| with the private half of the owner key and sends
// the resulting policy blob for storage. The
// result of the operation is reported through |callback|.
virtual void SignAndStorePolicyAsync(
scoped_ptr<enterprise_management::PolicyData> policy,
const base::Closure& callback) = 0;
// Checks whether |setting| is handled by OwnerSettingsService.
virtual bool HandlesSetting(const std::string& setting) = 0;
// Sets |setting| value to |value|.
virtual bool Set(const std::string& setting, const base::Value& value) = 0;
// Sets a bunch of device settings accumulated before ownership gets
// established.
//
// TODO (ygorshenin@, crbug.com/230018): that this is a temporary
// solution and should be removed.
virtual bool CommitTentativeDeviceSettings(
scoped_ptr<enterprise_management::PolicyData> policy) = 0;
bool SetBoolean(const std::string& setting, bool value);
bool SetInteger(const std::string& setting, int value);
bool SetDouble(const std::string& setting, double value);
bool SetString(const std::string& setting, const std::string& value);
protected:
void ReloadKeypair();
......@@ -89,6 +126,8 @@ class OWNERSHIP_EXPORT OwnerSettingsService : public KeyedService {
std::vector<IsOwnerCallback> pending_is_owner_callbacks_;
ObserverList<Observer> observers_;
base::ThreadChecker thread_checker_;
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment