diff options
author | cmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-03 21:40:10 +0000 |
---|---|---|
committer | cmasone@google.com <cmasone@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-03 21:40:10 +0000 |
commit | 32352d183d26f0c96014c3a22d8beb2d3e91e3fd (patch) | |
tree | 46350d8c44156f636cc6f11ce87edfbd9151178b /chrome | |
parent | 43d259d2f2653c30652d09856bcbfbcfdf639f2e (diff) | |
download | chromium_src-32352d183d26f0c96014c3a22d8beb2d3e91e3fd.zip chromium_src-32352d183d26f0c96014c3a22d8beb2d3e91e3fd.tar.gz chromium_src-32352d183d26f0c96014c3a22d8beb2d3e91e3fd.tar.bz2 |
[CHrome OS] Provides nicer abstractions around ownership API
There are two categories of operations that can be performed on the Chrome OS owner-signed settings store:
1) doing stuff to the whitelist (adding/removing/checking)
2) Storing/Retrieving arbitrary name=value pairs
Unfortunately, it is currently a limitation that only one of a each category can be in-flight at a time. I've filed an issue on me to remove that restriction.
The pattern of use here is that the caller instantiates some subclass of SignedSettings by calling one of the create methods. Then, call Execute() on this object from the UI thread. It'll go off and do work (on the FILE thread and over DBus), and then call the appropriate method of the Delegate you passed in -- again, on the UI thread.
BUG=chromium-os:4488
TEST=Unit tests
Review URL: http://codereview.chromium.org/3345002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58546 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/chromeos/login/signed_settings.cc | 308 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/signed_settings.h | 87 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/signed_settings_unittest.cc | 291 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
5 files changed, 689 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/login/signed_settings.cc b/chrome/browser/chromeos/login/signed_settings.cc new file mode 100644 index 0000000..03961c3 --- /dev/null +++ b/chrome/browser/chromeos/login/signed_settings.cc @@ -0,0 +1,308 @@ +// Copyright (c) 2010 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/login/signed_settings.h" + +#include <string> +#include <vector> + +#include "base/ref_counted.h" +#include "base/stringprintf.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/cros/login_library.h" +#include "chrome/browser/chromeos/login/ownership_service.h" + +namespace chromeos { + +SignedSettings::SignedSettings() + : service_(OwnershipService::GetSharedInstance()) { +} + +SignedSettings::~SignedSettings() {} + +class CheckWhitelistOp : public SignedSettings { + public: + CheckWhitelistOp(const std::string& email, + SignedSettings::Delegate<bool>* d); + virtual ~CheckWhitelistOp(); + bool Execute(); + // Implementation of OwnerManager::Delegate::OnKeyOpComplete() + void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload); + + private: + const std::string email_; + SignedSettings::Delegate<bool>* d_; +}; + +class WhitelistOp : public SignedSettings, + public LoginLibrary::Delegate<bool> { + public: + WhitelistOp(const std::string& email, + bool add_to_whitelist, + SignedSettings::Delegate<bool>* d); + virtual ~WhitelistOp(); + bool Execute(); + // Implementation of OwnerManager::Delegate::OnKeyOpComplete() + void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload); + // Implementation of LoginLibrary::Delegate::Run() + void Run(bool value); + + private: + bool InitiateWhitelistOp(const std::vector<uint8>& signature); + + const std::string email_; + const bool add_to_whitelist_; + SignedSettings::Delegate<bool>* d_; +}; + +class StorePropertyOp : public SignedSettings, + public LoginLibrary::Delegate<bool> { + public: + StorePropertyOp(const std::string& name, + const std::string& value, + SignedSettings::Delegate<bool>* d); + virtual ~StorePropertyOp(); + bool Execute(); + // Implementation of OwnerManager::Delegate::OnKeyOpComplete() + void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload); + // Implementation of LoginLibrary::Delegate::Run() + void Run(bool value); + + private: + std::string name_; + std::string value_; + SignedSettings::Delegate<bool>* d_; +}; + +class RetrievePropertyOp : public SignedSettings { + public: + RetrievePropertyOp(const std::string& name, + SignedSettings::Delegate<std::string>* d); + virtual ~RetrievePropertyOp(); + bool Execute(); + // Implementation of OwnerManager::Delegate::OnKeyOpComplete() + void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload); + + private: + std::string name_; + std::string value_; + SignedSettings::Delegate<std::string>* d_; +}; + +// static +SignedSettings* SignedSettings::CreateCheckWhitelistOp( + const std::string& email, + SignedSettings::Delegate<bool>* d) { + return new CheckWhitelistOp(email, d); +} + +// static +SignedSettings* SignedSettings::CreateWhitelistOp( + const std::string& email, + bool add_to_whitelist, + SignedSettings::Delegate<bool>* d) { + return new WhitelistOp(email, add_to_whitelist, d); +} + +// static +SignedSettings* SignedSettings::CreateStorePropertyOp( + const std::string& name, + const std::string& value, + SignedSettings::Delegate<bool>* d) { + return new StorePropertyOp(name, value, d); +} + +// static +SignedSettings* SignedSettings::CreateRetrievePropertyOp( + const std::string& name, + SignedSettings::Delegate<std::string>* d) { + return new RetrievePropertyOp(name, d); +} + +CheckWhitelistOp::CheckWhitelistOp(const std::string& email, + SignedSettings::Delegate<bool>* d) + : email_(email), + d_(d) { +} + +CheckWhitelistOp::~CheckWhitelistOp() {} + +bool CheckWhitelistOp::Execute() { + CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); + std::vector<uint8> sig; + if (!CrosLibrary::Get()->GetLoginLibrary()->CheckWhitelist(email_, &sig)) + return false; + + // Posts a task to the FILE thread to verify |sig|. + service_->StartVerifyAttempt(email_, sig, this); + return true; +} + +void CheckWhitelistOp::OnKeyOpComplete( + const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload) { + // Ensure we're on the UI thread, due to the need to send DBus traffic. + if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &CheckWhitelistOp::OnKeyOpComplete, + return_code, payload)); + return; + } + if (return_code == OwnerManager::SUCCESS) + d_->OnSettingsOpSucceeded(true); + else + d_->OnSettingsOpFailed(); +} + +WhitelistOp::WhitelistOp(const std::string& email, + bool add_to_whitelist, + SignedSettings::Delegate<bool>* d) + : email_(email), + add_to_whitelist_(add_to_whitelist), + d_(d) { +} + +WhitelistOp::~WhitelistOp() {} + +bool WhitelistOp::Execute() { + // Posts a task to the FILE thread to sign |email_|. + service_->StartSigningAttempt(email_, this); + return true; +} + +void WhitelistOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload) { + // Ensure we're on the UI thread, due to the need to send DBus traffic. + if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &WhitelistOp::OnKeyOpComplete, + return_code, payload)); + return; + } + // Now, sure we're on the UI thread. + bool success = false; + if (return_code == OwnerManager::SUCCESS) { + // Run() will be called when this is done. + success = InitiateWhitelistOp(payload); + } + if (!success) + d_->OnSettingsOpFailed(); +} + +void WhitelistOp::Run(bool value) { + if (value) + d_->OnSettingsOpSucceeded(value); + else + d_->OnSettingsOpFailed(); +} + +bool WhitelistOp::InitiateWhitelistOp(const std::vector<uint8>& signature) { + LoginLibrary* library = CrosLibrary::Get()->GetLoginLibrary(); + if (add_to_whitelist_) + return library->WhitelistAsync(email_, signature, this); + return library->UnwhitelistAsync(email_, signature, this); +} + +StorePropertyOp::StorePropertyOp(const std::string& name, + const std::string& value, + SignedSettings::Delegate<bool>* d) + : name_(name), + value_(value), + d_(d) { +} + +StorePropertyOp::~StorePropertyOp() {} + +bool StorePropertyOp::Execute() { + // Posts a task to the FILE thread to sign |name_|=|value_|. + std::string to_sign = base::StringPrintf("%s=%s", + name_.c_str(), + value_.c_str()); + service_->StartSigningAttempt(to_sign, this); + return true; +} + +void StorePropertyOp::OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload) { + // Ensure we're on the UI thread, due to the need to send DBus traffic. + if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &StorePropertyOp::OnKeyOpComplete, + return_code, payload)); + return; + } + // Now, sure we're on the UI thread. + bool success = false; + if (return_code == OwnerManager::SUCCESS) { + // Run() will be called when this is done. + success = CrosLibrary::Get()->GetLoginLibrary()->StorePropertyAsync(name_, + value_, + payload, + this); + } + if (!success) + d_->OnSettingsOpFailed(); +} + +void StorePropertyOp::Run(bool value) { + if (value) + d_->OnSettingsOpSucceeded(value); + else + d_->OnSettingsOpFailed(); +} + +RetrievePropertyOp::RetrievePropertyOp(const std::string& name, + SignedSettings::Delegate<std::string>* d) + : name_(name), + d_(d) { +} + +RetrievePropertyOp::~RetrievePropertyOp() {} + +bool RetrievePropertyOp::Execute() { + CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); + std::vector<uint8> sig; + if (!CrosLibrary::Get()->GetLoginLibrary()->RetrieveProperty(name_, + &value_, + &sig)) { + return false; + } + std::string to_verify = base::StringPrintf("%s=%s", + name_.c_str(), + value_.c_str()); + // Posts a task to the FILE thread to verify |sig|. + service_->StartVerifyAttempt(to_verify, sig, this); + return true; +} + +void RetrievePropertyOp::OnKeyOpComplete( + const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload) { + if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { + ChromeThread::PostTask( + ChromeThread::UI, FROM_HERE, + NewRunnableMethod(this, + &RetrievePropertyOp::OnKeyOpComplete, + return_code, payload)); + return; + } + // Now, sure we're on the UI thread. + if (return_code == OwnerManager::SUCCESS) + d_->OnSettingsOpSucceeded(value_); + else + d_->OnSettingsOpFailed(); +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/login/signed_settings.h b/chrome/browser/chromeos/login/signed_settings.h new file mode 100644 index 0000000..d2c1049 --- /dev/null +++ b/chrome/browser/chromeos/login/signed_settings.h @@ -0,0 +1,87 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SIGNED_SETTINGS_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SIGNED_SETTINGS_H_ +#pragma once + +#include <string> + +#include "base/ref_counted.h" +#include "chrome/browser/chromeos/login/owner_manager.h" + +// There are two categories of operations that can be performed on the +// Chrome OS owner-signed settings store: +// 1) doing stuff to the whitelist (adding/removing/checking) +// 2) Storing/Retrieving arbitrary name=value pairs +// +// Unfortunately, it is currently a limitation that only one of each +// category can be in-flight at a time. You can be doing exactly one thing +// to the whitelist, and exactly one thing to the property store at a time. +// I've filed an issue on me to remove that restriction. +// http://code.google.com/p/chromium-os/issues/detail?id=6415 + +// The pattern of use here is that the caller instantiates some +// subclass of SignedSettings by calling one of the create +// methods. Then, call Execute() on this object from the UI +// thread. It'll go off and do work (on the FILE thread and over DBus), +// and then call the appropriate method of the Delegate you passed in +// -- again, on the UI thread. + +namespace chromeos { +class OwnershipService; + +class SignedSettings : public base::RefCountedThreadSafe<SignedSettings>, + public OwnerManager::Delegate { + public: + template <class T> + class Delegate { + public: + // These methods will be called on the UI thread. + virtual void OnSettingsOpSucceeded(T value) = 0; + virtual void OnSettingsOpFailed() = 0; + }; + + SignedSettings(); + virtual ~SignedSettings(); + + // These are both "whitelist" operations, and only one instance of + // one type can be in flight at a time. + static SignedSettings* CreateCheckWhitelistOp( + const std::string& email, + SignedSettings::Delegate<bool>* d); + + static SignedSettings* CreateWhitelistOp(const std::string& email, + bool add_to_whitelist, + SignedSettings::Delegate<bool>* d); + + // These are both "property" operations, and only one instance of + // one type can be in flight at a time. + static SignedSettings* CreateStorePropertyOp( + const std::string& name, + const std::string& value, + SignedSettings::Delegate<bool>* d); + + static SignedSettings* CreateRetrievePropertyOp( + const std::string& name, + SignedSettings::Delegate<std::string>* d); + + virtual bool Execute() = 0; + + // Implementation of OwnerManager::Delegate::OnKeyOpComplete() + void OnKeyOpComplete(const OwnerManager::KeyOpCode return_code, + const std::vector<uint8>& payload) = 0; + + protected: + OwnershipService* service_; + + private: + friend class SignedSettingsTest; + + void set_service(OwnershipService* service) { service_ = service; } +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SIGNED_SETTINGS_H_ diff --git a/chrome/browser/chromeos/login/signed_settings_unittest.cc b/chrome/browser/chromeos/login/signed_settings_unittest.cc new file mode 100644 index 0000000..f56a393 --- /dev/null +++ b/chrome/browser/chromeos/login/signed_settings_unittest.cc @@ -0,0 +1,291 @@ +// Copyright (c) 2010 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/login/signed_settings.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "base/nss_util.h" +#include "base/scoped_temp_dir.h" +#include "base/stringprintf.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/chromeos/login/mock_owner_key_utils.h" +#include "chrome/browser/chromeos/login/ownership_service.h" +#include "chrome/browser/chromeos/login/owner_manager_unittest.h" +#include "chrome/browser/chromeos/cros/cros_library.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::Invoke; +using ::testing::Return; +using ::testing::_; + +namespace chromeos { + +namespace { +template <class T> +class DummyDelegate : public SignedSettings::Delegate<T> { + public: + explicit DummyDelegate(T to_expect) + : expect_success_(false), + expected_(to_expect), + run_(false) {} + virtual ~DummyDelegate() { EXPECT_TRUE(run_); } + virtual void OnSettingsOpSucceeded(T value) { + run_ = true; + EXPECT_TRUE(expect_success_); + EXPECT_EQ(expected_, value); + } + virtual void OnSettingsOpFailed() { + run_ = true; + EXPECT_FALSE(expect_success_); + } + virtual void expect_success() { expect_success_ = true; } + bool expect_success_; + T expected_; + bool run_; +}; + +class Quitter : public DummyDelegate<bool> { + public: + explicit Quitter(bool to_expect) : DummyDelegate<bool>(to_expect) {} + virtual ~Quitter() {} + void OnSettingsOpSucceeded(bool value) { + DummyDelegate<bool>::OnSettingsOpSucceeded(value); + MessageLoop::current()->Quit(); + } + void OnSettingsOpFailed() { + DummyDelegate<bool>::OnSettingsOpFailed(); + MessageLoop::current()->Quit(); + } +}; +} // anonymous namespace + +class MockService : public OwnershipService { + public: + MOCK_METHOD0(IsAlreadyOwned, bool(void)); + MOCK_METHOD0(StartLoadOwnerKeyAttempt, bool(void)); + MOCK_METHOD0(StartTakeOwnershipAttempt, bool(void)); + MOCK_METHOD2(StartSigningAttempt, void(const std::string&, + OwnerManager::Delegate*)); + MOCK_METHOD3(StartVerifyAttempt, void(const std::string&, + const std::vector<uint8>&, + OwnerManager::Delegate*)); + MOCK_METHOD0(CurrentUserIsOwner, bool(void)); +}; + +class SignedSettingsTest : public ::testing::Test { + public: + SignedSettingsTest() + : fake_email_("fakey"), + fake_prop_("prop_name"), + fake_value_("stub"), + message_loop_(MessageLoop::TYPE_UI), + ui_thread_(ChromeThread::UI, &message_loop_), + file_thread_(ChromeThread::FILE), + mock_(new MockKeyUtils), + injector_(mock_) /* injector_ takes ownership of mock_ */ { + } + + virtual ~SignedSettingsTest() {} + + virtual void SetUp() { + chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl(); + file_thread_.Start(); + } + + virtual void TearDown() { + OwnerKeyUtils::set_factory(NULL); + } + + void mock_service(SignedSettings* s, MockService* m) { + s->set_service(m); + } + + void FailingCheckWhitelist(const OwnerManager::KeyOpCode return_code) { + DummyDelegate<bool> d(false); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateCheckWhitelistOp(fake_email_, &d)); + + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartVerifyAttempt(fake_email_, _, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(return_code, std::vector<uint8>()); + } + + void FailingWhitelistOp(const OwnerManager::KeyOpCode return_code) { + DummyDelegate<bool> d(false); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateWhitelistOp(fake_email_, true, &d)); + + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(return_code, std::vector<uint8>()); + } + + void FailingStorePropertyOp(const OwnerManager::KeyOpCode return_code) { + DummyDelegate<bool> d(false); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateStorePropertyOp(fake_prop_, fake_value_, &d)); + std::string to_sign = base::StringPrintf("%s=%s", + fake_prop_.c_str(), + fake_value_.c_str()); + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartSigningAttempt(to_sign, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(return_code, std::vector<uint8>()); + } + + void FailingRetrievePropertyOp(const OwnerManager::KeyOpCode return_code) { + DummyDelegate<std::string> d(fake_value_); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateRetrievePropertyOp(fake_prop_, &d)); + std::string to_verify = base::StringPrintf("%s=%s", + fake_prop_.c_str(), + fake_value_.c_str()); + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartVerifyAttempt(to_verify, _, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(return_code, std::vector<uint8>()); + } + + const std::string fake_email_; + const std::string fake_prop_; + const std::string fake_value_; + MockService m_; + + ScopedTempDir tmpdir_; + FilePath tmpfile_; + + MessageLoop message_loop_; + ChromeThread ui_thread_; + ChromeThread file_thread_; + + std::vector<uint8> fake_public_key_; + scoped_ptr<RSAPrivateKey> fake_private_key_; + + MockKeyUtils* mock_; + MockInjector injector_; + +}; + +TEST_F(SignedSettingsTest, CheckWhitelist) { + DummyDelegate<bool> d(true); + d.expect_success(); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateCheckWhitelistOp(fake_email_, &d)); + + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartVerifyAttempt(fake_email_, _, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>()); +} + +TEST_F(SignedSettingsTest, CheckWhitelistNoKey) { + FailingCheckWhitelist(OwnerManager::KEY_UNAVAILABLE); +} + +TEST_F(SignedSettingsTest, CheckWhitelistFailed) { + FailingCheckWhitelist(OwnerManager::OPERATION_FAILED); +} + +TEST_F(SignedSettingsTest, Whitelist) { + Quitter d(true); + d.expect_success(); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateWhitelistOp(fake_email_, true, &d)); + + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>()); + message_loop_.Run(); +} + +TEST_F(SignedSettingsTest, Unwhitelist) { + Quitter d(true); + d.expect_success(); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateWhitelistOp(fake_email_, false, &d)); + + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartSigningAttempt(fake_email_, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>()); + message_loop_.Run(); +} + +TEST_F(SignedSettingsTest, WhitelistNoKey) { + FailingWhitelistOp(OwnerManager::KEY_UNAVAILABLE); +} + +TEST_F(SignedSettingsTest, WhitelistFailed) { + FailingWhitelistOp(OwnerManager::OPERATION_FAILED); +} + +TEST_F(SignedSettingsTest, StoreProperty) { + Quitter d(true); + d.expect_success(); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateStorePropertyOp(fake_prop_, fake_value_, &d)); + std::string to_sign = base::StringPrintf("%s=%s", + fake_prop_.c_str(), + fake_value_.c_str()); + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartSigningAttempt(to_sign, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>()); + message_loop_.Run(); +} + +TEST_F(SignedSettingsTest, StorePropertyNoKey) { + FailingStorePropertyOp(OwnerManager::KEY_UNAVAILABLE); +} + +TEST_F(SignedSettingsTest, StorePropertyFailed) { + FailingStorePropertyOp(OwnerManager::OPERATION_FAILED); +} + +TEST_F(SignedSettingsTest, RetrieveProperty) { + DummyDelegate<std::string> d(fake_value_); + d.expect_success(); + scoped_refptr<SignedSettings> s( + SignedSettings::CreateRetrievePropertyOp(fake_prop_, &d)); + std::string to_verify = base::StringPrintf("%s=%s", + fake_prop_.c_str(), + fake_value_.c_str()); + mock_service(s.get(), &m_); + EXPECT_CALL(m_, StartVerifyAttempt(to_verify, _, _)) + .Times(1); + + EXPECT_TRUE(s->Execute()); + s->OnKeyOpComplete(OwnerManager::SUCCESS, std::vector<uint8>()); +} + +TEST_F(SignedSettingsTest, RetrievePropertyNoKey) { + FailingRetrievePropertyOp(OwnerManager::KEY_UNAVAILABLE); +} + +TEST_F(SignedSettingsTest, RetrievePropertyFailed) { + FailingRetrievePropertyOp(OwnerManager::OPERATION_FAILED); +} + +} // namespace chromeos diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 8e92f6f..9157a84 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -543,6 +543,8 @@ 'browser/chromeos/login/screen_lock_view.cc', 'browser/chromeos/login/screen_lock_view.h', 'browser/chromeos/login/screen_observer.h', + 'browser/chromeos/login/signed_settings.cc', + 'browser/chromeos/login/signed_settings.h', 'browser/chromeos/login/update_screen.cc', 'browser/chromeos/login/update_screen.h', 'browser/chromeos/login/update_view.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index cd751e2..45ebc5d 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -870,6 +870,7 @@ 'browser/chromeos/login/owner_key_utils_unittest.cc', 'browser/chromeos/login/owner_manager_unittest.cc', 'browser/chromeos/login/ownership_service_unittest.cc', + 'browser/chromeos/login/signed_settings_unittest.cc', 'browser/chromeos/notifications/desktop_notifications_unittest.cc', 'browser/chromeos/offline/offline_load_page_unittest.cc', 'browser/chromeos/options/language_config_model_unittest.cc', |