15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/policy/user_policy_disk_cache.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/sequenced_task_runner.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/enterprise_metrics.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/device_management_local.pb.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UserPolicyDiskCache::Delegate::~Delegate() {}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UserPolicyDiskCache::UserPolicyDiskCache(
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::WeakPtr<Delegate>& delegate,
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const base::FilePath& backing_file_path,
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> background_task_runner)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(delegate),
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      backing_file_path_(backing_file_path),
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      origin_task_runner_(base::MessageLoopProxy::current()),
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      background_task_runner_(background_task_runner) {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::Load() {
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool ret = background_task_runner_->PostTask(
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE, base::Bind(&UserPolicyDiskCache::LoadOnFileThread, this));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ret);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::Store(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const em::CachedCloudPolicyResponse& policy) {
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  background_task_runner_->PostTask(
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&UserPolicyDiskCache::StoreOnFileThread, this, policy));
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UserPolicyDiskCache::~UserPolicyDiskCache() {}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::LoadOnFileThread() {
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  em::CachedCloudPolicyResponse cached_response;
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(backing_file_path_)) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadDone(LOAD_RESULT_NOT_FOUND, cached_response);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the protobuf from the file.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!base::ReadFileToString(backing_file_path_, &data)) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to read policy data from "
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << backing_file_path_.value();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadDone(LOAD_RESULT_READ_ERROR, cached_response);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decode it.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cached_response.ParseFromArray(data.c_str(), data.size())) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to parse policy data read from "
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << backing_file_path_.value();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadDone(LOAD_RESULT_PARSE_ERROR, cached_response);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadDone(LOAD_RESULT_SUCCESS, cached_response);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::LoadDone(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadResult result,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const em::CachedCloudPolicyResponse& policy) {
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  origin_task_runner_->PostTask(
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      FROM_HERE,
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      base::Bind(
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          &UserPolicyDiskCache::ReportResultOnUIThread, this, result, policy));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::ReportResultOnUIThread(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LoadResult result,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const em::CachedCloudPolicyResponse& policy) {
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (result) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LOAD_RESULT_NOT_FOUND:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LOAD_RESULT_READ_ERROR:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LOAD_RESULT_PARSE_ERROR:
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                kMetricPolicyLoadFailed,
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                policy::kMetricPolicySize);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LOAD_RESULT_SUCCESS:
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                kMetricPolicyLoadSucceeded,
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                policy::kMetricPolicySize);
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_.get())
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnDiskCacheLoaded(result, policy);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UserPolicyDiskCache::StoreOnFileThread(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const em::CachedCloudPolicyResponse& policy) {
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!policy.SerializeToString(&data)) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to serialize policy data";
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              kMetricPolicyStoreFailed,
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              policy::kMetricPolicySize);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::CreateDirectory(backing_file_path_.DirName())) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to create directory "
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << backing_file_path_.DirName().value();
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              kMetricPolicyStoreFailed,
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              policy::kMetricPolicySize);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size = data.size();
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (base::WriteFile(backing_file_path_, data.c_str(), size) != size) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to write " << backing_file_path_.value();
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              kMetricPolicyStoreFailed,
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              policy::kMetricPolicySize);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            kMetricPolicyStoreSucceeded,
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            policy::kMetricPolicySize);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
147