summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/settings/ownership_service.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/chromeos/settings/ownership_service.cc')
-rw-r--r--chrome/browser/chromeos/settings/ownership_service.cc259
1 files changed, 259 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/settings/ownership_service.cc b/chrome/browser/chromeos/settings/ownership_service.cc
new file mode 100644
index 0000000..6343fa3
--- /dev/null
+++ b/chrome/browser/chromeos/settings/ownership_service.cc
@@ -0,0 +1,259 @@
+// 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/ownership_service.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+namespace {
+
+typedef std::pair<OwnershipService::Status, bool> OwnershipStatusReturnType;
+
+// Makes the check for ownership on the FILE thread and stores the result in the
+// provided pointers.
+OwnershipStatusReturnType CheckStatusOnFileThread() {
+ bool current_user_is_owner;
+ OwnershipService::Status status;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ status = OwnershipService::GetSharedInstance()->IsAlreadyOwned() ?
+ OwnershipService::OWNERSHIP_TAKEN : OwnershipService::OWNERSHIP_NONE;
+ current_user_is_owner =
+ OwnershipService::GetSharedInstance()->IsCurrentUserOwner();
+ return OwnershipStatusReturnType(status, current_user_is_owner);
+}
+
+} // namespace
+
+static base::LazyInstance<OwnershipService> g_ownership_service =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+OwnershipService* OwnershipService::GetSharedInstance() {
+ return g_ownership_service.Pointer();
+}
+
+OwnershipService::OwnershipService()
+ : manager_(new OwnerManager),
+ utils_(OwnerKeyUtils::Create()),
+ ownership_status_(OWNERSHIP_UNKNOWN),
+ force_ownership_(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kStubCrosSettings)) {
+ notification_registrar_.Add(
+ this,
+ chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
+ content::NotificationService::AllSources());
+}
+
+OwnershipService::~OwnershipService() {}
+
+void OwnershipService::Prewarm() {
+ // Note that we cannot prewarm in constructor because in current codebase
+ // object is created before spawning threads.
+ if (g_ownership_service == this) {
+ // Start getting ownership status.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&OwnershipService::FetchStatus, base::Unretained(this)));
+ } else {
+ // This can happen only for particular test: OwnershipServiceTest. It uses
+ // mocks and for that uses OwnershipService not as a regular singleton but
+ // as a resurrecting object. This behaviour conflicts with
+ // base::Unretained(). So avoid posting task in those circumstances
+ // in order to avoid accessing already deleted object.
+ }
+}
+
+bool OwnershipService::IsAlreadyOwned() {
+ return file_util::PathExists(utils_->GetOwnerKeyFilePath());
+}
+
+OwnershipService::Status OwnershipService::GetStatus(bool blocking) {
+ if (force_ownership_)
+ return OWNERSHIP_TAKEN;
+ Status status = OWNERSHIP_UNKNOWN;
+ bool is_owned = false;
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ ownership_status_lock_.Acquire();
+ status = ownership_status_;
+ ownership_status_lock_.Release();
+ if (status != OWNERSHIP_UNKNOWN || !blocking)
+ return status;
+ // Under common usage there is very short lapse of time when ownership
+ // status is still unknown after constructing OwnershipService.
+ LOG(ERROR) << "Blocking on UI thread in OwnershipService::GetStatus";
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ is_owned = IsAlreadyOwned();
+ } else {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ is_owned = IsAlreadyOwned();
+ }
+ status = is_owned ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
+ SetStatus(status);
+ return status;
+}
+
+void OwnershipService::StartLoadOwnerKeyAttempt() {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&TryLoadOwnerKeyAttempt, base::Unretained(this)));
+}
+
+void OwnershipService::StartUpdateOwnerKey(const std::vector<uint8>& new_key,
+ OwnerManager::KeyUpdateDelegate* d) {
+ BrowserThread::ID thread_id;
+ if (!BrowserThread::GetCurrentThreadIdentifier(&thread_id))
+ thread_id = BrowserThread::UI;
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&OwnershipService::UpdateOwnerKey, base::Unretained(this),
+ thread_id, new_key, d));
+ return;
+}
+
+void OwnershipService::StartSigningAttempt(const std::string& data,
+ OwnerManager::Delegate* d) {
+ BrowserThread::ID thread_id;
+ if (!BrowserThread::GetCurrentThreadIdentifier(&thread_id))
+ thread_id = BrowserThread::UI;
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&OwnershipService::TrySigningAttempt, base::Unretained(this),
+ thread_id, data, d));
+ return;
+}
+
+void OwnershipService::StartVerifyAttempt(const std::string& data,
+ const std::vector<uint8>& signature,
+ OwnerManager::Delegate* d) {
+ BrowserThread::ID thread_id;
+ if (!BrowserThread::GetCurrentThreadIdentifier(&thread_id))
+ thread_id = BrowserThread::UI;
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&OwnershipService::TryVerifyAttempt, base::Unretained(this),
+ thread_id, data, signature, d));
+ return;
+}
+
+void OwnershipService::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
+ SetStatus(OWNERSHIP_TAKEN);
+ notification_registrar_.RemoveAll();
+ } else {
+ NOTREACHED();
+ }
+}
+
+bool OwnershipService::IsCurrentUserOwner() {
+ if (force_ownership_)
+ return true;
+ // If this user has the private key associated with the owner's
+ // public key, this user is the owner.
+ return IsAlreadyOwned() && manager_->EnsurePrivateKey();
+}
+
+void OwnershipService::GetStatusAsync(const Callback& callback) {
+ PostTaskAndReplyWithResult(
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
+ FROM_HERE,
+ base::Bind(&CheckStatusOnFileThread),
+ base::Bind(&OwnershipService::ReturnStatus,
+ callback));
+}
+
+
+// static
+void OwnershipService::UpdateOwnerKey(OwnershipService* service,
+ const BrowserThread::ID thread_id,
+ const std::vector<uint8>& new_key,
+ OwnerManager::KeyUpdateDelegate* d) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ service->manager()->UpdateOwnerKey(thread_id, new_key, d);
+}
+
+// static
+void OwnershipService::TryLoadOwnerKeyAttempt(OwnershipService* service) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ if (!service->IsAlreadyOwned()) {
+ VLOG(1) << "Device not yet owned";
+ return;
+ }
+ service->manager()->LoadOwnerKey();
+}
+
+// static
+void OwnershipService::TrySigningAttempt(OwnershipService* service,
+ const BrowserThread::ID thread_id,
+ const std::string& data,
+ OwnerManager::Delegate* d) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ if (!service->IsAlreadyOwned()) {
+ LOG(ERROR) << "Device not yet owned";
+ BrowserThread::PostTask(
+ thread_id, FROM_HERE,
+ base::Bind(&OwnershipService::FailAttempt, d));
+ return;
+ }
+ service->manager()->Sign(thread_id, data, d);
+}
+
+// static
+void OwnershipService::TryVerifyAttempt(OwnershipService* service,
+ const BrowserThread::ID thread_id,
+ const std::string& data,
+ const std::vector<uint8>& signature,
+ OwnerManager::Delegate* d) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ if (!service->IsAlreadyOwned()) {
+ LOG(ERROR) << "Device not yet owned";
+ BrowserThread::PostTask(
+ thread_id, FROM_HERE,
+ base::Bind(&OwnershipService::FailAttempt, d));
+ return;
+ }
+ service->manager()->Verify(thread_id, data, signature, d);
+}
+
+// static
+void OwnershipService::FailAttempt(OwnerManager::Delegate* d) {
+ d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
+}
+
+void OwnershipService::FetchStatus() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ Status status = IsAlreadyOwned() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
+ SetStatus(status);
+}
+
+void OwnershipService::SetStatus(Status new_status) {
+ DCHECK(new_status == OWNERSHIP_TAKEN || new_status == OWNERSHIP_NONE);
+ base::AutoLock lk(ownership_status_lock_);
+ ownership_status_ = new_status;
+}
+
+// static
+void OwnershipService::ReturnStatus(const Callback& callback,
+ OwnershipStatusReturnType status) {
+ callback.Run(status.first, status.second);
+}
+
+} // namespace chromeos