Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/policy/user_policy_disk_cache.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/file_util.h"
      9 #include "base/logging.h"
     10 #include "base/metrics/histogram.h"
     11 #include "chrome/browser/policy/cloud/enterprise_metrics.h"
     12 #include "chrome/browser/policy/proto/cloud/device_management_local.pb.h"
     13 #include "content/public/browser/browser_thread.h"
     14 
     15 using content::BrowserThread;
     16 
     17 namespace em = enterprise_management;
     18 
     19 namespace {
     20 
     21 // Other places can sample on the same UMA counter, so make sure they all do
     22 // it on the same thread (UI).
     23 void SampleUMAOnUIThread(policy::MetricPolicy sample) {
     24   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     25   UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy, sample,
     26                             policy::kMetricPolicySize);
     27 }
     28 
     29 void SampleUMA(policy::MetricPolicy sample) {
     30   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     31   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     32                           base::Bind(&SampleUMAOnUIThread, sample));
     33 }
     34 
     35 }  // namespace
     36 
     37 namespace policy {
     38 
     39 UserPolicyDiskCache::Delegate::~Delegate() {}
     40 
     41 UserPolicyDiskCache::UserPolicyDiskCache(
     42     const base::WeakPtr<Delegate>& delegate,
     43     const base::FilePath& backing_file_path)
     44     : delegate_(delegate),
     45       backing_file_path_(backing_file_path) {}
     46 
     47 void UserPolicyDiskCache::Load() {
     48   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     49   bool ret = BrowserThread::PostTask(
     50       BrowserThread::FILE, FROM_HERE,
     51       base::Bind(&UserPolicyDiskCache::LoadOnFileThread, this));
     52   DCHECK(ret);
     53 }
     54 
     55 void UserPolicyDiskCache::Store(
     56     const em::CachedCloudPolicyResponse& policy) {
     57   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     58   BrowserThread::PostTask(
     59       BrowserThread::FILE, FROM_HERE,
     60       base::Bind(&UserPolicyDiskCache::StoreOnFileThread, this, policy));
     61 }
     62 
     63 UserPolicyDiskCache::~UserPolicyDiskCache() {}
     64 
     65 void UserPolicyDiskCache::LoadOnFileThread() {
     66   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     67 
     68   em::CachedCloudPolicyResponse cached_response;
     69   if (!base::PathExists(backing_file_path_)) {
     70     LoadDone(LOAD_RESULT_NOT_FOUND, cached_response);
     71     return;
     72   }
     73 
     74   // Read the protobuf from the file.
     75   std::string data;
     76   if (!file_util::ReadFileToString(backing_file_path_, &data)) {
     77     LOG(WARNING) << "Failed to read policy data from "
     78                  << backing_file_path_.value();
     79     LoadDone(LOAD_RESULT_READ_ERROR, cached_response);
     80     return;
     81   }
     82 
     83   // Decode it.
     84   if (!cached_response.ParseFromArray(data.c_str(), data.size())) {
     85     LOG(WARNING) << "Failed to parse policy data read from "
     86                  << backing_file_path_.value();
     87     LoadDone(LOAD_RESULT_PARSE_ERROR, cached_response);
     88     return;
     89   }
     90 
     91   LoadDone(LOAD_RESULT_SUCCESS, cached_response);
     92 }
     93 
     94 void UserPolicyDiskCache::LoadDone(
     95     LoadResult result,
     96     const em::CachedCloudPolicyResponse& policy) {
     97   BrowserThread::PostTask(
     98       BrowserThread::UI, FROM_HERE,
     99       base::Bind(&UserPolicyDiskCache::ReportResultOnUIThread, this,
    100                  result, policy));
    101 }
    102 
    103 void UserPolicyDiskCache::ReportResultOnUIThread(
    104     LoadResult result,
    105     const em::CachedCloudPolicyResponse& policy) {
    106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    107 
    108   switch (result) {
    109     case LOAD_RESULT_NOT_FOUND:
    110       break;
    111     case LOAD_RESULT_READ_ERROR:
    112     case LOAD_RESULT_PARSE_ERROR:
    113       SampleUMAOnUIThread(kMetricPolicyLoadFailed);
    114       break;
    115     case LOAD_RESULT_SUCCESS:
    116       SampleUMAOnUIThread(kMetricPolicyLoadSucceeded);
    117   }
    118 
    119   if (delegate_.get())
    120     delegate_->OnDiskCacheLoaded(result, policy);
    121 }
    122 
    123 void UserPolicyDiskCache::StoreOnFileThread(
    124     const em::CachedCloudPolicyResponse& policy) {
    125   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    126   std::string data;
    127   if (!policy.SerializeToString(&data)) {
    128     LOG(WARNING) << "Failed to serialize policy data";
    129     SampleUMA(kMetricPolicyStoreFailed);
    130     return;
    131   }
    132 
    133   if (!file_util::CreateDirectory(backing_file_path_.DirName())) {
    134     LOG(WARNING) << "Failed to create directory "
    135                  << backing_file_path_.DirName().value();
    136     SampleUMA(kMetricPolicyStoreFailed);
    137     return;
    138   }
    139 
    140   int size = data.size();
    141   if (file_util::WriteFile(backing_file_path_, data.c_str(), size) != size) {
    142     LOG(WARNING) << "Failed to write " << backing_file_path_.value();
    143     SampleUMA(kMetricPolicyStoreFailed);
    144     return;
    145   }
    146   SampleUMA(kMetricPolicyStoreSucceeded);
    147 }
    148 
    149 }  // namespace policy
    150