Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/chromeos/policy/device_local_account.h"
     14 #include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
     15 #include "chrome/browser/chromeos/settings/cros_settings.h"
     16 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
     17 #include "chrome/browser/chromeos/settings/cros_settings_provider.h"
     18 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     19 #include "chrome/browser/policy/cloud/cloud_policy_client.h"
     20 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
     21 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
     22 #include "chrome/browser/policy/cloud/device_management_service.h"
     23 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
     24 #include "chromeos/dbus/session_manager_client.h"
     25 #include "content/public/browser/notification_details.h"
     26 #include "policy/policy_constants.h"
     27 
     28 namespace em = enterprise_management;
     29 
     30 namespace policy {
     31 
     32 namespace {
     33 
     34 // Creates a broker for the device-local account with the given |user_id| and
     35 // |account_id|.
     36 scoped_ptr<DeviceLocalAccountPolicyBroker> CreateBroker(
     37     const std::string& user_id,
     38     const std::string& account_id,
     39     chromeos::SessionManagerClient* session_manager_client,
     40     chromeos::DeviceSettingsService* device_settings_service,
     41     DeviceLocalAccountPolicyService* device_local_account_policy_service) {
     42   scoped_ptr<DeviceLocalAccountPolicyStore> store(
     43       new DeviceLocalAccountPolicyStore(account_id, session_manager_client,
     44                                         device_settings_service));
     45   scoped_ptr<DeviceLocalAccountPolicyBroker> broker(
     46       new DeviceLocalAccountPolicyBroker(user_id, store.Pass()));
     47   broker->core()->store()->AddObserver(device_local_account_policy_service);
     48   broker->core()->store()->Load();
     49   return broker.Pass();
     50 }
     51 
     52 // Creates and initializes a cloud policy client. Returns NULL if the device
     53 // doesn't have credentials in device settings (i.e. is not
     54 // enterprise-enrolled).
     55 scoped_ptr<CloudPolicyClient> CreateClient(
     56     chromeos::DeviceSettingsService* device_settings_service,
     57     DeviceManagementService* device_management_service) {
     58   const em::PolicyData* policy_data = device_settings_service->policy_data();
     59   if (!policy_data ||
     60       !policy_data->has_request_token() ||
     61       !policy_data->has_device_id() ||
     62       !device_management_service) {
     63     return scoped_ptr<CloudPolicyClient>();
     64   }
     65 
     66   scoped_ptr<CloudPolicyClient> client(
     67       new CloudPolicyClient(std::string(), std::string(),
     68                             USER_AFFILIATION_MANAGED,
     69                             NULL, device_management_service));
     70   client->SetupRegistration(policy_data->request_token(),
     71                             policy_data->device_id());
     72   return client.Pass();
     73 }
     74 
     75 }  // namespace
     76 
     77 DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
     78     const std::string& user_id,
     79     scoped_ptr<DeviceLocalAccountPolicyStore> store)
     80     : user_id_(user_id),
     81       store_(store.Pass()),
     82       core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
     83                                store_->account_id()),
     84             store_.get()) {}
     85 
     86 DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {}
     87 
     88 void DeviceLocalAccountPolicyBroker::Connect(
     89     scoped_ptr<CloudPolicyClient> client) {
     90   core_.Connect(client.Pass());
     91   core_.StartRefreshScheduler();
     92   UpdateRefreshDelay();
     93 }
     94 
     95 void DeviceLocalAccountPolicyBroker::Disconnect() {
     96   core_.Disconnect();
     97 }
     98 
     99 void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
    100   if (core_.refresh_scheduler()) {
    101     const Value* policy_value =
    102         store_->policy_map().GetValue(key::kPolicyRefreshRate);
    103     int delay = 0;
    104     if (policy_value && policy_value->GetAsInteger(&delay))
    105       core_.refresh_scheduler()->SetRefreshDelay(delay);
    106   }
    107 }
    108 
    109 std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
    110   std::string display_name;
    111   const base::Value* display_name_value =
    112       store_->policy_map().GetValue(policy::key::kUserDisplayName);
    113   if (display_name_value)
    114     display_name_value->GetAsString(&display_name);
    115   return display_name;
    116 }
    117 
    118 DeviceLocalAccountPolicyService::PolicyBrokerWrapper::PolicyBrokerWrapper()
    119     : parent(NULL), broker(NULL) {}
    120 
    121 DeviceLocalAccountPolicyBroker*
    122     DeviceLocalAccountPolicyService::PolicyBrokerWrapper::GetBroker() {
    123   if (!broker) {
    124     broker = CreateBroker(user_id, account_id,
    125                           parent->session_manager_client_,
    126                           parent->device_settings_service_,
    127                           parent).release();
    128   }
    129   return broker;
    130 }
    131 
    132 void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::ConnectIfPossible() {
    133   if (broker && broker->core()->client())
    134     return;
    135   scoped_ptr<CloudPolicyClient> client(CreateClient(
    136       parent->device_settings_service_,
    137       parent->device_management_service_));
    138   if (client)
    139     GetBroker()->Connect(client.Pass());
    140 }
    141 
    142 void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::Disconnect() {
    143   if (broker)
    144     broker->Disconnect();
    145 }
    146 
    147 void DeviceLocalAccountPolicyService::PolicyBrokerWrapper::DeleteBroker() {
    148   if (!broker)
    149     return;
    150   broker->core()->store()->RemoveObserver(parent);
    151   delete broker;
    152   broker = NULL;
    153 }
    154 
    155 DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
    156     chromeos::SessionManagerClient* session_manager_client,
    157     chromeos::DeviceSettingsService* device_settings_service,
    158     chromeos::CrosSettings* cros_settings)
    159     : session_manager_client_(session_manager_client),
    160       device_settings_service_(device_settings_service),
    161       cros_settings_(cros_settings),
    162       device_management_service_(NULL),
    163       cros_settings_callback_factory_(this) {
    164   cros_settings_->AddSettingsObserver(
    165       chromeos::kAccountsPrefDeviceLocalAccounts, this);
    166   UpdateAccountList();
    167 }
    168 
    169 DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
    170   cros_settings_->RemoveSettingsObserver(
    171       chromeos::kAccountsPrefDeviceLocalAccounts, this);
    172   DeleteBrokers(&policy_brokers_);
    173 }
    174 
    175 void DeviceLocalAccountPolicyService::Connect(
    176     DeviceManagementService* device_management_service) {
    177   DCHECK(!device_management_service_);
    178   device_management_service_ = device_management_service;
    179 
    180   // Connect the brokers.
    181   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
    182        it != policy_brokers_.end(); ++it) {
    183     it->second.ConnectIfPossible();
    184   }
    185 }
    186 
    187 void DeviceLocalAccountPolicyService::Disconnect() {
    188   DCHECK(device_management_service_);
    189   device_management_service_ = NULL;
    190 
    191   // Disconnect the brokers.
    192   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
    193        it != policy_brokers_.end(); ++it) {
    194     it->second.Disconnect();
    195   }
    196 }
    197 
    198 DeviceLocalAccountPolicyBroker*
    199     DeviceLocalAccountPolicyService::GetBrokerForUser(
    200         const std::string& user_id) {
    201   PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
    202   if (entry == policy_brokers_.end())
    203     return NULL;
    204 
    205   return entry->second.GetBroker();
    206 }
    207 
    208 bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
    209     const std::string& user_id) {
    210   DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
    211   return broker && broker->core()->store()->is_managed();
    212 }
    213 
    214 void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
    215   observers_.AddObserver(observer);
    216 }
    217 
    218 void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
    219   observers_.RemoveObserver(observer);
    220 }
    221 
    222 void DeviceLocalAccountPolicyService::Observe(
    223     int type,
    224     const content::NotificationSource& source,
    225     const content::NotificationDetails& details) {
    226   if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED ||
    227       *content::Details<const std::string>(details).ptr() !=
    228           chromeos::kAccountsPrefDeviceLocalAccounts) {
    229     NOTREACHED();
    230     return;
    231   }
    232 
    233   // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
    234   // pending (because the |cros_settings_| are not trusted yet), the updated
    235   // account list will be processed by that call when it eventually runs.
    236   if (!cros_settings_callback_factory_.HasWeakPtrs())
    237     UpdateAccountList();
    238 }
    239 
    240 void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
    241   DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
    242   DCHECK(broker);
    243   if (!broker)
    244     return;
    245   broker->UpdateRefreshDelay();
    246   FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
    247 }
    248 
    249 void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) {
    250   DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
    251   DCHECK(broker);
    252   if (!broker)
    253     return;
    254   FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
    255 }
    256 
    257 void DeviceLocalAccountPolicyService::UpdateAccountList() {
    258   if (chromeos::CrosSettingsProvider::TRUSTED !=
    259           cros_settings_->PrepareTrustedValues(
    260               base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
    261                          cros_settings_callback_factory_.GetWeakPtr()))) {
    262     return;
    263   }
    264 
    265   // Update |policy_brokers_|, keeping existing entries.
    266   PolicyBrokerMap new_policy_brokers;
    267   const std::vector<DeviceLocalAccount> device_local_accounts =
    268       GetDeviceLocalAccounts(cros_settings_);
    269   for (std::vector<DeviceLocalAccount>::const_iterator it =
    270            device_local_accounts.begin();
    271        it != device_local_accounts.end(); ++it) {
    272     PolicyBrokerWrapper& wrapper = new_policy_brokers[it->user_id];
    273     wrapper.user_id = it->user_id;
    274     wrapper.account_id = it->account_id;
    275     wrapper.parent = this;
    276 
    277     // Reuse the existing broker if present.
    278     PolicyBrokerWrapper& existing_wrapper = policy_brokers_[it->user_id];
    279     wrapper.broker = existing_wrapper.broker;
    280     existing_wrapper.broker = NULL;
    281 
    282     // Fire up the cloud connection for fetching policy for the account from
    283     // the cloud if this is an enterprise-managed device.
    284     wrapper.ConnectIfPossible();
    285   }
    286   policy_brokers_.swap(new_policy_brokers);
    287   DeleteBrokers(&new_policy_brokers);
    288 
    289   FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
    290 }
    291 
    292 void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
    293   for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it)
    294     it->second.DeleteBroker();
    295   map->clear();
    296 }
    297 
    298 DeviceLocalAccountPolicyBroker*
    299     DeviceLocalAccountPolicyService::GetBrokerForStore(
    300         CloudPolicyStore* store) {
    301   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
    302        it != policy_brokers_.end(); ++it) {
    303     if (it->second.broker && it->second.broker->core()->store() == store)
    304       return it->second.broker;
    305   }
    306   return NULL;
    307 }
    308 
    309 }  // namespace policy
    310