Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Unified Diff: chrome/browser/chromeos/settings/device_settings_service.cc

Issue 10828032: Add DeviceSettingsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/settings/device_settings_service.cc
diff --git a/chrome/browser/chromeos/settings/device_settings_service.cc b/chrome/browser/chromeos/settings/device_settings_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e8c03f1cb1756b3fbbef4d8178f0d7ba8cf08eee
--- /dev/null
+++ b/chrome/browser/chromeos/settings/device_settings_service.cc
@@ -0,0 +1,272 @@
+// 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/settings/device_settings_service.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/stl_util.h"
+#include "chrome/browser/chromeos/settings/owner_key_util.h"
+#include "chrome/browser/chromeos/settings/session_manager_operation.h"
+#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "crypto/rsa_private_key.h"
+
+namespace em = enterprise_management;
+
+namespace chromeos {
+
+static base::LazyInstance<DeviceSettingsService> g_device_settings_service =
+ LAZY_INSTANCE_INITIALIZER;
+
+OwnerKey::OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
+ scoped_ptr<crypto::RSAPrivateKey> private_key)
+ : public_key_(public_key.Pass()),
+ private_key_(private_key.Pass()) {}
+
+OwnerKey::~OwnerKey() {}
+
+DeviceSettingsService::Observer::~Observer() {}
+
+DeviceSettingsService::DeviceSettingsService()
+ : session_manager_client_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+ store_status_(STORE_SUCCESS) {}
+
+DeviceSettingsService::~DeviceSettingsService() {
+ DCHECK(pending_operations_.empty());
+}
+
+// static
+DeviceSettingsService* DeviceSettingsService::Get() {
+ return g_device_settings_service.Pointer();
+}
+
+void DeviceSettingsService::Initialize(
+ SessionManagerClient* session_manager_client,
+ scoped_refptr<OwnerKeyUtil> owner_key_util) {
+ DCHECK(session_manager_client);
+ DCHECK(owner_key_util.get());
+ DCHECK(!session_manager_client_);
+ DCHECK(!owner_key_util_.get());
+
+ session_manager_client_ = session_manager_client;
+ owner_key_util_ = owner_key_util;
+
+ session_manager_client_->AddObserver(this);
+
+ StartNextOperation();
+}
+
+void DeviceSettingsService::Shutdown() {
+ STLDeleteContainerPointers(pending_operations_.begin(),
+ pending_operations_.end());
+ pending_operations_.clear();
+
+ session_manager_client_->RemoveObserver(this);
+ session_manager_client_ = NULL;
+ owner_key_util_ = NULL;
+}
+
+scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
+ return owner_key_;
+}
+
+void DeviceSettingsService::Load() {
+ EnqueueLoad(false);
+}
+
+void DeviceSettingsService::SignAndStore(
+ scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
+ const base::Closure& callback) {
+ Enqueue(
+ new SignAndStoreSettingsOperation(
+ base::Bind(&DeviceSettingsService::HandleCompletedOperation,
+ weak_factory_.GetWeakPtr(),
+ callback),
+ new_settings.Pass(),
+ username_));
+}
+
+void DeviceSettingsService::Store(const std::string& policy_blob,
+ const base::Closure& callback) {
+ Enqueue(
+ new StoreSettingsOperation(
+ base::Bind(&DeviceSettingsService::HandleCompletedOperation,
+ weak_factory_.GetWeakPtr(),
+ callback),
+ policy_blob));
+}
+
+DeviceSettingsService::OwnershipStatus
+ DeviceSettingsService::GetOwnershipStatus() {
+ if (owner_key_.get())
+ return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
+
+ return OWNERSHIP_UNKNOWN;
+}
+
+void DeviceSettingsService::GetOwnershipStatusAsync(
+ const OwnershipStatusCallback& callback) {
+ if (owner_key_.get()) {
+ // If there is a key, report status immediately.
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback,
+ owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE,
+ owner_key_->private_key() != NULL));
+ } else {
+ // If the key hasn't been loaded yet, enqueue the callback to be fired when
+ // the next SessionManagerOperation completes. If no operation is pending,
+ // start a load operation to fetch the key and report the result.
+ pending_ownership_status_callbacks_.push_back(callback);
+ if (pending_operations_.empty())
+ EnqueueLoad(false);
+ }
+}
+
+bool DeviceSettingsService::HasPrivateOwnerKey() {
+ return owner_key_.get() && owner_key_->private_key();
+}
+
+void DeviceSettingsService::SetUsername(const std::string& username) {
+ username_ = username;
+
+ // The private key may have become available, so force a key reload.
+ owner_key_ = NULL;
+ EnsureReload(true);
+}
+
+const std::string& DeviceSettingsService::GetUsername() const {
+ return username_;
+}
+
+void DeviceSettingsService::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void DeviceSettingsService::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void DeviceSettingsService::OwnerKeySet(bool success) {
+ if (!success) {
+ LOG(ERROR) << "Owner key change failed.";
+ return;
+ }
+
+ owner_key_ = NULL;
+ EnsureReload(true);
+}
+
+void DeviceSettingsService::PropertyChangeComplete(bool success) {
+ if (!success) {
+ LOG(ERROR) << "Policy update failed.";
+ return;
+ }
+
+ EnsureReload(false);
+}
+
+void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
+ pending_operations_.push_back(operation);
+ if (pending_operations_.front() == operation)
+ StartNextOperation();
+}
+
+void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
+ SessionManagerOperation* operation =
+ new LoadSettingsOperation(
+ base::Bind(&DeviceSettingsService::HandleCompletedOperation,
+ weak_factory_.GetWeakPtr(),
+ base::Closure()));
+ operation->set_force_key_load(force_key_load);
+ Enqueue(operation);
+}
+
+void DeviceSettingsService::EnsureReload(bool force_key_load) {
+ if (!pending_operations_.empty())
+ pending_operations_.front()->RestartLoad(force_key_load);
+ else
+ EnqueueLoad(force_key_load);
+}
+
+void DeviceSettingsService::StartNextOperation() {
+ if (!pending_operations_.empty() &&
+ session_manager_client_ &&
+ owner_key_util_.get()) {
+ pending_operations_.front()->Start(session_manager_client_,
+ owner_key_util_, owner_key_);
+ }
+}
+
+void DeviceSettingsService::HandleCompletedOperation(
+ const base::Closure& callback,
+ SessionManagerOperation* operation,
+ Status status) {
+ DCHECK_EQ(operation, pending_operations_.front());
+ store_status_ = status;
+
+ OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
+ bool is_owner = false;
+ scoped_refptr<OwnerKey> new_key(operation->owner_key());
+ if (new_key.get()) {
+ ownership_status =
+ new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
+ is_owner = (new_key->private_key() != NULL);
+ } else {
+ NOTREACHED() << "Failed to determine key status.";
+ }
+
+ bool new_owner_key = false;
+ if (owner_key_.get() != new_key.get()) {
+ owner_key_ = new_key;
+ new_owner_key = true;
+ }
+
+ if (status == STORE_SUCCESS) {
+ policy_data_ = operation->policy_data().Pass();
+ device_settings_ = operation->device_settings().Pass();
+ } else if (status != STORE_KEY_UNAVAILABLE) {
+ LOG(ERROR) << "Session manager operation failed: " << status;
+ }
+
+ if (new_owner_key) {
+ FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
+ content::Source<DeviceSettingsService>(this),
+ content::NotificationService::NoDetails());
+ }
+
+ FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
+
+ std::vector<OwnershipStatusCallback> callbacks;
+ callbacks.swap(pending_ownership_status_callbacks_);
+ for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
+ iter != callbacks.end(); ++iter) {
+ iter->Run(ownership_status, is_owner);
+ }
+
+ // The completion callback happens after the notification so clients can
+ // filter self-triggered updates.
+ if (!callback.is_null())
+ callback.Run();
+
+ // 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();
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698