device_local_account_policy_service.cc revision f2477e01787aa58f445919b809d89e252beef54f
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <vector> 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/bind.h" 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/file_util.h" 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/files/file_enumerator.h" 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/files/file_path.h" 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/logging.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/message_loop/message_loop.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/path_service.h" 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/sequenced_task_runner.h" 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_external_data_service.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h" 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_service.h" 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_client.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_constants.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/policy/cloud/device_management_service.h" 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chromeos/chromeos_paths.h" 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chromeos/dbus/session_manager_client.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h" 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chromeos/settings/cros_settings_provider.h" 32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "net/url_request/url_request_context_getter.h" 33f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "policy/policy_constants.h" 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace em = enterprise_management; 369e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace policy { 387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 39e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)namespace { 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// Creates and initializes a cloud policy client. Returns NULL if the device 425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// doesn't have credentials in device settings (i.e. is not 43f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// enterprise-enrolled). 44591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochscoped_ptr<CloudPolicyClient> CreateClient( 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chromeos::DeviceSettingsService* device_settings_service, 4651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) DeviceManagementService* device_management_service) { 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const em::PolicyData* policy_data = device_settings_service->policy_data(); 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!policy_data || 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !policy_data->has_request_token() || 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !policy_data->has_device_id() || 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !device_management_service) { 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return scoped_ptr<CloudPolicyClient>(); 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_ptr<CloudPolicyClient> client( 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) new CloudPolicyClient(std::string(), std::string(), 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) USER_AFFILIATION_MANAGED, 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) NULL, device_management_service)); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) client->SetupRegistration(policy_data->request_token(), 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) policy_data->device_id()); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return client.Pass(); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Get the subdirectory of the cache directory in which force-installed 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// extensions are cached for |account_id|. 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)std::string GetCacheSubdirectoryForAccountID(const std::string& account_id) { 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return base::HexEncode(account_id.c_str(), account_id.size()); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Cleans up the cache directory by removing subdirectories that are not found 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// in |subdirectories_to_keep|. Only caches whose cache directory is found in 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// |subdirectories_to_keep| may be running while the clean-up is in progress. 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DeleteOrphanedExtensionCaches( 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const std::set<std::string>& subdirectories_to_keep) { 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) base::FilePath cache_root_dir; 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) &cache_root_dir)); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) base::FileEnumerator enumerator(cache_root_dir, 79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) false, 80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) base::FileEnumerator::DIRECTORIES); 811fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch for (base::FilePath path = enumerator.Next(); !path.empty(); 821fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch path = enumerator.Next()) { 837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const std::string subdirectory(path.BaseName().MaybeAsASCII()); 84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (subdirectories_to_keep.find(subdirectory) == 85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) subdirectories_to_keep.end()) { 86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) base::DeleteFile(path, true); 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Removes the subdirectory belonging to |account_id_to_delete| from the cache 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// directory. No cache belonging to |account_id_to_delete| may be running while 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// the removal is in progress. 941fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdochvoid DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) { 951fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch base::FilePath cache_root_dir; 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, 9751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) &cache_root_dir)); 9851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) const base::FilePath path = cache_root_dir 9951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) .Append(GetCacheSubdirectoryForAccountID(account_id_to_delete)); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (base::DirectoryExists(path)) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) base::DeleteFile(path, true); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 106197021e6b966cfb06891637935ef33fff06433d1Ben MurdochDeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker( 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const DeviceLocalAccount& account, 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_ptr<DeviceLocalAccountPolicyStore> store, 109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager, 110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const scoped_refptr<base::SequencedTaskRunner>& task_runner) 11181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) : account_id_(account.account_id), 11281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) user_id_(account.user_id), 11381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) store_(store.Pass()), 11481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) external_data_manager_(external_data_manager), 115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType, 116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) store_->account_id()), 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) store_.get(), 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) task_runner) { 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) base::FilePath cache_root_dir; 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS, 121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch &cache_root_dir)); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader( 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) store_.get(), 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cache_root_dir.Append( 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GetCacheSubdirectoryForAccountID(account.account_id))); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 128197021e6b966cfb06891637935ef33fff06433d1Ben MurdochDeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() { 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) external_data_manager_->SetPolicyStore(NULL); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) external_data_manager_->Disconnect(); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DeviceLocalAccountPolicyBroker::Initialize() { 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) store_->Load(); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void DeviceLocalAccountPolicyBroker::ConnectIfPossible( 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chromeos::DeviceSettingsService* device_settings_service, 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DeviceManagementService* device_management_service, 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context) { 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (core_.client()) 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 143e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 1449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) scoped_ptr<CloudPolicyClient> client(CreateClient(device_settings_service, 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) device_management_service)); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!client) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) core_.Connect(client.Pass()); 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) external_data_manager_->Connect(request_context); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) core_.StartRefreshScheduler(); 152f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) UpdateRefreshDelay(); 153f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)} 154f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 155f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() { 156f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (core_.refresh_scheduler()) { 1579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) const Value* policy_value = 158f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) store_->policy_map().GetValue(key::kPolicyRefreshRate); 159f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) int delay = 0; 160f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (policy_value && policy_value->GetAsInteger(&delay)) 161f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) core_.refresh_scheduler()->SetRefreshDelay(delay); 162f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) } 163f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)} 164f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 165f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const { 166f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) std::string display_name; 167f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) const base::Value* display_name_value = 168323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) store_->policy_map().GetValue(policy::key::kUserDisplayName); 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (display_name_value) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) display_name_value->GetAsString(&display_name); 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return display_name; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 173323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService( 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chromeos::SessionManagerClient* session_manager_client, 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chromeos::DeviceSettingsService* device_settings_service, 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) chromeos::CrosSettings* cros_settings, 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> store_background_task_runner, 179323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> extension_cache_task_runner, 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> 181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) external_data_service_backend_task_runner, 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> io_task_runner, 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context) 18451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) : session_manager_client_(session_manager_client), 185 device_settings_service_(device_settings_service), 186 cros_settings_(cros_settings), 187 device_management_service_(NULL), 188 waiting_for_cros_settings_(false), 189 orphan_cache_deletion_state_(NOT_STARTED), 190 store_background_task_runner_(store_background_task_runner), 191 extension_cache_task_runner_(extension_cache_task_runner), 192 request_context_(request_context), 193 local_accounts_subscription_(cros_settings_->AddSettingsObserver( 194 chromeos::kAccountsPrefDeviceLocalAccounts, 195 base::Bind(&DeviceLocalAccountPolicyService:: 196 UpdateAccountListIfNonePending, 197 base::Unretained(this)))), 198 weak_factory_(this) { 199 external_data_service_.reset(new DeviceLocalAccountExternalDataService( 200 this, 201 external_data_service_backend_task_runner, 202 io_task_runner)); 203 UpdateAccountList(); 204} 205 206DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() { 207 DCHECK(!request_context_); 208 DCHECK(policy_brokers_.empty()); 209} 210 211void DeviceLocalAccountPolicyService::Shutdown() { 212 device_management_service_ = NULL; 213 request_context_ = NULL; 214 DeleteBrokers(&policy_brokers_); 215} 216 217void DeviceLocalAccountPolicyService::Connect( 218 DeviceManagementService* device_management_service) { 219 DCHECK(!device_management_service_); 220 device_management_service_ = device_management_service; 221 222 // Connect the brokers. 223 for (PolicyBrokerMap::iterator it(policy_brokers_.begin()); 224 it != policy_brokers_.end(); ++it) { 225 it->second->ConnectIfPossible(device_settings_service_, 226 device_management_service_, 227 request_context_); 228 } 229} 230 231DeviceLocalAccountPolicyBroker* 232 DeviceLocalAccountPolicyService::GetBrokerForUser( 233 const std::string& user_id) { 234 PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id); 235 if (entry == policy_brokers_.end()) 236 return NULL; 237 238 return entry->second; 239} 240 241bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser( 242 const std::string& user_id) { 243 DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id); 244 return broker && broker->core()->store()->is_managed(); 245} 246 247void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) { 248 observers_.AddObserver(observer); 249} 250 251void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) { 252 observers_.RemoveObserver(observer); 253} 254 255void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) { 256 DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store); 257 DCHECK(broker); 258 if (!broker) 259 return; 260 broker->UpdateRefreshDelay(); 261 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id())); 262} 263 264void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) { 265 DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store); 266 DCHECK(broker); 267 if (!broker) 268 return; 269 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id())); 270} 271 272bool DeviceLocalAccountPolicyService::IsExtensionCacheDirectoryBusy( 273 const std::string& account_id) { 274 return busy_extension_cache_directories_.find(account_id) != 275 busy_extension_cache_directories_.end(); 276} 277 278void DeviceLocalAccountPolicyService::StartExtensionCachesIfPossible() { 279 for (PolicyBrokerMap::iterator it = policy_brokers_.begin(); 280 it != policy_brokers_.end(); ++it) { 281 if (!it->second->extension_loader()->IsCacheRunning() && 282 !IsExtensionCacheDirectoryBusy(it->second->account_id())) { 283 it->second->extension_loader()->StartCache(extension_cache_task_runner_); 284 } 285 } 286} 287 288bool DeviceLocalAccountPolicyService::StartExtensionCacheForAccountIfPresent( 289 const std::string& account_id) { 290 for (PolicyBrokerMap::iterator it = policy_brokers_.begin(); 291 it != policy_brokers_.end(); ++it) { 292 if (it->second->account_id() == account_id) { 293 DCHECK(!it->second->extension_loader()->IsCacheRunning()); 294 it->second->extension_loader()->StartCache(extension_cache_task_runner_); 295 return true; 296 } 297 } 298 return false; 299} 300 301void DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted() { 302 DCHECK_EQ(IN_PROGRESS, orphan_cache_deletion_state_); 303 304 orphan_cache_deletion_state_ = DONE; 305 StartExtensionCachesIfPossible(); 306} 307 308void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown( 309 const std::string& account_id) { 310 DCHECK_NE(NOT_STARTED, orphan_cache_deletion_state_); 311 DCHECK(IsExtensionCacheDirectoryBusy(account_id)); 312 313 // The account with |account_id| was deleted and the broker for it has shut 314 // down completely. 315 316 if (StartExtensionCacheForAccountIfPresent(account_id)) { 317 // If another account with the same ID was created in the meantime, its 318 // extension cache is started, reusing the cache directory. The directory no 319 // longer needs to be marked as busy in this case. 320 busy_extension_cache_directories_.erase(account_id); 321 return; 322 } 323 324 // If no account with |account_id| exists anymore, the cache directory should 325 // be removed. The directory must stay marked as busy while the removal is in 326 // progress. 327 extension_cache_task_runner_->PostTaskAndReply( 328 FROM_HERE, 329 base::Bind(&DeleteObsoleteExtensionCache, account_id), 330 base::Bind(&DeviceLocalAccountPolicyService:: 331 OnObsoleteExtensionCacheDeleted, 332 weak_factory_.GetWeakPtr(), 333 account_id)); 334} 335 336void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheDeleted( 337 const std::string& account_id) { 338 DCHECK_EQ(DONE, orphan_cache_deletion_state_); 339 DCHECK(IsExtensionCacheDirectoryBusy(account_id)); 340 341 // The cache directory for |account_id| has been deleted. The directory no 342 // longer needs to be marked as busy. 343 busy_extension_cache_directories_.erase(account_id); 344 345 // If another account with the same ID was created in the meantime, start its 346 // extension cache, creating a new cache directory. 347 StartExtensionCacheForAccountIfPresent(account_id); 348} 349 350void DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending() { 351 // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still 352 // pending (because the |cros_settings_| are not trusted yet), the updated 353 // account list will be processed by that call when it eventually runs. 354 if (!waiting_for_cros_settings_) 355 UpdateAccountList(); 356} 357 358void DeviceLocalAccountPolicyService::UpdateAccountList() { 359 chromeos::CrosSettingsProvider::TrustedStatus status = 360 cros_settings_->PrepareTrustedValues( 361 base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList, 362 weak_factory_.GetWeakPtr())); 363 switch (status) { 364 case chromeos::CrosSettingsProvider::TRUSTED: 365 waiting_for_cros_settings_ = false; 366 break; 367 case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED: 368 waiting_for_cros_settings_ = true; 369 return; 370 case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED: 371 waiting_for_cros_settings_ = false; 372 return; 373 } 374 375 // Update |policy_brokers_|, keeping existing entries. 376 PolicyBrokerMap old_policy_brokers; 377 policy_brokers_.swap(old_policy_brokers); 378 std::set<std::string> subdirectories_to_keep; 379 const std::vector<DeviceLocalAccount> device_local_accounts = 380 GetDeviceLocalAccounts(cros_settings_); 381 for (std::vector<DeviceLocalAccount>::const_iterator it = 382 device_local_accounts.begin(); 383 it != device_local_accounts.end(); ++it) { 384 PolicyBrokerMap::iterator broker_it = old_policy_brokers.find(it->user_id); 385 386 scoped_ptr<DeviceLocalAccountPolicyBroker> broker; 387 bool broker_initialized = false; 388 if (broker_it != old_policy_brokers.end()) { 389 // Reuse the existing broker if present. 390 broker.reset(broker_it->second); 391 old_policy_brokers.erase(broker_it); 392 broker_initialized = true; 393 } else { 394 scoped_ptr<DeviceLocalAccountPolicyStore> store( 395 new DeviceLocalAccountPolicyStore(it->account_id, 396 session_manager_client_, 397 device_settings_service_, 398 store_background_task_runner_)); 399 store->AddObserver(this); 400 scoped_refptr<DeviceLocalAccountExternalDataManager> 401 external_data_manager = 402 external_data_service_->GetExternalDataManager(it->account_id, 403 store.get()); 404 broker.reset(new DeviceLocalAccountPolicyBroker( 405 *it, 406 store.Pass(), 407 external_data_manager, 408 base::MessageLoopProxy::current())); 409 } 410 411 // Fire up the cloud connection for fetching policy for the account from 412 // the cloud if this is an enterprise-managed device. 413 broker->ConnectIfPossible(device_settings_service_, 414 device_management_service_, 415 request_context_); 416 417 policy_brokers_[it->user_id] = broker.release(); 418 if (!broker_initialized) { 419 // The broker must be initialized after it has been added to 420 // |policy_brokers_|. 421 policy_brokers_[it->user_id]->Initialize(); 422 } 423 424 if (orphan_cache_deletion_state_ == NOT_STARTED) { 425 subdirectories_to_keep.insert( 426 GetCacheSubdirectoryForAccountID(it->account_id)); 427 } 428 } 429 430 std::set<std::string> obsolete_account_ids; 431 for (PolicyBrokerMap::const_iterator it = old_policy_brokers.begin(); 432 it != old_policy_brokers.end(); ++it) { 433 obsolete_account_ids.insert(it->second->account_id()); 434 } 435 436 if (orphan_cache_deletion_state_ == NOT_STARTED) { 437 DCHECK(old_policy_brokers.empty()); 438 DCHECK(busy_extension_cache_directories_.empty()); 439 440 // If this method is running for the first time, no extension caches have 441 // been started yet. Take this opportunity to do a clean-up by removing 442 // orphaned cache directories not found in |subdirectories_to_keep| from the 443 // cache directory. 444 orphan_cache_deletion_state_ = IN_PROGRESS; 445 extension_cache_task_runner_->PostTaskAndReply( 446 FROM_HERE, 447 base::Bind(&DeleteOrphanedExtensionCaches, subdirectories_to_keep), 448 base::Bind(&DeviceLocalAccountPolicyService:: 449 OnOrphanedExtensionCachesDeleted, 450 weak_factory_.GetWeakPtr())); 451 452 // Start the extension caches for all brokers. These belong to accounts in 453 // |account_ids| and are not affected by the clean-up. 454 StartExtensionCachesIfPossible(); 455 } else { 456 // If this method has run before, obsolete brokers may exist. Shut down 457 // their extension caches and delete the brokers. 458 DeleteBrokers(&old_policy_brokers); 459 460 if (orphan_cache_deletion_state_ == DONE) { 461 // If the initial clean-up of orphaned cache directories has been 462 // complete, start any extension caches that are not running yet but can 463 // be started now because their cache directories are not busy. 464 StartExtensionCachesIfPossible(); 465 } 466 } 467 468 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged()); 469} 470 471void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) { 472 for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it) { 473 it->second->core()->store()->RemoveObserver(this); 474 scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader> 475 extension_loader = it->second->extension_loader(); 476 if (extension_loader->IsCacheRunning()) { 477 DCHECK(!IsExtensionCacheDirectoryBusy(it->second->account_id())); 478 busy_extension_cache_directories_.insert(it->second->account_id()); 479 extension_loader->StopCache(base::Bind( 480 &DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown, 481 weak_factory_.GetWeakPtr(), 482 it->second->account_id())); 483 } 484 delete it->second; 485 } 486 map->clear(); 487} 488 489DeviceLocalAccountPolicyBroker* 490 DeviceLocalAccountPolicyService::GetBrokerForStore( 491 CloudPolicyStore* store) { 492 for (PolicyBrokerMap::iterator it(policy_brokers_.begin()); 493 it != policy_brokers_.end(); ++it) { 494 if (it->second->core()->store() == store) 495 return it->second; 496 } 497 return NULL; 498} 499 500} // namespace policy 501