Chromium Code Reviews| 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..ee167fc0ad2355048e58bb73b8c37d2d86320e47 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,61 @@ 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) |
|
Mattias Nissler (ping if slow)
2013/05/17 14:29:44
Hm, could as well do if(client) connect
bartfab (slow)
2013/05/17 16:08:47
Done.
|
| + return; |
| + 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 +179,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 +190,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 +220,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 +290,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 |