diff options
author | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-23 16:26:35 +0000 |
---|---|---|
committer | mnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-23 16:26:35 +0000 |
commit | 0f456542ea264dfadc276f51567933af10402064 (patch) | |
tree | d8309bb83023498117a1e181dc04e9cf8f89b10d | |
parent | a3bd13145d57525d67272a6661c3c6f87b265f7a (diff) | |
download | chromium_src-0f456542ea264dfadc276f51567933af10402064.zip chromium_src-0f456542ea264dfadc276f51567933af10402064.tar.gz chromium_src-0f456542ea264dfadc276f51567933af10402064.tar.bz2 |
Implement DeviceLocalAccountPolicyService.
This is the main switching central for device-local accounts on the
Chrome side and takes care of brokering access to the policy blobs kept
by session_manager.
BUG=chromium:152937
TEST=unit tests
TBR=ben@chromium.org
Review URL: https://chromiumcodereview.appspot.com/11377137
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169343 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/policy/browser_policy_connector.cc | 12 | ||||
-rw-r--r-- | chrome/browser/policy/browser_policy_connector.h | 3 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_constants.cc | 1 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_constants.h | 1 | ||||
-rw-r--r-- | chrome/browser/policy/device_local_account_policy_service.cc | 251 | ||||
-rw-r--r-- | chrome/browser/policy/device_local_account_policy_service.h | 184 | ||||
-rw-r--r-- | chrome/browser/policy/device_local_account_policy_service_unittest.cc | 221 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 60 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 17 |
9 files changed, 716 insertions, 34 deletions
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc index bad98e5..2cb3c6f 100644 --- a/chrome/browser/policy/browser_policy_connector.cc +++ b/chrome/browser/policy/browser_policy_connector.cc @@ -59,6 +59,7 @@ #include "chrome/browser/policy/cros_user_policy_cache.h" #include "chrome/browser/policy/device_cloud_policy_manager_chromeos.h" #include "chrome/browser/policy/device_cloud_policy_store_chromeos.h" +#include "chrome/browser/policy/device_local_account_policy_service.h" #include "chrome/browser/policy/device_policy_cache.h" #include "chrome/browser/policy/network_configuration_updater.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -127,6 +128,10 @@ void BrowserPolicyConnector::Init() { new DeviceCloudPolicyManagerChromeOS( device_cloud_policy_store.Pass(), install_attributes_.get())); + device_local_account_policy_service_.reset( + new DeviceLocalAccountPolicyService( + chromeos::DBusThreadManager::Get()->GetSessionManagerClient(), + chromeos::DeviceSettingsService::Get())); } else { cloud_provider_.reset(new CloudPolicyProvider(this)); } @@ -171,6 +176,8 @@ void BrowserPolicyConnector::Shutdown() { if (device_cloud_policy_manager_) device_cloud_policy_manager_->Shutdown(); + if (device_local_account_policy_service_) + device_local_account_policy_service_->Shutdown(); #endif // Shutdown user cloud policy. @@ -606,6 +613,11 @@ void BrowserPolicyConnector::CompleteInitialization() { device_management_service_.get()); } + if (device_local_account_policy_service_.get()) { + device_local_account_policy_service_->Initialize( + device_management_service_.get()); + } + SetTimezoneIfPolicyAvailable(); #endif diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h index c8b5834..df350fc 100644 --- a/chrome/browser/policy/browser_policy_connector.h +++ b/chrome/browser/policy/browser_policy_connector.h @@ -28,6 +28,7 @@ class CloudPolicyProvider; class CloudPolicySubsystem; class ConfigurationPolicyProvider; class DeviceCloudPolicyManagerChromeOS; +class DeviceLocalAccountPolicyService; class DeviceManagementService; class NetworkConfigurationUpdater; class PolicyService; @@ -232,6 +233,8 @@ class BrowserPolicyConnector : public content::NotificationObserver { #if defined(OS_CHROMEOS) scoped_ptr<EnterpriseInstallAttributes> install_attributes_; scoped_ptr<DeviceCloudPolicyManagerChromeOS> device_cloud_policy_manager_; + scoped_ptr<DeviceLocalAccountPolicyService> + device_local_account_policy_service_; #endif ProxyPolicyProvider user_cloud_policy_provider_; diff --git a/chrome/browser/policy/cloud_policy_constants.cc b/chrome/browser/policy/cloud_policy_constants.cc index 61de7d7..e46876a 100644 --- a/chrome/browser/policy/cloud_policy_constants.cc +++ b/chrome/browser/policy/cloud_policy_constants.cc @@ -31,6 +31,7 @@ const char kValueUserAffiliationNone[] = "none"; const char kChromeDevicePolicyType[] = "google/chromeos/device"; const char kChromeUserPolicyType[] = "google/chromeos/user"; +const char kChromePublicAccountPolicyType[] = "google/chromeos/publicaccount"; } // namespace dm_protocol diff --git a/chrome/browser/policy/cloud_policy_constants.h b/chrome/browser/policy/cloud_policy_constants.h index c9b46ad..d2f8f1b 100644 --- a/chrome/browser/policy/cloud_policy_constants.h +++ b/chrome/browser/policy/cloud_policy_constants.h @@ -33,6 +33,7 @@ extern const char kValueUserAffiliationNone[]; // Policy type strings for the policy_type field in PolicyFetchRequest. extern const char kChromeDevicePolicyType[]; extern const char kChromeUserPolicyType[]; +extern const char kChromePublicAccountPolicyType[]; // These codes are sent in the |error_code| field of PolicyFetchResponse. enum PolicyFetchStatus { diff --git a/chrome/browser/policy/device_local_account_policy_service.cc b/chrome/browser/policy/device_local_account_policy_service.cc new file mode 100644 index 0000000..ef49d36 --- /dev/null +++ b/chrome/browser/policy/device_local_account_policy_service.cc @@ -0,0 +1,251 @@ +// 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/policy/device_local_account_policy_service.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "chrome/browser/policy/cloud_policy_validator.h" +#include "chrome/browser/policy/device_management_service.h" +#include "chrome/browser/policy/proto/chrome_device_policy.pb.h" +#include "chrome/browser/policy/proto/cloud_policy.pb.h" +#include "chrome/browser/policy/proto/device_management_backend.pb.h" +#include "chromeos/dbus/session_manager_client.h" + +namespace em = enterprise_management; + +namespace policy { + +DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker( + const std::string& account_id, + chromeos::SessionManagerClient* session_manager_client, + chromeos::DeviceSettingsService* device_settings_service, + Delegate* delegate) + : account_id_(account_id), + session_manager_client_(session_manager_client), + device_settings_service_(device_settings_service), + delegate_(delegate), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), + status_(CloudPolicyStore::STATUS_OK), + validation_status_(CloudPolicyValidatorBase::VALIDATION_OK) {} + +DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {} + +void DeviceLocalAccountPolicyBroker::Load() { + weak_factory_.InvalidateWeakPtrs(); + session_manager_client_->RetrieveDeviceLocalAccountPolicy( + account_id_, + base::Bind(&DeviceLocalAccountPolicyBroker::ValidateLoadedPolicyBlob, + weak_factory_.GetWeakPtr())); +} + +void DeviceLocalAccountPolicyBroker::Store( + const em::PolicyFetchResponse& policy) { + weak_factory_.InvalidateWeakPtrs(); + CheckKeyAndValidate( + make_scoped_ptr(new em::PolicyFetchResponse(policy)), + base::Bind(&DeviceLocalAccountPolicyBroker::StoreValidatedPolicy, + weak_factory_.GetWeakPtr())); +} + +void DeviceLocalAccountPolicyBroker::ValidateLoadedPolicyBlob( + const std::string& policy_blob) { + if (policy_blob.empty()) { + status_ = CloudPolicyStore::STATUS_LOAD_ERROR; + delegate_->OnLoadComplete(account_id_); + } else { + scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse()); + if (policy->ParseFromString(policy_blob)) { + CheckKeyAndValidate( + policy.Pass(), + base::Bind(&DeviceLocalAccountPolicyBroker::UpdatePolicy, + weak_factory_.GetWeakPtr())); + } else { + status_ = CloudPolicyStore::STATUS_PARSE_ERROR; + delegate_->OnLoadComplete(account_id_); + } + } +} + +void DeviceLocalAccountPolicyBroker::UpdatePolicy( + UserCloudPolicyValidator* validator) { + if (validator->success()) { + status_ = CloudPolicyStore::STATUS_OK; + validation_status_ = CloudPolicyValidatorBase::VALIDATION_OK; + policy_data_ = validator->policy_data().Pass(); + policy_settings_ = validator->payload().Pass(); + } else { + status_ = CloudPolicyStore::STATUS_VALIDATION_ERROR; + validation_status_ = validator->status(); + } + delegate_->OnLoadComplete(account_id_); +} + +void DeviceLocalAccountPolicyBroker::StoreValidatedPolicy( + UserCloudPolicyValidator* validator) { + if (!validator->success()) { + status_ = CloudPolicyStore::STATUS_VALIDATION_ERROR; + validation_status_ = validator->status(); + delegate_->OnLoadComplete(account_id_); + return; + } + + std::string policy_blob; + if (!validator->policy()->SerializeToString(&policy_blob)) { + status_ = CloudPolicyStore::STATUS_SERIALIZE_ERROR; + delegate_->OnLoadComplete(account_id_); + return; + } + + session_manager_client_->StoreDeviceLocalAccountPolicy( + account_id_, + policy_blob, + base::Bind(&DeviceLocalAccountPolicyBroker::HandleStoreResult, + weak_factory_.GetWeakPtr())); +} + +void DeviceLocalAccountPolicyBroker::HandleStoreResult(bool success) { + if (!success) { + status_ = CloudPolicyStore::STATUS_STORE_ERROR; + delegate_->OnLoadComplete(account_id_); + } else { + Load(); + } +} + +void DeviceLocalAccountPolicyBroker::CheckKeyAndValidate( + scoped_ptr<em::PolicyFetchResponse> policy, + const UserCloudPolicyValidator::CompletionCallback& callback) { + device_settings_service_->GetOwnershipStatusAsync( + base::Bind(&DeviceLocalAccountPolicyBroker::Validate, + weak_factory_.GetWeakPtr(), + base::Passed(policy.Pass()), + callback)); +} + +void DeviceLocalAccountPolicyBroker::Validate( + scoped_ptr<em::PolicyFetchResponse> policy, + const UserCloudPolicyValidator::CompletionCallback& callback, + chromeos::DeviceSettingsService::OwnershipStatus ownership_status, + bool is_owner) { + DCHECK_NE(chromeos::DeviceSettingsService::OWNERSHIP_UNKNOWN, + ownership_status); + chromeos::OwnerKey* key = device_settings_service_->GetOwnerKey(); + if (!key->public_key()) { + status_ = CloudPolicyStore::STATUS_BAD_STATE; + delegate_->OnLoadComplete(account_id_); + return; + } + + scoped_ptr<UserCloudPolicyValidator> validator( + UserCloudPolicyValidator::Create(policy.Pass())); + validator->ValidateUsername(account_id_); + validator->ValidatePolicyType(dm_protocol::kChromePublicAccountPolicyType); + validator->ValidateAgainstCurrentPolicy(policy_data_.get(), false); + validator->ValidatePayload(); + validator->ValidateSignature(*key->public_key(), false); + validator.release()->StartValidation(callback); +} + +DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService( + chromeos::SessionManagerClient* session_manager_client, + chromeos::DeviceSettingsService* device_settings_service) + : session_manager_client_(session_manager_client), + device_settings_service_(device_settings_service), + device_management_service_(NULL) { + device_settings_service_->AddObserver(this); + DeviceSettingsUpdated(); +} + +DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() { + device_settings_service_->RemoveObserver(this); + + STLDeleteContainerPairSecondPointers(policy_brokers_.begin(), + policy_brokers_.end()); + policy_brokers_.clear(); +} + +void DeviceLocalAccountPolicyService::Initialize( + DeviceManagementService* device_management_service) { + DCHECK(!device_management_service_); + device_management_service_ = device_management_service; +} + +void DeviceLocalAccountPolicyService::Shutdown() { + DCHECK(device_management_service_); + device_management_service_ = NULL; +} + +DeviceLocalAccountPolicyBroker* + DeviceLocalAccountPolicyService::GetBrokerForAccount( + const std::string& account_id) { + PolicyBrokerMap::iterator entry = policy_brokers_.find(account_id); + if (entry == policy_brokers_.end()) + return NULL; + + if (!entry->second) { + entry->second = new DeviceLocalAccountPolicyBroker(account_id, + session_manager_client_, + device_settings_service_, + this); + } + + return entry->second; +} + +void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void DeviceLocalAccountPolicyService::OwnershipStatusChanged() { + // TODO(mnissler): The policy key has changed, re-fetch policy. For + // consumer devices, re-sign the current settings and send updates to + // session_manager. +} + +void DeviceLocalAccountPolicyService::DeviceSettingsUpdated() { + const em::ChromeDeviceSettingsProto* device_settings = + device_settings_service_->device_settings(); + if (device_settings) + UpdateAccountList(*device_settings); +} + +void DeviceLocalAccountPolicyService::UpdateAccountList( + const em::ChromeDeviceSettingsProto& device_settings) { + using google::protobuf::RepeatedPtrField; + + // Update |policy_brokers_|, keeping existing entries. + PolicyBrokerMap new_policy_brokers; + const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts = + device_settings.device_local_accounts().account(); + RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry; + for (entry = accounts.begin(); entry != accounts.end(); ++entry) { + if (entry->has_id()) { + DeviceLocalAccountPolicyBroker*& broker = policy_brokers_[entry->id()]; + new_policy_brokers[entry->id()] = broker; + broker = NULL; + } + } + policy_brokers_.swap(new_policy_brokers); + STLDeleteContainerPairSecondPointers(new_policy_brokers.begin(), + new_policy_brokers.end()); + + FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged()); + + // TODO(mnissler): Trigger policy fetches for all the new brokers on + // cloud-managed devices. +} + +void DeviceLocalAccountPolicyService::OnLoadComplete( + const std::string& account_id) { + FOR_EACH_OBSERVER(Observer, observers_, OnPolicyChanged(account_id)); +} + +} // namespace policy diff --git a/chrome/browser/policy/device_local_account_policy_service.h b/chrome/browser/policy/device_local_account_policy_service.h new file mode 100644 index 0000000..8d9a49b --- /dev/null +++ b/chrome/browser/policy/device_local_account_policy_service.h @@ -0,0 +1,184 @@ +// 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. + +#ifndef CHROME_BROWSER_POLICY_DEVICE_LOCAL_ACCOUNT_POLICY_SERVICE_H_ +#define CHROME_BROWSER_POLICY_DEVICE_LOCAL_ACCOUNT_POLICY_SERVICE_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" +#include "chrome/browser/policy/cloud_policy_store.h" + +namespace chromeos { +class SessionManagerClient; +} + +namespace enterprise_management { +class CloudPolicySettings; +class PolicyData; +class PolicyFetchResponse; +} + +namespace policy { + +class DeviceManagementService; + +// This class manages the policy blob for a single device-local account, taking +// care of interaction with session_manager and doing validation. +class DeviceLocalAccountPolicyBroker { + public: + class Delegate { + public: + virtual ~Delegate() {} + virtual void OnLoadComplete(const std::string& account_id) = 0; + }; + + DeviceLocalAccountPolicyBroker( + const std::string& account_id, + chromeos::SessionManagerClient* session_manager_client, + chromeos::DeviceSettingsService* device_settings_service, + Delegate* delegate); + ~DeviceLocalAccountPolicyBroker(); + + const std::string& account_id() const { return account_id_; } + const enterprise_management::PolicyData* policy_data() const { + return policy_data_.get(); + } + const enterprise_management::CloudPolicySettings* policy_settings() const { + return policy_settings_.get(); + } + CloudPolicyStore::Status status() const { return status_; } + CloudPolicyValidatorBase::Status validation_status() const { + return validation_status_; + } + + // Loads the policy from session_manager. + void Load(); + + // Send policy to session_manager to store it. + void Store(const enterprise_management::PolicyFetchResponse& policy); + + private: + // Called back by |session_manager_client_| after policy retrieval. Checks for + // success and triggers policy validation. + void ValidateLoadedPolicyBlob(const std::string& policy_blob); + + // Updates state after validation and notifies the delegate. + void UpdatePolicy(UserCloudPolicyValidator* validator); + + // Sends the policy blob to session_manager for storing after validation. + void StoreValidatedPolicy(UserCloudPolicyValidator* validator); + + // Called back when a store operation completes, updates state and reloads the + // policy if applicable. + void HandleStoreResult(bool result); + + // Gets the owner key and triggers policy validation. + void CheckKeyAndValidate( + scoped_ptr<enterprise_management::PolicyFetchResponse> policy, + const UserCloudPolicyValidator::CompletionCallback& callback); + + // Triggers policy validation. + void Validate( + scoped_ptr<enterprise_management::PolicyFetchResponse> policy, + const UserCloudPolicyValidator::CompletionCallback& callback, + chromeos::DeviceSettingsService::OwnershipStatus ownership_status, + bool is_owner); + + const std::string account_id_; + chromeos::SessionManagerClient* session_manager_client_; + chromeos::DeviceSettingsService* device_settings_service_; + Delegate* delegate_; + + base::WeakPtrFactory<DeviceLocalAccountPolicyBroker> weak_factory_; + + // Current policy. + scoped_ptr<enterprise_management::PolicyData> policy_data_; + scoped_ptr<enterprise_management::CloudPolicySettings> policy_settings_; + + // Status codes. + CloudPolicyStore::Status status_; + CloudPolicyValidatorBase::Status validation_status_; + + DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyBroker); +}; + +// Manages user policy blobs for device-local accounts present on the device. +// The actual policy blobs are brokered by session_manager (to prevent file +// manipulation), and we're making signature checks on the policy blobs to +// ensure they're issued by the device owner. +class DeviceLocalAccountPolicyService + : public chromeos::DeviceSettingsService::Observer, + public DeviceLocalAccountPolicyBroker::Delegate { + public: + // Interface for interested parties to observe policy changes. + class Observer { + public: + virtual ~Observer() {} + + // Policy for the given account has changed. + virtual void OnPolicyChanged(const std::string& account_id) = 0; + + // The list of accounts has been updated. + virtual void OnDeviceLocalAccountsChanged() = 0; + }; + + DeviceLocalAccountPolicyService( + chromeos::SessionManagerClient* session_manager_client, + chromeos::DeviceSettingsService* device_settings_service); + virtual ~DeviceLocalAccountPolicyService(); + + // Initializes the cloud policy service connection. + void Initialize(DeviceManagementService* device_management_service); + + // Prevents further policy fetches from the cloud. + void Shutdown(); + + // Get the policy broker for a given account. Returns NULL if that account is + // not valid. + DeviceLocalAccountPolicyBroker* GetBrokerForAccount( + const std::string& account_id); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // DeviceSettingsService::Observer: + virtual void OwnershipStatusChanged() OVERRIDE; + virtual void DeviceSettingsUpdated() OVERRIDE; + + private: + // Re-queries the list of defined device-local accounts from device settings + // and updates |policy_brokers_| to match that list. + void UpdateAccountList( + const enterprise_management::ChromeDeviceSettingsProto& device_settings); + + // DeviceLocalAccountPolicyBroker::Delegate: + virtual void OnLoadComplete(const std::string& account_id) OVERRIDE; + + chromeos::SessionManagerClient* session_manager_client_; + chromeos::DeviceSettingsService* device_settings_service_; + + DeviceManagementService* device_management_service_; + + // The device-local account policy brokers, keyed by account ID. + typedef std::map<std::string, DeviceLocalAccountPolicyBroker*> + PolicyBrokerMap; + PolicyBrokerMap policy_brokers_; + + ObserverList<Observer, true> observers_; + + DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyService); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_DEVICE_LOCAL_ACCOUNT_POLICY_SERVICE_H_ diff --git a/chrome/browser/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/policy/device_local_account_policy_service_unittest.cc new file mode 100644 index 0000000..03c4dd5 --- /dev/null +++ b/chrome/browser/policy/device_local_account_policy_service_unittest.cc @@ -0,0 +1,221 @@ +// 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/policy/device_local_account_policy_service.h" + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" +#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" +#include "chrome/browser/chromeos/settings/mock_owner_key_util.h" +#include "chrome/browser/policy/mock_device_management_service.h" +#include "chrome/browser/policy/policy_builder.h" +#include "chrome/browser/policy/proto/chrome_device_policy.pb.h" +#include "content/public/test/test_browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace em = enterprise_management; + +using testing::Mock; + +namespace policy { + +class MockDeviceLocalAccountPolicyServiceObserver + : public DeviceLocalAccountPolicyService::Observer { + public: + MOCK_METHOD1(OnPolicyChanged, void(const std::string&)); + MOCK_METHOD0(OnDeviceLocalAccountsChanged, void(void)); +}; + +class DeviceLocalAccountPolicyServiceTest : public testing::Test { + protected: + DeviceLocalAccountPolicyServiceTest() + : loop_(MessageLoop::TYPE_UI), + ui_thread_(content::BrowserThread::UI, &loop_), + file_thread_(content::BrowserThread::FILE, &loop_), + owner_key_util_(new chromeos::MockOwnerKeyUtil()), + service_(&device_settings_test_helper_, &device_settings_service_) {} + + virtual void SetUp() OVERRIDE { + owner_key_util_->SetPublicKeyFromPrivateKey(device_policy_.signing_key()); + + device_settings_service_.Initialize(&device_settings_test_helper_, + owner_key_util_); + device_settings_service_.Load(); + + device_local_account_policy_.payload().mutable_disablespdy()-> + set_disablespdy(true); + device_local_account_policy_.policy_data().set_policy_type( + dm_protocol::kChromePublicAccountPolicyType); + device_local_account_policy_.Build(); + + device_policy_.payload().mutable_device_local_accounts()->add_account()-> + set_id(PolicyBuilder::kFakeUsername); + device_policy_.Build(); + + service_.AddObserver(&observer_); + } + + virtual void TearDown() OVERRIDE { + service_.RemoveObserver(&observer_); + } + + void InstallDevicePolicy() { + EXPECT_CALL(observer_, OnDeviceLocalAccountsChanged()); + device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + } + + MessageLoop loop_; + content::TestBrowserThread ui_thread_; + content::TestBrowserThread file_thread_; + + DevicePolicyBuilder device_policy_; + UserPolicyBuilder device_local_account_policy_; + + chromeos::DeviceSettingsTestHelper device_settings_test_helper_; + scoped_refptr<chromeos::MockOwnerKeyUtil> owner_key_util_; + chromeos::DeviceSettingsService device_settings_service_; + MockDeviceManagementService device_management_service_; + + MockDeviceLocalAccountPolicyServiceObserver observer_; + + DeviceLocalAccountPolicyService service_; + + private: + DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountPolicyServiceTest); +}; + +TEST_F(DeviceLocalAccountPolicyServiceTest, NoAccounts) { + device_settings_test_helper_.Flush(); + EXPECT_FALSE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, GetBroker) { + InstallDevicePolicy(); + + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + EXPECT_EQ(PolicyBuilder::kFakeUsername, broker->account_id()); + EXPECT_EQ(CloudPolicyStore::STATUS_OK, broker->status()); + EXPECT_FALSE(broker->policy_data()); + EXPECT_FALSE(broker->policy_settings()); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, LoadNoPolicy) { + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnPolicyChanged(PolicyBuilder::kFakeUsername)); + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + broker->Load(); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + + EXPECT_EQ(CloudPolicyStore::STATUS_LOAD_ERROR, broker->status()); + EXPECT_FALSE(broker->policy_data()); + EXPECT_FALSE(broker->policy_settings()); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, LoadValidationFailure) { + device_local_account_policy_.policy_data().set_policy_type( + dm_protocol::kChromeUserPolicyType); + device_local_account_policy_.Build(); + device_settings_test_helper_.set_device_local_account_policy_blob( + PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnPolicyChanged(PolicyBuilder::kFakeUsername)); + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + broker->Load(); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + + EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, broker->status()); + EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE, + broker->validation_status()); + EXPECT_FALSE(broker->policy_data()); + EXPECT_FALSE(broker->policy_settings()); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, LoadPolicy) { + device_settings_test_helper_.set_device_local_account_policy_blob( + PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnPolicyChanged(PolicyBuilder::kFakeUsername)); + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + broker->Load(); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + + EXPECT_EQ(CloudPolicyStore::STATUS_OK, broker->status()); + ASSERT_TRUE(broker->policy_data()); + EXPECT_EQ(device_local_account_policy_.policy_data().SerializeAsString(), + broker->policy_data()->SerializeAsString()); + ASSERT_TRUE(broker->policy_settings()); + EXPECT_EQ(device_local_account_policy_.payload().SerializeAsString(), + broker->policy_settings()->SerializeAsString()); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, StoreValidationFailure) { + device_local_account_policy_.policy_data().set_policy_type( + dm_protocol::kChromeUserPolicyType); + device_local_account_policy_.Build(); + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnPolicyChanged(PolicyBuilder::kFakeUsername)); + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + broker->Store(device_local_account_policy_.policy()); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + + EXPECT_EQ(CloudPolicyStore::STATUS_VALIDATION_ERROR, broker->status()); + EXPECT_EQ(CloudPolicyValidatorBase::VALIDATION_WRONG_POLICY_TYPE, + broker->validation_status()); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, StorePolicy) { + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnPolicyChanged(PolicyBuilder::kFakeUsername)); + DeviceLocalAccountPolicyBroker* broker = + service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername); + ASSERT_TRUE(broker); + broker->Store(device_local_account_policy_.policy()); + device_settings_test_helper_.Flush(); + Mock::VerifyAndClearExpectations(&observer_); + + EXPECT_EQ(device_local_account_policy_.GetBlob(), + device_settings_test_helper_.device_local_account_policy_blob( + PolicyBuilder::kFakeUsername)); +} + +TEST_F(DeviceLocalAccountPolicyServiceTest, DevicePolicyChange) { + device_settings_test_helper_.set_device_local_account_policy_blob( + PolicyBuilder::kFakeUsername, device_local_account_policy_.GetBlob()); + InstallDevicePolicy(); + + EXPECT_CALL(observer_, OnDeviceLocalAccountsChanged()); + device_policy_.payload().mutable_device_local_accounts()->clear_account(); + device_policy_.Build(); + device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); + device_settings_service_.PropertyChangeComplete(true); + device_settings_test_helper_.Flush(); + EXPECT_FALSE(service_.GetBrokerForAccount(PolicyBuilder::kFakeUsername)); + Mock::VerifyAndClearExpectations(&observer_); +} + +} // namespace policy diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index c167c41..17a8aca 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1326,6 +1326,8 @@ 'browser/policy/device_cloud_policy_manager_chromeos.h', 'browser/policy/device_cloud_policy_store_chromeos.cc', 'browser/policy/device_cloud_policy_store_chromeos.h', + 'browser/policy/device_local_account_policy_service.cc', + 'browser/policy/device_local_account_policy_service.h', 'browser/policy/device_policy_cache.cc', 'browser/policy/device_policy_cache.h', 'browser/policy/device_policy_decoder_chromeos.cc', @@ -2377,34 +2379,36 @@ ], }], ['chromeos==0', { - 'sources/': [ - ['exclude', 'browser/extensions/api/input_ime/input_ime_api.cc'], - ['exclude', 'browser/extensions/api/input_ime/input_ime_api.h'], - ['exclude', 'browser/extensions/api/terminal/terminal_extension_helper.cc'], - ['exclude', 'browser/extensions/api/terminal/terminal_extension_helper.h'], - ['exclude', 'browser/extensions/api/terminal/terminal_private_api.cc'], - ['exclude', 'browser/extensions/api/terminal/terminal_private_api.h'], - ['exclude', 'browser/net/gaia/gaia_oauth_consumer.h'], - ['exclude', 'browser/net/gaia/gaia_oauth_fetcher.cc'], - ['exclude', 'browser/net/gaia/gaia_oauth_fetcher.h'], - ['exclude', 'browser/policy/app_pack_updater.cc'], - ['exclude', 'browser/policy/app_pack_updater.h'], - ['exclude', 'browser/policy/auto_enrollment_client.cc'], - ['exclude', 'browser/policy/auto_enrollment_client.h'], - ['exclude', 'browser/policy/cros_user_policy_cache.cc'], - ['exclude', 'browser/policy/cros_user_policy_cache.h'], - ['exclude', 'browser/policy/device_policy_cache.cc'], - ['exclude', 'browser/policy/device_policy_cache.h'], - ['exclude', 'browser/policy/device_status_collector.cc'], - ['exclude', 'browser/policy/device_status_collector.h'], - ['exclude', 'browser/policy/enterprise_install_attributes.cc'], - ['exclude', 'browser/policy/enterprise_install_attributes.h'], - ['exclude', 'browser/policy/network_configuration_updater.cc'], - ['exclude', 'browser/policy/network_configuration_updater.h'], - ['exclude', 'browser/policy/proto/chrome_device_policy.pb.cc'], - ['exclude', 'browser/policy/proto/chrome_device_policy.pb.h'], - ['exclude', 'browser/renderer_host/offline_resource_throttle.cc'], - ['exclude', 'browser/renderer_host/offline_resource_throttle.h'], + 'sources!': [ + 'browser/extensions/api/input_ime/input_ime_api.cc', + 'browser/extensions/api/input_ime/input_ime_api.h', + 'browser/extensions/api/terminal/terminal_extension_helper.cc', + 'browser/extensions/api/terminal/terminal_extension_helper.h', + 'browser/extensions/api/terminal/terminal_private_api.cc', + 'browser/extensions/api/terminal/terminal_private_api.h', + 'browser/net/gaia/gaia_oauth_consumer.h', + 'browser/net/gaia/gaia_oauth_fetcher.cc', + 'browser/net/gaia/gaia_oauth_fetcher.h', + 'browser/policy/app_pack_updater.cc', + 'browser/policy/app_pack_updater.h', + 'browser/policy/auto_enrollment_client.cc', + 'browser/policy/auto_enrollment_client.h', + 'browser/policy/cros_user_policy_cache.cc', + 'browser/policy/cros_user_policy_cache.h', + 'browser/policy/device_local_account_policy_service.cc', + 'browser/policy/device_local_account_policy_service.h', + 'browser/policy/device_policy_cache.cc', + 'browser/policy/device_policy_cache.h', + 'browser/policy/device_status_collector.cc', + 'browser/policy/device_status_collector.h', + 'browser/policy/enterprise_install_attributes.cc', + 'browser/policy/enterprise_install_attributes.h', + 'browser/policy/network_configuration_updater.cc', + 'browser/policy/network_configuration_updater.h', + 'browser/policy/proto/chrome_device_policy.pb.cc', + 'browser/policy/proto/chrome_device_policy.pb.h', + 'browser/renderer_host/offline_resource_throttle.cc', + 'browser/renderer_host/offline_resource_throttle.h', ], }, { # chromeos==1 'dependencies': [ diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 82455f7..db65829 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -921,6 +921,7 @@ 'browser/policy/device_management_service_unittest.cc', 'browser/policy/device_policy_cache_unittest.cc', 'browser/policy/device_token_fetcher_unittest.cc', + 'browser/policy/device_local_account_policy_service_unittest.cc', 'browser/policy/enterprise_install_attributes_unittest.cc', 'browser/policy/logging_work_scheduler.cc', 'browser/policy/logging_work_scheduler.h', @@ -1847,17 +1848,21 @@ }, { # else: chromeos == 0 'sources/': [ ['exclude', '^browser/chromeos/'], - ['exclude', '^browser/net/gaia/gaia_oauth_fetcher_unittest.cc'], - ['exclude', '^browser/policy/auto_enrollment_client_unittest.cc' ], - ['exclude', '^browser/policy/cros_user_policy_cache_unittest.cc'], - ['exclude', '^browser/policy/device_policy_cache_unittest.cc'], - ['exclude', '^browser/policy/enterprise_install_attributes_unittest.cc' ], - ['exclude', '^browser/policy/network_configuration_updater_unittest.cc' ], ['exclude', '^browser/ui/webui/chromeos/imageburner/'], ['exclude', '^browser/ui/webui/chromeos/login'], ['exclude', '^browser/ui/webui/options/chromeos/'], ['exclude', '^browser/ui/webui/options/chromeos/'], ], + 'sources!': [ + 'browser/net/gaia/gaia_oauth_fetcher_unittest.cc', + 'browser/policy/auto_enrollment_client_unittest.cc' , + 'browser/policy/cros_user_policy_cache_unittest.cc', + 'browser/policy/device_policy_cache_unittest.cc', + 'browser/policy/device_local_account_policy_service_unittest.cc', + 'browser/policy/device_status_collector_unittest.cc', + 'browser/policy/enterprise_install_attributes_unittest.cc', + 'browser/policy/network_configuration_updater_unittest.cc', + ], }], ['toolkit_uses_gtk == 1', { 'conditions': [ |