| Index: chrome/browser/chromeos/policy/device_local_account_policy_service.cc
|
| diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
|
| index df918a8701f2c3edabe8b145021a0867cd81794f..a5388264dd169bec1de7ab8e41d41471f8c8c950 100644
|
| --- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
|
| +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
|
| @@ -4,35 +4,87 @@
|
|
|
| #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
|
|
|
| +#include <vector>
|
| +
|
| +#include "base/bind.h"
|
| #include "base/logging.h"
|
| #include "base/message_loop.h"
|
| +#include "chrome/browser/chromeos/policy/device_local_account.h"
|
| #include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
|
| +#include "chrome/browser/chromeos/settings/cros_settings.h"
|
| +#include "chrome/browser/chromeos/settings/cros_settings_names.h"
|
| +#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
|
| +#include "chrome/browser/chromeos/settings/device_settings_service.h"
|
| #include "chrome/browser/policy/cloud/cloud_policy_client.h"
|
| #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
|
| #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
|
| #include "chrome/browser/policy/cloud/device_management_service.h"
|
| -#include "chrome/browser/policy/proto/chromeos/chrome_device_policy.pb.h"
|
| #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
|
| +#include "chrome/common/chrome_notification_types.h"
|
| #include "chromeos/dbus/session_manager_client.h"
|
| +#include "content/public/browser/notification_details.h"
|
| #include "policy/policy_constants.h"
|
|
|
| namespace em = enterprise_management;
|
|
|
| namespace policy {
|
|
|
| +namespace {
|
| +
|
| +// Creates a broker for the device-local account with the given |user_id| and
|
| +// |account_id|.
|
| +scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker(
|
| + const std::string& user_id,
|
| + const std::string& account_id,
|
| + chromeos::SessionManagerClient* session_manager_client,
|
| + chromeos::DeviceSettingsService* device_settings_service,
|
| + DeviceLocalAccountPolicyService* device_local_account_policy_service) {
|
| + scoped_ptr<DeviceLocalAccountPolicyStore> store(
|
| + new DeviceLocalAccountPolicyStore(account_id, session_manager_client,
|
| + device_settings_service));
|
| + scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
|
| + new DeviceLocalAccountPolicyBroker(user_id, store.Pass()));
|
| + broker->core()->store()->AddObserver(device_local_account_policy_service);
|
| + broker->core()->store()->Load();
|
| + return broker.Pass();
|
| +}
|
| +
|
| +// Creates and initializes a cloud policy client. Returns NULL if the device
|
| +// doesn't have credentials in device settings (i.e. is not
|
| +// enterprise-enrolled).
|
| +scoped_ptr<CloudPolicyClient> CreateClient(
|
| + chromeos::DeviceSettingsService* device_settings_service,
|
| + DeviceManagementService* device_management_service) {
|
| + const em::PolicyData* policy_data = device_settings_service->policy_data();
|
| + if (!policy_data ||
|
| + !policy_data->has_request_token() ||
|
| + !policy_data->has_device_id() ||
|
| + !device_management_service) {
|
| + return scoped_ptr<CloudPolicyClient>();
|
| + }
|
| +
|
| + scoped_ptr<CloudPolicyClient> client(
|
| + new CloudPolicyClient(std::string(), std::string(),
|
| + USER_AFFILIATION_MANAGED,
|
| + NULL, device_management_service));
|
| + client->SetupRegistration(policy_data->request_token(),
|
| + policy_data->device_id());
|
| + return client.Pass();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
|
| + const std::string& user_id,
|
| scoped_ptr<DeviceLocalAccountPolicyStore> store)
|
| - : store_(store.Pass()),
|
| + : user_id_(user_id),
|
| + store_(store.Pass()),
|
| core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
|
| store_->account_id()),
|
| store_.get()) {}
|
|
|
| DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {}
|
|
|
| -const std::string& DeviceLocalAccountPolicyBroker::account_id() const {
|
| - return store_->account_id();
|
| -}
|
| -
|
| void DeviceLocalAccountPolicyBroker::Connect(
|
| scoped_ptr<CloudPolicyClient> client) {
|
| core_.Connect(client.Pass());
|
| @@ -63,18 +115,60 @@ std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
|
| return display_name;
|
| }
|
|
|
| +DeviceLocalAccountPolicyService::PolicyBrokerWrapper::PolicyBrokerWrapper()
|
| + : parent(NULL), broker(NULL) {}
|
| +
|
| +DeviceLocalAccountPolicyBroker*
|
| + DeviceLocalAccountPolicyService::PolicyBrokerWrapper::GetBroker() {
|
| + if (!broker) {
|
| + broker = CreateBroker(user_id, account_id,
|
| + parent->session_manager_client_,
|
| + parent->device_settings_service_,
|
| + parent).release();
|
| + }
|
| + return broker;
|
| +}
|
| +
|
| +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::ConnectIfPossible() {
|
| + if (broker && broker->core()->client())
|
| + return;
|
| + scoped_ptr<CloudPolicyClient> client(CreateClient(
|
| + parent->device_settings_service_,
|
| + parent->device_management_service_));
|
| + if (client)
|
| + GetBroker()->Connect(client.Pass());
|
| +}
|
| +
|
| +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::Disconnect() {
|
| + if (broker)
|
| + broker->Disconnect();
|
| +}
|
| +
|
| +void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::DeleteBroker() {
|
| + if (!broker)
|
| + return;
|
| + broker->core()->store()->RemoveObserver(parent);
|
| + delete broker;
|
| + broker = NULL;
|
| +}
|
| +
|
| DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
|
| chromeos::SessionManagerClient* session_manager_client,
|
| - chromeos::DeviceSettingsService* device_settings_service)
|
| + chromeos::DeviceSettingsService* device_settings_service,
|
| + chromeos::CrosSettings* cros_settings)
|
| : session_manager_client_(session_manager_client),
|
| device_settings_service_(device_settings_service),
|
| - device_management_service_(NULL) {
|
| - device_settings_service_->AddObserver(this);
|
| - DeviceSettingsUpdated();
|
| + cros_settings_(cros_settings),
|
| + device_management_service_(NULL),
|
| + cros_settings_callback_factory_(this) {
|
| + cros_settings_->AddSettingsObserver(
|
| + chromeos::kAccountsPrefDeviceLocalAccounts, this);
|
| + UpdateAccountList();
|
| }
|
|
|
| DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
|
| - device_settings_service_->RemoveObserver(this);
|
| + cros_settings_->RemoveSettingsObserver(
|
| + chromeos::kAccountsPrefDeviceLocalAccounts, this);
|
| DeleteBrokers(&policy_brokers_);
|
| }
|
|
|
| @@ -84,11 +178,9 @@ void DeviceLocalAccountPolicyService::Connect(
|
| device_management_service_ = device_management_service;
|
|
|
| // Connect the brokers.
|
| - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
|
| - broker != policy_brokers_.end(); ++broker) {
|
| - DCHECK(!broker->second->core()->client());
|
| - broker->second->Connect(
|
| - CreateClientForAccount(broker->second->account_id()).Pass());
|
| + for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
|
| + it != policy_brokers_.end(); ++it) {
|
| + it->second.ConnectIfPossible();
|
| }
|
| }
|
|
|
| @@ -97,28 +189,25 @@ void DeviceLocalAccountPolicyService::Disconnect() {
|
| device_management_service_ = NULL;
|
|
|
| // Disconnect the brokers.
|
| - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
|
| - broker != policy_brokers_.end(); ++broker) {
|
| - broker->second->Disconnect();
|
| + for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
|
| + it != policy_brokers_.end(); ++it) {
|
| + it->second.Disconnect();
|
| }
|
| }
|
|
|
| DeviceLocalAccountPolicyBroker*
|
| - DeviceLocalAccountPolicyService::GetBrokerForAccount(
|
| - const std::string& account_id) {
|
| - PolicyBrokerMap::iterator entry = policy_brokers_.find(account_id);
|
| + DeviceLocalAccountPolicyService::GetBrokerForUser(
|
| + const std::string& user_id) {
|
| + PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
|
| if (entry == policy_brokers_.end())
|
| return NULL;
|
|
|
| - if (!entry->second)
|
| - entry->second = CreateBroker(account_id).release();
|
| -
|
| - return entry->second;
|
| + return entry->second.GetBroker();
|
| }
|
|
|
| -bool DeviceLocalAccountPolicyService::IsPolicyAvailableForAccount(
|
| - const std::string& account_id) {
|
| - DeviceLocalAccountPolicyBroker* broker = GetBrokerForAccount(account_id);
|
| +bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
|
| + const std::string& user_id) {
|
| + DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
|
| return broker && broker->core()->store()->is_managed();
|
| }
|
|
|
| @@ -130,79 +219,69 @@ 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::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
|
| + *content::Details<const std::string>(details).ptr() !=
|
| + chromeos::kAccountsPrefDeviceLocalAccounts) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
|
|
| -void DeviceLocalAccountPolicyService::DeviceSettingsUpdated() {
|
| - const em::ChromeDeviceSettingsProto* device_settings =
|
| - device_settings_service_->device_settings();
|
| - if (device_settings)
|
| - UpdateAccountList(*device_settings);
|
| + // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
|
| + // pending (because the |cros_settings_| are not trusted yet), the updated
|
| + // account list will be processed by that call when it eventually runs.
|
| + if (!cros_settings_callback_factory_.HasWeakPtrs())
|
| + UpdateAccountList();
|
| }
|
|
|
| void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
|
| DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
|
| + DCHECK(broker);
|
| + if (!broker)
|
| + return;
|
| broker->UpdateRefreshDelay();
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnPolicyUpdated(broker->account_id()));
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
|
| }
|
|
|
| void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) {
|
| DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnPolicyUpdated(broker->account_id()));
|
| + DCHECK(broker);
|
| + if (!broker)
|
| + return;
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
|
| }
|
|
|
| -void DeviceLocalAccountPolicyService::UpdateAccountList(
|
| - const em::ChromeDeviceSettingsProto& device_settings) {
|
| - using google::protobuf::RepeatedPtrField;
|
| +void DeviceLocalAccountPolicyService::UpdateAccountList() {
|
| + if (chromeos::CrosSettingsProvider::TRUSTED !=
|
| + cros_settings_->PrepareTrustedValues(
|
| + base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
|
| + cros_settings_callback_factory_.GetWeakPtr()))) {
|
| + return;
|
| + }
|
|
|
| // 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) {
|
| - std::string account_id;
|
| - if (entry->has_type() &&
|
| - entry->type() ==
|
| - em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION) {
|
| - account_id = entry->account_id();
|
| - } else if (entry->has_deprecated_public_session_id()) {
|
| - account_id = entry->deprecated_public_session_id();
|
| - }
|
| -
|
| - if (account_id.empty())
|
| - continue;
|
| -
|
| - // Sanity check for whether this account ID has already been processed.
|
| - DeviceLocalAccountPolicyBroker*& new_broker =
|
| - new_policy_brokers[account_id];
|
| - if (new_broker) {
|
| - LOG(WARNING) << "Duplicate public account " << account_id;
|
| - continue;
|
| - }
|
| + const std::vector<DeviceLocalAccount> device_local_accounts =
|
| + GetDeviceLocalAccounts(cros_settings_);
|
| + for (std::vector<DeviceLocalAccount>::const_iterator it =
|
| + device_local_accounts.begin();
|
| + it != device_local_accounts.end(); ++it) {
|
| + PolicyBrokerWrapper& wrapper = new_policy_brokers[it->user_id];
|
| + wrapper.user_id = it->user_id;
|
| + wrapper.account_id = it->account_id;
|
| + wrapper.parent = this;
|
|
|
| // Reuse the existing broker if present.
|
| - DeviceLocalAccountPolicyBroker*& existing_broker =
|
| - policy_brokers_[account_id];
|
| - new_broker = existing_broker;
|
| - existing_broker = NULL;
|
| + PolicyBrokerWrapper& existing_wrapper = policy_brokers_[it->user_id];
|
| + wrapper.broker = existing_wrapper.broker;
|
| + existing_wrapper.broker = NULL;
|
|
|
| // Fire up the cloud connection for fetching policy for the account from
|
| // the cloud if this is an enterprise-managed device.
|
| - if (!new_broker || !new_broker->core()->client()) {
|
| - scoped_ptr<CloudPolicyClient> client(
|
| - CreateClientForAccount(account_id));
|
| - if (client.get()) {
|
| - if (!new_broker)
|
| - new_broker = CreateBroker(account_id).release();
|
| - new_broker->Connect(client.Pass());
|
| - }
|
| - }
|
| + wrapper.ConnectIfPossible();
|
| }
|
| policy_brokers_.swap(new_policy_brokers);
|
| DeleteBrokers(&new_policy_brokers);
|
| @@ -210,59 +289,21 @@ void DeviceLocalAccountPolicyService::UpdateAccountList(
|
| FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
|
| }
|
|
|
| -scoped_ptr<DeviceLocalAccountPolicyBroker>
|
| - DeviceLocalAccountPolicyService::CreateBroker(
|
| - const std::string& account_id) {
|
| - scoped_ptr<DeviceLocalAccountPolicyStore> store(
|
| - new DeviceLocalAccountPolicyStore(account_id, session_manager_client_,
|
| - device_settings_service_));
|
| - scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
|
| - new DeviceLocalAccountPolicyBroker(store.Pass()));
|
| - broker->core()->store()->AddObserver(this);
|
| - broker->core()->store()->Load();
|
| - return broker.Pass();
|
| -}
|
| -
|
| void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
|
| - for (PolicyBrokerMap::iterator broker = map->begin(); broker != map->end();
|
| - ++broker) {
|
| - if (broker->second) {
|
| - broker->second->core()->store()->RemoveObserver(this);
|
| - delete broker->second;
|
| - }
|
| - }
|
| + for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it)
|
| + it->second.DeleteBroker();
|
| map->clear();
|
| }
|
|
|
| DeviceLocalAccountPolicyBroker*
|
| DeviceLocalAccountPolicyService::GetBrokerForStore(
|
| CloudPolicyStore* store) {
|
| - for (PolicyBrokerMap::iterator broker(policy_brokers_.begin());
|
| - broker != policy_brokers_.end(); ++broker) {
|
| - if (broker->second->core()->store() == store)
|
| - return broker->second;
|
| + for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
|
| + it != policy_brokers_.end(); ++it) {
|
| + if (it->second.broker && it->second.broker->core()->store() == store)
|
| + return it->second.broker;
|
| }
|
| return NULL;
|
| }
|
|
|
| -scoped_ptr<CloudPolicyClient>
|
| - DeviceLocalAccountPolicyService::CreateClientForAccount(
|
| - const std::string& account_id) {
|
| - const em::PolicyData* policy_data = device_settings_service_->policy_data();
|
| - if (!policy_data ||
|
| - !policy_data->has_request_token() ||
|
| - !policy_data->has_device_id() ||
|
| - !device_management_service_) {
|
| - return scoped_ptr<CloudPolicyClient>();
|
| - }
|
| -
|
| - scoped_ptr<CloudPolicyClient> client(
|
| - new CloudPolicyClient(std::string(), std::string(),
|
| - USER_AFFILIATION_MANAGED,
|
| - NULL, device_management_service_));
|
| - client->SetupRegistration(policy_data->request_token(),
|
| - policy_data->device_id());
|
| - return client.Pass();
|
| -}
|
| -
|
| } // namespace policy
|
|
|