Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / device_local_account_policy_service.cc
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/file_util.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/files/file_path.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/path_service.h"
17 #include "base/sequenced_task_runner.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chromeos/policy/device_local_account.h"
21 #include "chrome/browser/chromeos/policy/device_local_account_external_data_service.h"
22 #include "chrome/browser/chromeos/policy/device_local_account_policy_store.h"
23 #include "chrome/browser/chromeos/settings/device_settings_service.h"
24 #include "chromeos/chromeos_paths.h"
25 #include "chromeos/dbus/session_manager_client.h"
26 #include "chromeos/settings/cros_settings_names.h"
27 #include "chromeos/settings/cros_settings_provider.h"
28 #include "components/policy/core/common/cloud/cloud_policy_client.h"
29 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
30 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
31 #include "components/policy/core/common/cloud/device_management_service.h"
32 #include "components/policy/core/common/cloud/system_policy_request_context.h"
33 #include "content/public/common/content_client.h"
34 #include "net/url_request/url_request_context_getter.h"
35 #include "policy/policy_constants.h"
36 #include "policy/proto/device_management_backend.pb.h"
37 #include "url/gurl.h"
38
39 namespace em = enterprise_management;
40
41 namespace policy {
42
43 namespace {
44
45 // Creates and initializes a cloud policy client. Returns NULL if the device
46 // doesn't have credentials in device settings (i.e. is not
47 // enterprise-enrolled).
48 scoped_ptr<CloudPolicyClient> CreateClient(
49     chromeos::DeviceSettingsService* device_settings_service,
50     DeviceManagementService* device_management_service,
51     scoped_refptr<net::URLRequestContextGetter> system_request_context) {
52   const em::PolicyData* policy_data = device_settings_service->policy_data();
53   if (!policy_data ||
54       !policy_data->has_request_token() ||
55       !policy_data->has_device_id() ||
56       !device_management_service) {
57     return scoped_ptr<CloudPolicyClient>();
58   }
59
60   scoped_refptr<net::URLRequestContextGetter> request_context =
61       new SystemPolicyRequestContext(
62           system_request_context,
63           content::GetUserAgent(GURL(
64               device_management_service->GetServerUrl())));
65
66   scoped_ptr<CloudPolicyClient> client(
67       new CloudPolicyClient(std::string(), std::string(),
68                             kPolicyVerificationKeyHash,
69                             USER_AFFILIATION_MANAGED,
70                             NULL, device_management_service, request_context));
71   client->SetupRegistration(policy_data->request_token(),
72                             policy_data->device_id());
73   return client.Pass();
74 }
75
76 // Get the subdirectory of the cache directory in which force-installed
77 // extensions are cached for |account_id|.
78 std::string GetCacheSubdirectoryForAccountID(const std::string& account_id) {
79   return base::HexEncode(account_id.c_str(), account_id.size());
80 }
81
82 // Cleans up the cache directory by removing subdirectories that are not found
83 // in |subdirectories_to_keep|. Only caches whose cache directory is found in
84 // |subdirectories_to_keep| may be running while the clean-up is in progress.
85 void DeleteOrphanedExtensionCaches(
86     const std::set<std::string>& subdirectories_to_keep) {
87   base::FilePath cache_root_dir;
88   CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
89                          &cache_root_dir));
90   base::FileEnumerator enumerator(cache_root_dir,
91                                   false,
92                                   base::FileEnumerator::DIRECTORIES);
93   for (base::FilePath path = enumerator.Next(); !path.empty();
94        path = enumerator.Next()) {
95     const std::string subdirectory(path.BaseName().MaybeAsASCII());
96     if (subdirectories_to_keep.find(subdirectory) ==
97         subdirectories_to_keep.end()) {
98       base::DeleteFile(path, true);
99     }
100   }
101 }
102
103 // Removes the subdirectory belonging to |account_id_to_delete| from the cache
104 // directory. No cache belonging to |account_id_to_delete| may be running while
105 // the removal is in progress.
106 void DeleteObsoleteExtensionCache(const std::string& account_id_to_delete) {
107   base::FilePath cache_root_dir;
108   CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
109                          &cache_root_dir));
110   const base::FilePath path = cache_root_dir
111       .Append(GetCacheSubdirectoryForAccountID(account_id_to_delete));
112   if (base::DirectoryExists(path))
113     base::DeleteFile(path, true);
114 }
115
116 }  // namespace
117
118 DeviceLocalAccountPolicyBroker::DeviceLocalAccountPolicyBroker(
119     const DeviceLocalAccount& account,
120     scoped_ptr<DeviceLocalAccountPolicyStore> store,
121     scoped_refptr<DeviceLocalAccountExternalDataManager> external_data_manager,
122     const scoped_refptr<base::SequencedTaskRunner>& task_runner)
123     : account_id_(account.account_id),
124       user_id_(account.user_id),
125       store_(store.Pass()),
126       external_data_manager_(external_data_manager),
127       core_(PolicyNamespaceKey(dm_protocol::kChromePublicAccountPolicyType,
128                                store_->account_id()),
129             store_.get(),
130             task_runner) {
131   base::FilePath cache_root_dir;
132   CHECK(PathService::Get(chromeos::DIR_DEVICE_LOCAL_ACCOUNT_EXTENSIONS,
133                          &cache_root_dir));
134   extension_loader_ = new chromeos::DeviceLocalAccountExternalPolicyLoader(
135       store_.get(),
136       cache_root_dir.Append(
137           GetCacheSubdirectoryForAccountID(account.account_id)));
138 }
139
140 DeviceLocalAccountPolicyBroker::~DeviceLocalAccountPolicyBroker() {
141   external_data_manager_->SetPolicyStore(NULL);
142   external_data_manager_->Disconnect();
143 }
144
145 void DeviceLocalAccountPolicyBroker::Initialize() {
146   store_->Load();
147 }
148
149 void DeviceLocalAccountPolicyBroker::ConnectIfPossible(
150     chromeos::DeviceSettingsService* device_settings_service,
151     DeviceManagementService* device_management_service,
152     scoped_refptr<net::URLRequestContextGetter> request_context) {
153   if (core_.client())
154     return;
155
156   scoped_ptr<CloudPolicyClient> client(CreateClient(device_settings_service,
157                                                     device_management_service,
158                                                     request_context));
159   if (!client)
160     return;
161
162   core_.Connect(client.Pass());
163   external_data_manager_->Connect(request_context);
164   core_.StartRefreshScheduler();
165   UpdateRefreshDelay();
166 }
167
168 void DeviceLocalAccountPolicyBroker::UpdateRefreshDelay() {
169   if (core_.refresh_scheduler()) {
170     const base::Value* policy_value =
171         store_->policy_map().GetValue(key::kPolicyRefreshRate);
172     int delay = 0;
173     if (policy_value && policy_value->GetAsInteger(&delay))
174       core_.refresh_scheduler()->SetRefreshDelay(delay);
175   }
176 }
177
178 std::string DeviceLocalAccountPolicyBroker::GetDisplayName() const {
179   std::string display_name;
180   const base::Value* display_name_value =
181       store_->policy_map().GetValue(policy::key::kUserDisplayName);
182   if (display_name_value)
183     display_name_value->GetAsString(&display_name);
184   return display_name;
185 }
186
187 DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
188     chromeos::SessionManagerClient* session_manager_client,
189     chromeos::DeviceSettingsService* device_settings_service,
190     chromeos::CrosSettings* cros_settings,
191     scoped_refptr<base::SequencedTaskRunner> store_background_task_runner,
192     scoped_refptr<base::SequencedTaskRunner> extension_cache_task_runner,
193     scoped_refptr<base::SequencedTaskRunner>
194         external_data_service_backend_task_runner,
195     scoped_refptr<base::SequencedTaskRunner> io_task_runner,
196     scoped_refptr<net::URLRequestContextGetter> request_context)
197     : session_manager_client_(session_manager_client),
198       device_settings_service_(device_settings_service),
199       cros_settings_(cros_settings),
200       device_management_service_(NULL),
201       waiting_for_cros_settings_(false),
202       orphan_cache_deletion_state_(NOT_STARTED),
203       store_background_task_runner_(store_background_task_runner),
204       extension_cache_task_runner_(extension_cache_task_runner),
205       request_context_(request_context),
206       local_accounts_subscription_(cros_settings_->AddSettingsObserver(
207           chromeos::kAccountsPrefDeviceLocalAccounts,
208           base::Bind(&DeviceLocalAccountPolicyService::
209                          UpdateAccountListIfNonePending,
210                      base::Unretained(this)))),
211       weak_factory_(this) {
212   external_data_service_.reset(new DeviceLocalAccountExternalDataService(
213       this,
214       external_data_service_backend_task_runner,
215       io_task_runner));
216   UpdateAccountList();
217 }
218
219 DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
220   DCHECK(!request_context_);
221   DCHECK(policy_brokers_.empty());
222 }
223
224 void DeviceLocalAccountPolicyService::Shutdown() {
225   device_management_service_ = NULL;
226   request_context_ = NULL;
227   DeleteBrokers(&policy_brokers_);
228 }
229
230 void DeviceLocalAccountPolicyService::Connect(
231     DeviceManagementService* device_management_service) {
232   DCHECK(!device_management_service_);
233   device_management_service_ = device_management_service;
234
235   // Connect the brokers.
236   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
237        it != policy_brokers_.end(); ++it) {
238     it->second->ConnectIfPossible(device_settings_service_,
239                                   device_management_service_,
240                                   request_context_);
241   }
242 }
243
244 DeviceLocalAccountPolicyBroker*
245     DeviceLocalAccountPolicyService::GetBrokerForUser(
246         const std::string& user_id) {
247   PolicyBrokerMap::iterator entry = policy_brokers_.find(user_id);
248   if (entry == policy_brokers_.end())
249     return NULL;
250
251   return entry->second;
252 }
253
254 bool DeviceLocalAccountPolicyService::IsPolicyAvailableForUser(
255     const std::string& user_id) {
256   DeviceLocalAccountPolicyBroker* broker = GetBrokerForUser(user_id);
257   return broker && broker->core()->store()->is_managed();
258 }
259
260 void DeviceLocalAccountPolicyService::AddObserver(Observer* observer) {
261   observers_.AddObserver(observer);
262 }
263
264 void DeviceLocalAccountPolicyService::RemoveObserver(Observer* observer) {
265   observers_.RemoveObserver(observer);
266 }
267
268 void DeviceLocalAccountPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
269   DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
270   DCHECK(broker);
271   if (!broker)
272     return;
273   broker->UpdateRefreshDelay();
274   FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
275 }
276
277 void DeviceLocalAccountPolicyService::OnStoreError(CloudPolicyStore* store) {
278   DeviceLocalAccountPolicyBroker* broker = GetBrokerForStore(store);
279   DCHECK(broker);
280   if (!broker)
281     return;
282   FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(broker->user_id()));
283 }
284
285 bool DeviceLocalAccountPolicyService::IsExtensionCacheDirectoryBusy(
286     const std::string& account_id) {
287   return busy_extension_cache_directories_.find(account_id) !=
288             busy_extension_cache_directories_.end();
289 }
290
291 void DeviceLocalAccountPolicyService::StartExtensionCachesIfPossible() {
292   for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
293        it != policy_brokers_.end(); ++it) {
294     if (!it->second->extension_loader()->IsCacheRunning() &&
295         !IsExtensionCacheDirectoryBusy(it->second->account_id())) {
296       it->second->extension_loader()->StartCache(extension_cache_task_runner_);
297     }
298   }
299 }
300
301 bool DeviceLocalAccountPolicyService::StartExtensionCacheForAccountIfPresent(
302     const std::string& account_id) {
303   for (PolicyBrokerMap::iterator it = policy_brokers_.begin();
304        it != policy_brokers_.end(); ++it) {
305     if (it->second->account_id() == account_id) {
306       DCHECK(!it->second->extension_loader()->IsCacheRunning());
307       it->second->extension_loader()->StartCache(extension_cache_task_runner_);
308       return true;
309     }
310   }
311   return false;
312 }
313
314 void DeviceLocalAccountPolicyService::OnOrphanedExtensionCachesDeleted() {
315   DCHECK_EQ(IN_PROGRESS, orphan_cache_deletion_state_);
316
317   orphan_cache_deletion_state_ = DONE;
318   StartExtensionCachesIfPossible();
319 }
320
321 void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown(
322     const std::string& account_id) {
323   DCHECK_NE(NOT_STARTED, orphan_cache_deletion_state_);
324   DCHECK(IsExtensionCacheDirectoryBusy(account_id));
325
326   // The account with |account_id| was deleted and the broker for it has shut
327   // down completely.
328
329   if (StartExtensionCacheForAccountIfPresent(account_id)) {
330     // If another account with the same ID was created in the meantime, its
331     // extension cache is started, reusing the cache directory. The directory no
332     // longer needs to be marked as busy in this case.
333     busy_extension_cache_directories_.erase(account_id);
334     return;
335   }
336
337   // If no account with |account_id| exists anymore, the cache directory should
338   // be removed. The directory must stay marked as busy while the removal is in
339   // progress.
340   extension_cache_task_runner_->PostTaskAndReply(
341       FROM_HERE,
342       base::Bind(&DeleteObsoleteExtensionCache, account_id),
343       base::Bind(&DeviceLocalAccountPolicyService::
344                      OnObsoleteExtensionCacheDeleted,
345                  weak_factory_.GetWeakPtr(),
346                  account_id));
347 }
348
349 void DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheDeleted(
350     const std::string& account_id) {
351   DCHECK_EQ(DONE, orphan_cache_deletion_state_);
352   DCHECK(IsExtensionCacheDirectoryBusy(account_id));
353
354   // The cache directory for |account_id| has been deleted. The directory no
355   // longer needs to be marked as busy.
356   busy_extension_cache_directories_.erase(account_id);
357
358   // If another account with the same ID was created in the meantime, start its
359   // extension cache, creating a new cache directory.
360   StartExtensionCacheForAccountIfPresent(account_id);
361 }
362
363 void DeviceLocalAccountPolicyService::UpdateAccountListIfNonePending() {
364   // Avoid unnecessary calls to UpdateAccountList(): If an earlier call is still
365   // pending (because the |cros_settings_| are not trusted yet), the updated
366   // account list will be processed by that call when it eventually runs.
367   if (!waiting_for_cros_settings_)
368     UpdateAccountList();
369 }
370
371 void DeviceLocalAccountPolicyService::UpdateAccountList() {
372   chromeos::CrosSettingsProvider::TrustedStatus status =
373       cros_settings_->PrepareTrustedValues(
374           base::Bind(&DeviceLocalAccountPolicyService::UpdateAccountList,
375                      weak_factory_.GetWeakPtr()));
376   switch (status) {
377     case chromeos::CrosSettingsProvider::TRUSTED:
378       waiting_for_cros_settings_ = false;
379       break;
380     case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
381       waiting_for_cros_settings_ = true;
382       return;
383     case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
384       waiting_for_cros_settings_ = false;
385       return;
386   }
387
388   // Update |policy_brokers_|, keeping existing entries.
389   PolicyBrokerMap old_policy_brokers;
390   policy_brokers_.swap(old_policy_brokers);
391   std::set<std::string> subdirectories_to_keep;
392   const std::vector<DeviceLocalAccount> device_local_accounts =
393       GetDeviceLocalAccounts(cros_settings_);
394   for (std::vector<DeviceLocalAccount>::const_iterator it =
395            device_local_accounts.begin();
396        it != device_local_accounts.end(); ++it) {
397     PolicyBrokerMap::iterator broker_it = old_policy_brokers.find(it->user_id);
398
399     scoped_ptr<DeviceLocalAccountPolicyBroker> broker;
400     bool broker_initialized = false;
401     if (broker_it != old_policy_brokers.end()) {
402       // Reuse the existing broker if present.
403       broker.reset(broker_it->second);
404       old_policy_brokers.erase(broker_it);
405       broker_initialized = true;
406     } else {
407       scoped_ptr<DeviceLocalAccountPolicyStore> store(
408           new DeviceLocalAccountPolicyStore(it->account_id,
409                                             session_manager_client_,
410                                             device_settings_service_,
411                                             store_background_task_runner_));
412       store->AddObserver(this);
413       scoped_refptr<DeviceLocalAccountExternalDataManager>
414           external_data_manager =
415               external_data_service_->GetExternalDataManager(it->account_id,
416                                                              store.get());
417       broker.reset(new DeviceLocalAccountPolicyBroker(
418           *it,
419           store.Pass(),
420           external_data_manager,
421           base::MessageLoopProxy::current()));
422     }
423
424     // Fire up the cloud connection for fetching policy for the account from
425     // the cloud if this is an enterprise-managed device.
426     broker->ConnectIfPossible(device_settings_service_,
427                               device_management_service_,
428                               request_context_);
429
430     policy_brokers_[it->user_id] = broker.release();
431     if (!broker_initialized) {
432       // The broker must be initialized after it has been added to
433       // |policy_brokers_|.
434       policy_brokers_[it->user_id]->Initialize();
435     }
436
437     if (orphan_cache_deletion_state_ == NOT_STARTED) {
438       subdirectories_to_keep.insert(
439           GetCacheSubdirectoryForAccountID(it->account_id));
440     }
441   }
442
443   std::set<std::string> obsolete_account_ids;
444   for (PolicyBrokerMap::const_iterator it = old_policy_brokers.begin();
445        it != old_policy_brokers.end(); ++it) {
446     obsolete_account_ids.insert(it->second->account_id());
447   }
448
449   if (orphan_cache_deletion_state_ == NOT_STARTED) {
450     DCHECK(old_policy_brokers.empty());
451     DCHECK(busy_extension_cache_directories_.empty());
452
453     // If this method is running for the first time, no extension caches have
454     // been started yet. Take this opportunity to do a clean-up by removing
455     // orphaned cache directories not found in |subdirectories_to_keep| from the
456     // cache directory.
457     orphan_cache_deletion_state_ = IN_PROGRESS;
458     extension_cache_task_runner_->PostTaskAndReply(
459         FROM_HERE,
460         base::Bind(&DeleteOrphanedExtensionCaches, subdirectories_to_keep),
461         base::Bind(&DeviceLocalAccountPolicyService::
462                        OnOrphanedExtensionCachesDeleted,
463                    weak_factory_.GetWeakPtr()));
464
465     // Start the extension caches for all brokers. These belong to accounts in
466     // |account_ids| and are not affected by the clean-up.
467     StartExtensionCachesIfPossible();
468   } else {
469     // If this method has run before, obsolete brokers may exist. Shut down
470     // their extension caches and delete the brokers.
471     DeleteBrokers(&old_policy_brokers);
472
473     if (orphan_cache_deletion_state_ == DONE) {
474       // If the initial clean-up of orphaned cache directories has been
475       // complete, start any extension caches that are not running yet but can
476       // be started now because their cache directories are not busy.
477       StartExtensionCachesIfPossible();
478     }
479   }
480
481   FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged());
482 }
483
484 void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) {
485   for (PolicyBrokerMap::iterator it = map->begin(); it != map->end(); ++it) {
486     it->second->core()->store()->RemoveObserver(this);
487     scoped_refptr<chromeos::DeviceLocalAccountExternalPolicyLoader>
488         extension_loader = it->second->extension_loader();
489     if (extension_loader->IsCacheRunning()) {
490       DCHECK(!IsExtensionCacheDirectoryBusy(it->second->account_id()));
491       busy_extension_cache_directories_.insert(it->second->account_id());
492       extension_loader->StopCache(base::Bind(
493           &DeviceLocalAccountPolicyService::OnObsoleteExtensionCacheShutdown,
494           weak_factory_.GetWeakPtr(),
495           it->second->account_id()));
496     }
497     delete it->second;
498   }
499   map->clear();
500 }
501
502 DeviceLocalAccountPolicyBroker*
503     DeviceLocalAccountPolicyService::GetBrokerForStore(
504         CloudPolicyStore* store) {
505   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
506        it != policy_brokers_.end(); ++it) {
507     if (it->second->core()->store() == store)
508       return it->second;
509   }
510   return NULL;
511 }
512
513 }  // namespace policy