summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-23 16:26:35 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-23 16:26:35 +0000
commit0f456542ea264dfadc276f51567933af10402064 (patch)
treed8309bb83023498117a1e181dc04e9cf8f89b10d
parenta3bd13145d57525d67272a6661c3c6f87b265f7a (diff)
downloadchromium_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.cc12
-rw-r--r--chrome/browser/policy/browser_policy_connector.h3
-rw-r--r--chrome/browser/policy/cloud_policy_constants.cc1
-rw-r--r--chrome/browser/policy/cloud_policy_constants.h1
-rw-r--r--chrome/browser/policy/device_local_account_policy_service.cc251
-rw-r--r--chrome/browser/policy/device_local_account_policy_service.h184
-rw-r--r--chrome/browser/policy/device_local_account_policy_service_unittest.cc221
-rw-r--r--chrome/chrome_browser.gypi60
-rw-r--r--chrome/chrome_tests_unit.gypi17
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': [