12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h"
106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/bind_helpers.h"
116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/command_line.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/files/file_enumerator.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/path_service.h"
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/sequenced_task_runner.h"
196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/stl_util.h"
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/browser_process.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_external_data_service.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_service.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/chrome_content_client.h"
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chromeos/chromeos_paths.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/session_manager_client.h"
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_provider.h"
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/policy/core/browser/browser_policy_connector.h"
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_client.h"
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_constants.h"
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/device_management_service.h"
366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/policy/core/common/cloud/resource_cache.h"
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/system_policy_request_context.h"
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/policy/core/common/policy_namespace.h"
396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/policy/core/common/policy_switches.h"
406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "policy/policy_constants.h"
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/device_management_backend.pb.h"
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h"
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace em = enterprise_management;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace policy {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Creates and initializes a cloud policy client. Returns NULL if the device
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// doesn't have credentials in device settings (i.e. is not
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// enterprise-enrolled).
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_ptr<CloudPolicyClient> CreateClient(
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    chromeos::DeviceSettingsService* device_settings_service,
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceManagementService* device_management_service,
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> system_request_context) {
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const em::PolicyData* policy_data = device_settings_service->policy_data();
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!policy_data ||
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !policy_data->has_request_token() ||
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !policy_data->has_device_id() ||
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !device_management_service) {
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return scoped_ptr<CloudPolicyClient>();
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> request_context =
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new SystemPolicyRequestContext(
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          system_request_context, GetUserAgent());
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<CloudPolicyClient> client(
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new CloudPolicyClient(std::string(), std::string(),
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            kPolicyVerificationKeyHash,
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            USER_AFFILIATION_MANAGED,
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            NULL, device_management_service, request_context));
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  client->SetupRegistration(policy_data->request_token(),
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            policy_data->device_id());
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return client.Pass();
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Get the subdirectory of the force-installed extension cache and the component
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// policy cache used for |account_id|.
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::string GetCacheSubdirectoryForAccountID(const std::string& account_id) {
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return base::HexEncode(account_id.c_str(), account_id.size());
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Cleans up the cache directory by removing subdirectories that are not found
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// in |subdirectories_to_keep|. Only caches whose cache directory is found in
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// |subdirectories_to_keep| may be running while the clean-up is in progress.
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeleteOrphanedCaches(
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const base::FilePath& cache_root_dir,
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::set<std::string>& subdirectories_to_keep) {
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::FileEnumerator enumerator(cache_root_dir,
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                  false,
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                  base::FileEnumerator::DIRECTORIES);
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (base::FilePath path = enumerator.Next(); !path.empty();
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       path = enumerator.Next()) {
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string subdirectory(path.BaseName().MaybeAsASCII());
996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (!ContainsKey(subdirectories_to_keep, subdirectory))
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::DeleteFile(path, true);
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Removes the subdirectory belonging to |account_id_to_delete| from the cache
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// directory. No cache belonging to |account_id_to_delete| may be running while
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// the removal is in progress.
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) {
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::FilePath cache_root_dir;
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         &cache_root_dir));
1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  const base::FilePath path = cache_root_dir.Append(
1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      GetCacheSubdirectoryForAccountID(account_id_to_delete));
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (base::DirectoryExists(path))
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    base::DeleteFile(path, true);
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const DeviceLocalAccount& account,
1216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const base::FilePath& component_policy_cache_path,
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    scoped_ptr<DeviceLocalAccountPolicyStore> store,
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager,
1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const base::Closure& policy_update_callback,
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& task_runner)
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : account_id_(account.account_id),
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      user_id_(account.user_id),
1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      component_policy_cache_path_(component_policy_cache_path),
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      store_(store.Pass()),
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_tracker_(account, store_.get(), &schema_registry_),
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      external_data_manager_(external_data_manager),
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               store_->account_id()),
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            store_.get(),
1356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            task_runner),
1366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      policy_update_callback_(policy_update_callback) {
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::FilePath cache_root_dir;
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         &cache_root_dir));
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader(
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      store_.get(),
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      cache_root_dir.Append(
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          GetCacheSubdirectoryForAccountID(account.account_id)));
1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  store_->AddObserver(this);
1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Unblock the |schema_registry_| so that the |component_policy_service_|
1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // starts using it.
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  schema_registry_.RegisterComponent(
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      g_browser_process->browser_policy_connector()->GetChromeSchema());
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  schema_registry_.SetReady(POLICY_DOMAIN_CHROME);
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  schema_registry_.SetReady(POLICY_DOMAIN_EXTENSIONS);
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  store_->RemoveObserver(this);
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_data_manager_->SetPolicyStore(NULL);
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_data_manager_->Disconnect();
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyBroker::Initialize() {
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  store_->Load();
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyBroker::ConnectIfPossible(
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    chromeos::DeviceSettingsService* device_settings_service,
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DeviceManagementService* device_management_service,
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> request_context) {
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (core_.client())
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<CloudPolicyClient> client(CreateClient(device_settings_service,
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    device_management_service,
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                    request_context));
1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!client)
1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core_.Connect(client.Pass());
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_data_manager_->Connect(request_context);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  core_.StartRefreshScheduler();
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateRefreshDelay();
1826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  CreateComponentCloudPolicyService(request_context);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (core_.refresh_scheduler()) {
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Value* policy_value =
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        store_->policy_map().GetValue(key::kPolicyRefreshRate);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int delay = 0;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (policy_value && policy_value->GetAsInteger(&delay))
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      core_.refresh_scheduler()->SetRefreshDelay(delay);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string display_name;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* display_name_value =
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      store_->policy_map().GetValue(policy::key::kUserDisplayName);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (display_name_value)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    display_name_value->GetAsString(&display_name);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return display_name;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeviceLocalAccountPolicyBroker::OnStoreLoaded(CloudPolicyStore* store) {
2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateRefreshDelay();
2066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  policy_update_callback_.Run();
2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeviceLocalAccountPolicyBroker::OnStoreError(CloudPolicyStore* store) {
2106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  policy_update_callback_.Run();
2116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeviceLocalAccountPolicyBroker::OnComponentCloudPolicyUpdated() {
2146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  policy_update_callback_.Run();
2156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeviceLocalAccountPolicyBroker::CreateComponentCloudPolicyService(
2186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const scoped_refptr<net::URLRequestContextGetter>& request_context) {
2196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
2206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          switches::kDisableComponentCloudPolicy)) {
2216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Disabled via the command line.
2226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
2236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
2246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  scoped_ptr<ResourceCache> resource_cache(
2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      new ResourceCache(component_policy_cache_path_,
2276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                        content::BrowserThread::GetMessageLoopProxyForThread(
2286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                            content::BrowserThread::FILE)));
2296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  component_policy_service_.reset(new ComponentCloudPolicyService(
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      this,
2326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      &schema_registry_,
2336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      core(),
2346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      resource_cache.Pass(),
2356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      request_context,
2366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      content::BrowserThread::GetMessageLoopProxyForThread(
2376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          content::BrowserThread::FILE),
2386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      content::BrowserThread::GetMessageLoopProxyForThread(
2396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          content::BrowserThread::IO)));
2406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
2416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chromeos::SessionManagerClient* session_manager_client,
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    chromeos::DeviceSettingsService* device_settings_service,
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    chromeos::CrosSettings* cros_settings,
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> store_background_task_runner,
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> extension_cache_task_runner,
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner>
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        external_data_service_backend_task_runner,
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> io_task_runner,
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> request_context)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : session_manager_client_(session_manager_client),
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      device_settings_service_(device_settings_service),
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      cros_settings_(cros_settings),
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      device_management_service_(NULL),
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      waiting_for_cros_settings_(false),
2576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      orphan_extension_cache_deletion_state_(NOT_STARTED),
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      store_background_task_runner_(store_background_task_runner),
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      extension_cache_task_runner_(extension_cache_task_runner),
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      request_context_(request_context),
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      local_accounts_subscription_(cros_settings_->AddSettingsObserver(
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          chromeos::kAccountsPrefDeviceLocalAccounts,
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          base::Bind(&DeviceLocalAccountPolicyService::
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         UpdateAccountListIfNonePending,
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     base::Unretained(this)))),
2668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      weak_factory_(this) {
2676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_COMPONENT_POLICY,
2686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                         &component_policy_cache_root_));
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  external_data_service_.reset(new DeviceLocalAccountExternalDataService(
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this,
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      external_data_service_backend_task_runner,
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      io_task_runner));
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateAccountList();
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!request_context_.get());
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(policy_brokers_.empty());
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DeviceLocalAccountPolicyService::Shutdown() {
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  device_management_service_ = NULL;
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  request_context_ = NULL;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeleteBrokers(&policy_brokers_);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceLocalAccountPolicyService::Connect(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DeviceManagementService* device_management_service) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!device_management_service_);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  device_management_service_ = device_management_service;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Connect the brokers.
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != policy_brokers_.end(); ++it) {
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    it->second->ConnectIfPossible(device_settings_service_,
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  device_management_service_,
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  request_context_);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceLocalAccountPolicyBroker*
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DeviceLocalAccountPolicyService::GetBrokerForUser(
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const std::string& user_id) {
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (entry == policy_brokers_.end())
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return entry->second;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& user_id) {
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return broker && broker->core()->store()->is_managed();
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool DeviceLocalAccountPolicyService::IsExtensionCacheDirectoryBusy(
3268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& account_id) {
3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return busy_extension_cache_directories_.find(account_id) !=
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            busy_extension_cache_directories_.end();
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyService::StartExtensionCachesIfPossible() {
3328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
3338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       it != policy_brokers_.end(); ++it) {
3348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!it->second->extension_loader()->IsCacheRunning() &&
3358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        !IsExtensionCacheDirectoryBusy(it->second->account_id())) {
3368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      it->second->extension_loader()->StartCache(extension_cache_task_runner_);
3378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool DeviceLocalAccountPolicyService::StartExtensionCacheForAccountIfPresent(
3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& account_id) {
3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       it != policy_brokers_.end(); ++it) {
3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (it->second->account_id() == account_id) {
3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      DCHECK(!it->second->extension_loader()->IsCacheRunning());
3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      it->second->extension_loader()->StartCache(extension_cache_task_runner_);
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return true;
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return false;
3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted() {
3556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK_EQ(IN_PROGRESS, orphan_extension_cache_deletion_state_);
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  orphan_extension_cache_deletion_state_ = DONE;
3588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  StartExtensionCachesIfPossible();
3598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown(
3628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& account_id) {
3636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK_NE(NOT_STARTED, orphan_extension_cache_deletion_state_);
3648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(IsExtensionCacheDirectoryBusy(account_id));
3658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The account with |account_id| was deleted and the broker for it has shut
3678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // down completely.
3688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (StartExtensionCacheForAccountIfPresent(account_id)) {
3708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If another account with the same ID was created in the meantime, its
3718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // extension cache is started, reusing the cache directory. The directory no
3728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // longer needs to be marked as busy in this case.
3738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    busy_extension_cache_directories_.erase(account_id);
3748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
3758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If no account with |account_id| exists anymore, the cache directory should
3788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // be removed. The directory must stay marked as busy while the removal is in
3798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // progress.
3808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  extension_cache_task_runner_->PostTaskAndReply(
3818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE,
3828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&DeleteObsoleteExtensionCache, account_id),
3838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(&DeviceLocalAccountPolicyService::
3848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     OnObsoleteExtensionCacheDeleted,
3858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                 account_id));
3878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheDeleted(
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& account_id) {
3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK_EQ(DONE, orphan_extension_cache_deletion_state_);
3928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(IsExtensionCacheDirectoryBusy(account_id));
3938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The cache directory for |account_id| has been deleted. The directory no
3958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // longer needs to be marked as busy.
3968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  busy_extension_cache_directories_.erase(account_id);
3978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If another account with the same ID was created in the meantime, start its
3998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // extension cache, creating a new cache directory.
4008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  StartExtensionCacheForAccountIfPresent(account_id);
4018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending() {
40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // pending (because the |cros_settings_| are not trusted yet), the updated
40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // account list will be processed by that call when it eventually runs.
4078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!waiting_for_cros_settings_)
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    UpdateAccountList();
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DeviceLocalAccountPolicyService::UpdateAccountList() {
4128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  chromeos::CrosSettingsProvider::TrustedStatus status =
4138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      cros_settings_->PrepareTrustedValues(
4148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
4158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     weak_factory_.GetWeakPtr()));
4168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  switch (status) {
4178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TRUSTED:
4188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      waiting_for_cros_settings_ = false;
4198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
4208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
4218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      waiting_for_cros_settings_ = true;
4228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
4238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
4248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      waiting_for_cros_settings_ = false;
4258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update |policy_brokers_|, keeping existing entries.
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PolicyBrokerMap old_policy_brokers;
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  policy_brokers_.swap(old_policy_brokers);
4318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::set<std::string> subdirectories_to_keep;
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::vector<DeviceLocalAccount> device_local_accounts =
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GetDeviceLocalAccounts(cros_settings_);
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (std::vector<DeviceLocalAccount>::const_iterator it =
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           device_local_accounts.begin();
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != device_local_accounts.end(); ++it) {
4378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    PolicyBrokerMap::iterator broker_it = old_policy_brokers.find(it->user_id);
4388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_ptr<DeviceLocalAccountPolicyBroker> broker;
4408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    bool broker_initialized = false;
4418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (broker_it != old_policy_brokers.end()) {
4428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // Reuse the existing broker if present.
4438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      broker.reset(broker_it->second);
4448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      old_policy_brokers.erase(broker_it);
4458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      broker_initialized = true;
4468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    } else {
4478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      scoped_ptr<DeviceLocalAccountPolicyStore> store(
4488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          new DeviceLocalAccountPolicyStore(it->account_id,
4498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                            session_manager_client_,
4508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                            device_settings_service_,
4518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                            store_background_task_runner_));
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      scoped_refptr<DeviceLocalAccountExternalDataManager>
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          external_data_manager =
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              external_data_service_->GetExternalDataManager(it->account_id,
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                             store.get());
4568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      broker.reset(new DeviceLocalAccountPolicyBroker(
4578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          *it,
4586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          component_policy_cache_root_.Append(
4596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)              GetCacheSubdirectoryForAccountID(it->account_id)),
4608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          store.Pass(),
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          external_data_manager,
4626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          base::Bind(&DeviceLocalAccountPolicyService::NotifyPolicyUpdated,
4636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     base::Unretained(this),
4646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                     it->user_id),
4658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          base::MessageLoopProxy::current()));
4668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Fire up the cloud connection for fetching policy for the account from
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // the cloud if this is an enterprise-managed device.
4708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    broker->ConnectIfPossible(device_settings_service_,
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              device_management_service_,
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              request_context_);
4738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    policy_brokers_[it->user_id] = broker.release();
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!broker_initialized) {
4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // The broker must be initialized after it has been added to
4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // |policy_brokers_|.
4788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      policy_brokers_[it->user_id]->Initialize();
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
4808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    subdirectories_to_keep.insert(
4826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        GetCacheSubdirectoryForAccountID(it->account_id));
4838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
4848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (orphan_extension_cache_deletion_state_ == NOT_STARTED) {
4868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DCHECK(old_policy_brokers.empty());
4878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DCHECK(busy_extension_cache_directories_.empty());
4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If this method is running for the first time, no extension caches have
4908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // been started yet. Take this opportunity to do a clean-up by removing
4918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // orphaned cache directories not found in |subdirectories_to_keep| from the
4928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // cache directory.
4936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    orphan_extension_cache_deletion_state_ = IN_PROGRESS;
4946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::FilePath cache_root_dir;
4966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
4976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                           &cache_root_dir));
4988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    extension_cache_task_runner_->PostTaskAndReply(
4998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        FROM_HERE,
5006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        base::Bind(
5016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            &DeleteOrphanedCaches, cache_root_dir, subdirectories_to_keep),
5026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        base::Bind(
5036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            &DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted,
5046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            weak_factory_.GetWeakPtr()));
5058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Start the extension caches for all brokers. These belong to accounts in
5078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // |account_ids| and are not affected by the clean-up.
5088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StartExtensionCachesIfPossible();
5098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else {
5108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If this method has run before, obsolete brokers may exist. Shut down
5118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // their extension caches and delete the brokers.
5128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DeleteBrokers(&old_policy_brokers);
5138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (orphan_extension_cache_deletion_state_ == DONE) {
5158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // If the initial clean-up of orphaned cache directories has been
5168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // complete, start any extension caches that are not running yet but can
5178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // be started now because their cache directories are not busy.
5188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      StartExtensionCachesIfPossible();
5198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Purge the component policy caches of any accounts that have been removed.
5236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Do this only after any obsolete brokers have been destroyed.
5246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // TODO(joaodasilva): for now this must be posted to the FILE thread,
5256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // to avoid racing with the ComponentCloudPolicyStore. Use a task runner
5266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // once that class supports another background thread too.
5276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
5286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                   base::Bind(&DeleteOrphanedCaches,
5296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                              component_policy_cache_root_,
5306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                              subdirectories_to_keep));
5316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it) {
5378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader>
5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        extension_loader = it->second->extension_loader();
5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (extension_loader->IsCacheRunning()) {
5408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      DCHECK(!IsExtensionCacheDirectoryBusy(it->second->account_id()));
5418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      busy_extension_cache_directories_.insert(it->second->account_id());
5428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      extension_loader->StopCache(base::Bind(
5438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          &DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown,
5448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          weak_factory_.GetWeakPtr(),
5458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          it->second->account_id()));
5468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete it->second;
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  map->clear();
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceLocalAccountPolicyBroker*
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DeviceLocalAccountPolicyService::GetBrokerForStore(
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CloudPolicyStore* store) {
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != policy_brokers_.end(); ++it) {
5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (it->second->core()->store() == store)
5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return it->second;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void DeviceLocalAccountPolicyService::NotifyPolicyUpdated(
5656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& user_id) {
5666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(user_id));
5676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace policy
570