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