Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: chrome/browser/policy/user_cloud_policy_store.cc

Issue 10825415: Added code to persist downloaded cloud policy to disk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed unneeded #include Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/policy/user_cloud_policy_store.h" 5 #include "chrome/browser/policy/user_cloud_policy_store.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_path.h"
Joao da Silva 2012/08/22 08:07:00 Nit: already in .h
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Done.
9 #include "base/file_util.h"
8 #include "chrome/browser/policy/proto/cloud_policy.pb.h" 10 #include "chrome/browser/policy/proto/cloud_policy.pb.h"
11 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
12 #include "chrome/browser/policy/proto/device_management_local.pb.h"
13 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/signin/signin_manager.h" 14 #include "chrome/browser/signin/signin_manager.h"
10 #include "chrome/browser/signin/signin_manager_factory.h" 15 #include "chrome/browser/signin/signin_manager_factory.h"
11 16 #include "content/public/browser/browser_thread.h"
12 using enterprise_management::PolicyData; 17
18 namespace em = enterprise_management;
19
20 namespace {
21 // Subdirectory in the user's profile for storing user policies.
22 const FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Policy");
23 // File in the above directory for storing user policy data.
24 const FilePath::CharType kPolicyCacheFile[] = FILE_PATH_LITERAL("User Policy");
25
26 // Helper class that is used to persist and reload policy on disk.
27 class PolicyBackingFile
28 : public base::RefCountedThreadSafe<PolicyBackingFile> {
Mattias Nissler (ping if slow) 2012/08/22 08:21:23 I don't see the need for making this a RefCountedT
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Hah, I knew about PostTaskAndReply but not PostTas
29 public:
30 explicit PolicyBackingFile(const FilePath& path)
31 : backing_file_path_(path),
32 error_(false) {}
33
34 // Loads policy from the backing file (must be called via a task on
35 // the FILE thread). Once complete, loaded policy is in |policy_| and
36 // error() will return true if an error was encountered.
37 void LoadPolicyFromDiskOnFileThread() {
38 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
39 // If the backing file did not exist, just return.
40 if (!file_util::PathExists(backing_file_path_))
41 return;
42
43 std::string data;
44 if (!file_util::ReadFileToString(backing_file_path_, &data)) {
45 DLOG(WARNING) << "Failed to read policy data from "
Mattias Nissler (ping if slow) 2012/08/22 08:21:23 Make this and the one below a LOG(WARNING)? That'd
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Hmmm. I thought we (chromium) were trying to avoid
Mattias Nissler (ping if slow) 2012/08/23 09:28:34 So why do we have crash reporting code then given
Andrew T Wilson (Slow) 2012/08/23 18:00:08 Done.
46 << backing_file_path_.value();
47 error_ = true;
48 return;
49 }
50 policy_.reset(new em::PolicyFetchResponse());
51 if (!policy_->ParseFromArray(data.c_str(), data.size())) {
52 DLOG(WARNING) << "Failed to parse policy data from "
53 << backing_file_path_.value();
54 error_ = true;
55 return;
Joao da Silva 2012/08/22 08:07:00 policy_.reset() before returning here?
Andrew T Wilson (Slow) 2012/08/22 23:39:30 No longer necessary after latest refactoring.
56 }
57 }
58
59 // Stores policy to the backing file (must be called via a task on
60 // the FILE thread).
61 void StorePolicyToDiskOnFileThread(const em::PolicyFetchResponse& policy) {
62 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
63 std::string data;
64 if (!policy.SerializeToString(&data)) {
65 DLOG(WARNING) << "Failed to serialize policy data";
66 return;
67 }
68
69 if (!file_util::CreateDirectory(backing_file_path_.DirName())) {
70 DLOG(WARNING) << "Failed to create directory "
71 << backing_file_path_.DirName().value();
72 return;
73 }
74
75 int size = data.size();
76 if (file_util::WriteFile(
77 backing_file_path_, data.c_str(), size) != size) {
78 DLOG(WARNING) << "Failed to write " << backing_file_path_.value();
79 }
80 }
81
82 // Returns the loaded policy blob, or NULL if there was no policy file.
83 scoped_ptr<em::PolicyFetchResponse> policy() { return policy_.Pass(); }
84
85 // Returns true if there was an error reading/writing the policy blob
86 // (false if the file did not exist).
87 bool error() { return error_; }
88
89 private:
90 // The path of the file containing the policy blob.
91 FilePath backing_file_path_;
92
93 // If true, an error was encountered reading the file.
94 bool error_;
95
96 // The policy blob to store/return.
97 scoped_ptr<em::PolicyFetchResponse> policy_;
98 };
99
100 } // namespace
13 101
14 namespace policy { 102 namespace policy {
15 103
16 UserCloudPolicyStore::UserCloudPolicyStore(Profile* profile) 104 UserCloudPolicyStore::UserCloudPolicyStore(Profile* profile,
105 const FilePath& path)
17 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 106 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
18 profile_(profile) { 107 profile_(profile),
108 backing_file_path_(path) {
19 } 109 }
20 110
21 UserCloudPolicyStore::~UserCloudPolicyStore() { 111 UserCloudPolicyStore::~UserCloudPolicyStore() {
22 } 112 }
23 113
114 static void PolicyLoadedFromDisk(
Joao da Silva 2012/08/22 08:07:00 Nit: namespace { ... } instead of static?
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Removed.
115 UserCloudPolicyStore* store,
Joao da Silva 2012/08/22 08:07:00 Shouldn't this be a WeakPtr?
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Interesting - I thought that the WeakPtr->regular
116 scoped_refptr<PolicyBackingFile> backing_file) {
117 if (store)
118 store->PolicyLoaded(backing_file->error(), backing_file->policy());
119 }
120
24 void UserCloudPolicyStore::Load() { 121 void UserCloudPolicyStore::Load() {
25 // TODO(atwilson): Read policy from file. 122 DVLOG(1) << "Initiating policy load from disk";
26 policy_.reset(); 123 // Cancel any pending Load/Store/Validate operations.
27 policy_map_.Clear(); 124 weak_factory_.InvalidateWeakPtrs();
125
126 // Start a new Load operation and have us get called back when it is
127 // complete.
128 scoped_refptr<PolicyBackingFile> policy_backing_file =
129 new PolicyBackingFile(backing_file_path_);
130 content::BrowserThread::PostTaskAndReply(
131 content::BrowserThread::FILE, FROM_HERE,
132 base::Bind(&PolicyBackingFile::LoadPolicyFromDiskOnFileThread,
133 policy_backing_file),
134 base::Bind(&PolicyLoadedFromDisk,
135 weak_factory_.GetWeakPtr(),
136 policy_backing_file));
Joao da Silva 2012/08/22 08:07:00 Two suggestions, feel free to ignore :-) 1) Inste
Andrew T Wilson (Slow) 2012/08/22 23:39:30 The reason I did not do this is because I did not
137 }
138
139 void UserCloudPolicyStore::PolicyLoaded(
140 bool error, scoped_ptr<em::PolicyFetchResponse> cloud_policy) {
Mattias Nissler (ping if slow) 2012/08/22 08:21:23 each parameter on separate line.
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Done.
141 if (error) {
142 DLOG(WARNING) << "Error reading policy from disk";
143 status_ = STATUS_LOAD_ERROR;
144 NotifyStoreError();
145 return;
146 }
147
148 status_ = STATUS_OK;
149 if (!cloud_policy.get()) {
150 // No policy found on disk.
151 DVLOG(1) << "No policy found on disk";
152 NotifyStoreLoaded();
153 return;
154 }
155
156 // Found policy on disk - need to validate it before it can be used.
157 Validate(cloud_policy.Pass(),
158 base::Bind(
159 &UserCloudPolicyStore::InstallLoadedPolicyAfterValidation,
160 weak_factory_.GetWeakPtr()));
161 }
162
163 void UserCloudPolicyStore::InstallLoadedPolicyAfterValidation(
164 UserCloudPolicyValidator* validator) {
165 validation_status_ = validator->status();
166 if (!validator->success()) {
167 DVLOG(1) << "Validation failed: status=" << validation_status_;
168 status_ = STATUS_VALIDATION_ERROR;
169 NotifyStoreError();
170 return;
171 }
172
173 DVLOG(1) << "Validation succeeded - installing policy with dm_token: " <<
174 validator->policy_data()->request_token();
175 DVLOG(1) << "Device ID: " << validator->policy_data()->device_id();
176
177 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
178 status_ = STATUS_OK;
28 NotifyStoreLoaded(); 179 NotifyStoreLoaded();
29 } 180 }
30 181
182 static void DeleteFileOnFileThread(const FilePath& path) {
Joao da Silva 2012/08/22 08:07:00 Nit: namespace { ... } instead of static?
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Removed in favor of base::IgnoreResult
183 file_util::Delete(path, false);
184 }
185
31 void UserCloudPolicyStore::RemoveStoredPolicy() { 186 void UserCloudPolicyStore::RemoveStoredPolicy() {
32 // TODO(atwilson): Remove policy from disk. 187 content::BrowserThread::PostTask(
33 } 188 content::BrowserThread::FILE, FROM_HERE,
34 189 base::Bind(&DeleteFileOnFileThread, backing_file_path_));
Joao da Silva 2012/08/22 08:07:00 Why not just bind file_util::Delete()?
Mattias Nissler (ping if slow) 2012/08/22 08:21:23 That should work if you wrap it in a base::IgnoreR
Andrew T Wilson (Slow) 2012/08/22 23:39:30 I could not get it to compile - I thought it was b
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Ah, there you go. Thanks.
35 void UserCloudPolicyStore::Store( 190 }
36 const enterprise_management::PolicyFetchResponse& policy) { 191
192 void UserCloudPolicyStore::Store(const em::PolicyFetchResponse& policy) {
37 // Stop any pending requests to store policy, then validate the new policy 193 // Stop any pending requests to store policy, then validate the new policy
38 // before storing it. 194 // before storing it.
39 weak_factory_.InvalidateWeakPtrs(); 195 weak_factory_.InvalidateWeakPtrs();
40 scoped_ptr<enterprise_management::PolicyFetchResponse> policy_copy( 196 scoped_ptr<em::PolicyFetchResponse> policy_copy(
41 new enterprise_management::PolicyFetchResponse(policy)); 197 new em::PolicyFetchResponse(policy));
42 Validate(policy_copy.Pass(), 198 Validate(policy_copy.Pass(),
43 base::Bind(&UserCloudPolicyStore::StorePolicyAfterValidation, 199 base::Bind(&UserCloudPolicyStore::StorePolicyAfterValidation,
44 weak_factory_.GetWeakPtr())); 200 weak_factory_.GetWeakPtr()));
45 } 201 }
46 202
47 void UserCloudPolicyStore::Validate( 203 void UserCloudPolicyStore::Validate(
48 scoped_ptr<enterprise_management::PolicyFetchResponse> policy, 204 scoped_ptr<em::PolicyFetchResponse> policy,
49 const UserCloudPolicyValidator::CompletionCallback& callback) { 205 const UserCloudPolicyValidator::CompletionCallback& callback) {
50 // Configure the validator. 206 // Configure the validator.
51 scoped_ptr<UserCloudPolicyValidator> validator = 207 scoped_ptr<UserCloudPolicyValidator> validator =
52 CreateValidator(policy.Pass(), callback); 208 CreateValidator(policy.Pass(), callback);
53 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_); 209 SigninManager* signin = SigninManagerFactory::GetForProfile(profile_);
54 std::string username = signin->GetAuthenticatedUsername(); 210 std::string username = signin->GetAuthenticatedUsername();
55 DCHECK(!username.empty()); 211 DCHECK(!username.empty());
56 validator->ValidateUsername(username); 212 validator->ValidateUsername(username);
57 213
58 // Start validation. The Validator will free itself once validation is 214 // Start validation. The Validator will free itself once validation is
59 // complete. 215 // complete.
60 validator.release()->StartValidation(); 216 validator.release()->StartValidation();
61 } 217 }
62 218
63 void UserCloudPolicyStore::StorePolicyAfterValidation( 219 void UserCloudPolicyStore::StorePolicyAfterValidation(
64 UserCloudPolicyValidator* validator) { 220 UserCloudPolicyValidator* validator) {
65 validation_status_ = validator->status(); 221 validation_status_ = validator->status();
222 DVLOG(1) << "Policy validation complete: status = " << validation_status_;
66 if (!validator->success()) { 223 if (!validator->success()) {
67 status_ = STATUS_VALIDATION_ERROR; 224 status_ = STATUS_VALIDATION_ERROR;
68 NotifyStoreError(); 225 NotifyStoreError();
69 return; 226 return;
70 } 227 }
71 // TODO(atwilson): Write policy to file. 228
229 // Persist the validated policy (just fire a task - don't bother getting a
230 // reply because we can't do anything if it fails).
231 scoped_refptr<PolicyBackingFile> policy_backing_file =
232 new PolicyBackingFile(backing_file_path_);
233 content::BrowserThread::PostTask(
234 content::BrowserThread::FILE, FROM_HERE,
235 base::Bind(&PolicyBackingFile::StorePolicyToDiskOnFileThread,
236 policy_backing_file, *validator->policy()));
Joao da Silva 2012/08/22 08:07:00 Same here: |policy_backing_file| can be passed wit
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Thanks for the tips. I haven't used the new bind s
72 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); 237 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
73 status_ = STATUS_OK; 238 status_ = STATUS_OK;
74 NotifyStoreLoaded(); 239 NotifyStoreLoaded();
75 } 240 }
76 241
77 // static 242 // static
78 scoped_ptr<CloudPolicyStore> CloudPolicyStore::CreateUserPolicyStore( 243 scoped_ptr<CloudPolicyStore> CloudPolicyStore::CreateUserPolicyStore(
79 Profile* profile) { 244 Profile* profile) {
80 return scoped_ptr<CloudPolicyStore>(new UserCloudPolicyStore(profile)); 245 FilePath path = profile->GetPath();
246 path = path.Append(kPolicyDir);
247 path = path.Append(kPolicyCacheFile);
Joao da Silva 2012/08/22 08:07:00 Suggestion: FilePath path = profile->GetPath().Ap
Andrew T Wilson (Slow) 2012/08/22 23:39:30 Done. And, tragically, it comes to 81 characters o
248 return scoped_ptr<CloudPolicyStore>(new UserCloudPolicyStore(profile, path));
81 } 249 }
82 250
83 } // namespace policy 251 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698