diff options
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', |