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

Side by Side Diff: chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc

Issue 654263003: Implemented OwnerSettingsService::Set() method. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes. Created 6 years, 2 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/chromeos/ownership/owner_settings_service_chromeos.h" 5 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/threading/thread_checker.h" 14 #include "base/threading/thread_checker.h"
15 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h" 16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/chromeos/settings/cros_settings.h" 17 #include "chrome/browser/chromeos/settings/cros_settings.h"
18 #include "chrome/browser/chromeos/settings/device_settings_provider.h"
18 #include "chrome/browser/chromeos/settings/session_manager_operation.h" 19 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
20 #include "chromeos/dbus/dbus_thread_manager.h" 21 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/tpm_token_loader.h" 22 #include "chromeos/tpm_token_loader.h"
22 #include "components/ownership/owner_key_util.h" 23 #include "components/ownership/owner_key_util.h"
23 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 24 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
24 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/notification_details.h" 26 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/notification_source.h" 28 #include "content/public/browser/notification_source.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 139
139 DeviceSettingsService* GetDeviceSettingsService() { 140 DeviceSettingsService* GetDeviceSettingsService() {
140 if (g_device_settings_service_for_testing) 141 if (g_device_settings_service_for_testing)
141 return g_device_settings_service_for_testing; 142 return g_device_settings_service_for_testing;
142 return DeviceSettingsService::IsInitialized() ? DeviceSettingsService::Get() 143 return DeviceSettingsService::IsInitialized() ? DeviceSettingsService::Get()
143 : NULL; 144 : NULL;
144 } 145 }
145 146
146 } // namespace 147 } // namespace
147 148
149 class OwnerSettingsServiceChromeOS::DeviceSettingsServiceLock {
Mattias Nissler (ping if slow) 2014/10/17 12:05:26 Calling this a lock is bit misleading, nothing get
ygorshenin1 2014/10/20 11:36:10 Renamed to ProcessingLoopAutoBlocker. Not sure tha
150 public:
151 DeviceSettingsServiceLock() {
152 if (GetDeviceSettingsService())
153 GetDeviceSettingsService()->EnableProcessingLoop(false /* enabled */);
154 }
155
156 ~DeviceSettingsServiceLock() {
157 if (GetDeviceSettingsService())
158 GetDeviceSettingsService()->EnableProcessingLoop(true /* enabled */);
159 }
160
161 private:
162 DISALLOW_COPY_AND_ASSIGN(DeviceSettingsServiceLock);
163 };
164
148 OwnerSettingsServiceChromeOS::OwnerSettingsServiceChromeOS( 165 OwnerSettingsServiceChromeOS::OwnerSettingsServiceChromeOS(
149 Profile* profile, 166 Profile* profile,
150 const scoped_refptr<OwnerKeyUtil>& owner_key_util) 167 const scoped_refptr<OwnerKeyUtil>& owner_key_util)
151 : ownership::OwnerSettingsService(owner_key_util), 168 : ownership::OwnerSettingsService(owner_key_util),
152 profile_(profile), 169 profile_(profile),
153 waiting_for_profile_creation_(true), 170 waiting_for_profile_creation_(true),
154 waiting_for_tpm_token_(true), 171 waiting_for_tpm_token_(true),
155 weak_factory_(this) { 172 weak_factory_(this),
173 set_requests_callback_factory_(this) {
156 if (TPMTokenLoader::IsInitialized()) { 174 if (TPMTokenLoader::IsInitialized()) {
157 TPMTokenLoader::TPMTokenStatus tpm_token_status = 175 TPMTokenLoader::TPMTokenStatus tpm_token_status =
158 TPMTokenLoader::Get()->IsTPMTokenEnabled( 176 TPMTokenLoader::Get()->IsTPMTokenEnabled(
159 base::Bind(&OwnerSettingsServiceChromeOS::OnTPMTokenReady, 177 base::Bind(&OwnerSettingsServiceChromeOS::OnTPMTokenReady,
160 weak_factory_.GetWeakPtr())); 178 weak_factory_.GetWeakPtr()));
161 waiting_for_tpm_token_ = 179 waiting_for_tpm_token_ =
162 tpm_token_status == TPMTokenLoader::TPM_TOKEN_STATUS_UNDETERMINED; 180 tpm_token_status == TPMTokenLoader::TPM_TOKEN_STATUS_UNDETERMINED;
163 } 181 }
164 182
165 if (DBusThreadManager::IsInitialized() && 183 if (DBusThreadManager::IsInitialized() &&
166 DBusThreadManager::Get()->GetSessionManagerClient()) { 184 DBusThreadManager::Get()->GetSessionManagerClient()) {
167 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this); 185 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
168 } 186 }
169 187
188 if (DeviceSettingsService::IsInitialized())
Mattias Nissler (ping if slow) 2014/10/17 12:05:27 I assume this is just for testing? A better way mi
ygorshenin1 2014/10/20 11:36:10 Done.
189 GetDeviceSettingsService()->AddObserver(this);
190
170 registrar_.Add(this, 191 registrar_.Add(this,
171 chrome::NOTIFICATION_PROFILE_CREATED, 192 chrome::NOTIFICATION_PROFILE_CREATED,
172 content::Source<Profile>(profile_)); 193 content::Source<Profile>(profile_));
173 } 194 }
174 195
175 OwnerSettingsServiceChromeOS::~OwnerSettingsServiceChromeOS() { 196 OwnerSettingsServiceChromeOS::~OwnerSettingsServiceChromeOS() {
176 DCHECK(thread_checker_.CalledOnValidThread()); 197 DCHECK(thread_checker_.CalledOnValidThread());
177 if (DBusThreadManager::IsInitialized() && 198 if (DBusThreadManager::IsInitialized() &&
178 DBusThreadManager::Get()->GetSessionManagerClient()) { 199 DBusThreadManager::Get()->GetSessionManagerClient()) {
179 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this); 200 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
180 } 201 }
202
203 if (DeviceSettingsService::IsInitialized())
204 GetDeviceSettingsService()->RemoveObserver(this);
181 } 205 }
182 206
183 void OwnerSettingsServiceChromeOS::OnTPMTokenReady( 207 void OwnerSettingsServiceChromeOS::OnTPMTokenReady(
184 bool /* tpm_token_enabled */) { 208 bool /* tpm_token_enabled */) {
185 DCHECK(thread_checker_.CalledOnValidThread()); 209 DCHECK(thread_checker_.CalledOnValidThread());
186 waiting_for_tpm_token_ = false; 210 waiting_for_tpm_token_ = false;
187 211
188 // TPMTokenLoader initializes the TPM and NSS database which is necessary to 212 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
189 // determine ownership. Force a reload once we know these are initialized. 213 // determine ownership. Force a reload once we know these are initialized.
190 ReloadKeypair(); 214 ReloadKeypair();
191 } 215 }
192 216
193 void OwnerSettingsServiceChromeOS::SignAndStorePolicyAsync( 217 bool OwnerSettingsServiceChromeOS::HandlesSetting(const std::string& setting) {
194 scoped_ptr<em::PolicyData> policy, 218 return DeviceSettingsProvider::IsDeviceSetting(setting);
195 const base::Closure& callback) { 219 }
196 DCHECK(thread_checker_.CalledOnValidThread()); 220
197 SignAndStoreSettingsOperation* operation = new SignAndStoreSettingsOperation( 221 void OwnerSettingsServiceChromeOS::Set(const std::string& setting,
198 base::Bind(&OwnerSettingsServiceChromeOS::HandleCompletedOperation, 222 const base::Value& value) {
199 weak_factory_.GetWeakPtr(), 223 if (!IsOwner() && !IsOwnerInTests(user_id_))
200 callback), 224 return;
201 policy.Pass()); 225 set_requests_.push(
202 operation->set_owner_settings_service(weak_factory_.GetWeakPtr()); 226 SetRequest(setting, linked_ptr<base::Value>(value.DeepCopy())));
203 pending_operations_.push_back(operation); 227 ProcessNextSetRequest();
204 if (pending_operations_.front() == operation)
205 StartNextOperation();
206 } 228 }
207 229
208 void OwnerSettingsServiceChromeOS::Observe( 230 void OwnerSettingsServiceChromeOS::Observe(
209 int type, 231 int type,
210 const content::NotificationSource& source, 232 const content::NotificationSource& source,
211 const content::NotificationDetails& details) { 233 const content::NotificationDetails& details) {
212 DCHECK(thread_checker_.CalledOnValidThread()); 234 DCHECK(thread_checker_.CalledOnValidThread());
213 if (type != chrome::NOTIFICATION_PROFILE_CREATED) { 235 if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
214 NOTREACHED(); 236 NOTREACHED();
215 return; 237 return;
216 } 238 }
217 239
218 Profile* profile = content::Source<Profile>(source).ptr(); 240 Profile* profile = content::Source<Profile>(source).ptr();
219 if (profile != profile_) { 241 if (profile != profile_) {
220 NOTREACHED(); 242 NOTREACHED();
221 return; 243 return;
222 } 244 }
223 245
224 waiting_for_profile_creation_ = false; 246 waiting_for_profile_creation_ = false;
225 ReloadKeypair(); 247 ReloadKeypair();
226 } 248 }
227 249
228 void OwnerSettingsServiceChromeOS::OwnerKeySet(bool success) { 250 void OwnerSettingsServiceChromeOS::OwnerKeySet(bool success) {
229 DCHECK(thread_checker_.CalledOnValidThread()); 251 DCHECK(thread_checker_.CalledOnValidThread());
230 if (success) 252 if (success)
231 ReloadKeypair(); 253 ReloadKeypair();
232 } 254 }
233 255
256 void OwnerSettingsServiceChromeOS::OwnershipStatusChanged() {
257 DCHECK(thread_checker_.CalledOnValidThread());
258 ProcessNextSetRequestAsync();
259 }
260
261 void OwnerSettingsServiceChromeOS::DeviceSettingsUpdated() {
262 DCHECK(thread_checker_.CalledOnValidThread());
263 ProcessNextSetRequestAsync();
264 }
265
234 // static 266 // static
235 void OwnerSettingsServiceChromeOS::IsOwnerForSafeModeAsync( 267 void OwnerSettingsServiceChromeOS::IsOwnerForSafeModeAsync(
236 const std::string& user_hash, 268 const std::string& user_hash,
237 const scoped_refptr<OwnerKeyUtil>& owner_key_util, 269 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
238 const IsOwnerCallback& callback) { 270 const IsOwnerCallback& callback) {
239 CHECK(chromeos::LoginState::Get()->IsInSafeMode()); 271 CHECK(chromeos::LoginState::Get()->IsInSafeMode());
240 272
241 // Make sure NSS is initialized and NSS DB is loaded for the user before 273 // Make sure NSS is initialized and NSS DB is loaded for the user before
242 // searching for the owner key. 274 // searching for the owner key.
243 BrowserThread::PostTaskAndReply( 275 BrowserThread::PostTaskAndReply(
244 BrowserThread::IO, 276 BrowserThread::IO,
245 FROM_HERE, 277 FROM_HERE,
246 base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser), 278 base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
247 user_hash, 279 user_hash,
248 ProfileHelper::GetProfilePathByUserIdHash(user_hash)), 280 ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
249 base::Bind(&DoesPrivateKeyExistAsync, owner_key_util, callback)); 281 base::Bind(&DoesPrivateKeyExistAsync, owner_key_util, callback));
250 } 282 }
251 283
252 // static 284 // static
253 void OwnerSettingsServiceChromeOS::SetDeviceSettingsServiceForTesting( 285 void OwnerSettingsServiceChromeOS::SetDeviceSettingsServiceForTesting(
254 DeviceSettingsService* device_settings_service) { 286 DeviceSettingsService* device_settings_service) {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256 g_device_settings_service_for_testing = device_settings_service; 288 g_device_settings_service_for_testing = device_settings_service;
257 } 289 }
258 290
291 void OwnerSettingsServiceChromeOS::AddObserver(Observer* observer) {
292 if (observer)
293 observers_.AddObserver(observer);
294 }
295
296 void OwnerSettingsServiceChromeOS::RemoveObserver(Observer* observer) {
297 observers_.RemoveObserver(observer);
298 }
299
259 void OwnerSettingsServiceChromeOS::OnPostKeypairLoadedActions() { 300 void OwnerSettingsServiceChromeOS::OnPostKeypairLoadedActions() {
260 DCHECK(thread_checker_.CalledOnValidThread()); 301 DCHECK(thread_checker_.CalledOnValidThread());
261 302
262 user_id_ = profile_->GetProfileName(); 303 user_id_ = profile_->GetProfileName();
263 const bool is_owner = IsOwner() || IsOwnerInTests(user_id_); 304 const bool is_owner = IsOwner() || IsOwnerInTests(user_id_);
264 if (is_owner && GetDeviceSettingsService()) 305 if (is_owner && GetDeviceSettingsService())
265 GetDeviceSettingsService()->InitOwner(user_id_, weak_factory_.GetWeakPtr()); 306 GetDeviceSettingsService()->InitOwner(user_id_, weak_factory_.GetWeakPtr());
266 } 307 }
267 308
268 void OwnerSettingsServiceChromeOS::ReloadKeypairImpl(const base::Callback< 309 void OwnerSettingsServiceChromeOS::ReloadKeypairImpl(const base::Callback<
269 void(const scoped_refptr<PublicKey>& public_key, 310 void(const scoped_refptr<PublicKey>& public_key,
270 const scoped_refptr<PrivateKey>& private_key)>& callback) { 311 const scoped_refptr<PrivateKey>& private_key)>& callback) {
271 DCHECK(thread_checker_.CalledOnValidThread()); 312 DCHECK(thread_checker_.CalledOnValidThread());
272 313
273 if (waiting_for_profile_creation_ || waiting_for_tpm_token_) 314 if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
274 return; 315 return;
275 scoped_refptr<base::TaskRunner> task_runner = 316 scoped_refptr<base::TaskRunner> task_runner =
276 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 317 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
277 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 318 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
278 task_runner->PostTask( 319 task_runner->PostTask(
279 FROM_HERE, 320 FROM_HERE,
280 base::Bind(&LoadPrivateKey, 321 base::Bind(&LoadPrivateKey,
281 owner_key_util_, 322 owner_key_util_,
282 ProfileHelper::GetUserIdHashFromProfile(profile_), 323 ProfileHelper::GetUserIdHashFromProfile(profile_),
283 callback)); 324 callback));
284 } 325 }
285 326
286 void OwnerSettingsServiceChromeOS::StartNextOperation() { 327 void OwnerSettingsServiceChromeOS::ProcessNextSetRequestAsync() {
287 DeviceSettingsService* service = GetDeviceSettingsService(); 328 DCHECK(thread_checker_.CalledOnValidThread());
288 if (!pending_operations_.empty() && service && 329 BrowserThread::PostTask(
Mattias Nissler (ping if slow) 2014/10/17 12:05:27 If you're on the right thread anyways, you can jus
ygorshenin1 2014/10/20 11:36:10 The reason is that the method is called when Devic
Mattias Nissler (ping if slow) 2014/10/20 12:41:30 Is there a good reason DeviceSettingsService is im
ygorshenin1 2014/10/22 09:20:11 Done.
289 service->session_manager_client()) { 330 BrowserThread::UI,
290 pending_operations_.front()->Start( 331 FROM_HERE,
291 service->session_manager_client(), owner_key_util_, public_key_); 332 base::Bind(&OwnerSettingsServiceChromeOS::ProcessNextSetRequest,
292 } 333 weak_factory_.GetWeakPtr()));
293 } 334 }
294 335
295 void OwnerSettingsServiceChromeOS::HandleCompletedOperation( 336 void OwnerSettingsServiceChromeOS::ProcessNextSetRequest() {
296 const base::Closure& callback, 337 DCHECK(thread_checker_.CalledOnValidThread());
297 SessionManagerOperation* operation, 338 if (set_requests_.empty())
298 DeviceSettingsService::Status status) { 339 return;
299 DCHECK_EQ(operation, pending_operations_.front()); 340 if (set_requests_callback_factory_.HasWeakPtrs())
Mattias Nissler (ping if slow) 2014/10/17 12:05:27 Could just unify the conditionals in lines 338, 34
ygorshenin1 2014/10/20 11:36:10 Done.
300 341 return;
301 DeviceSettingsService* service = GetDeviceSettingsService(); 342 if (!GetDeviceSettingsService() ||
302 if (status == DeviceSettingsService::STORE_SUCCESS) { 343 GetDeviceSettingsService()->HasPendingOperations()) {
303 service->set_policy_data(operation->policy_data().Pass()); 344 return;
304 service->set_device_settings(operation->device_settings().Pass());
305 } 345 }
306 346
307 if ((operation->public_key().get() && !public_key_.get()) || 347 scoped_ptr<DeviceSettingsServiceLock> lock(new DeviceSettingsServiceLock());
308 (operation->public_key().get() && public_key_.get() && 348
309 operation->public_key()->data() != public_key_->data())) { 349 // TODO (ygorshenin@): notify somehow DeviceSettingsProvider about tentative
310 // Public part changed so we need to reload private part too. 350 // change.
311 ReloadKeypair(); 351 // crbug.com/230018
Mattias Nissler (ping if slow) 2014/10/17 12:05:27 Have you tested how the device behaves (in particu
ygorshenin1 2014/10/20 11:36:10 Yes, I've tested the CL with small additional chan
312 content::NotificationService::current()->Notify( 352 std::string setting = set_requests_.front().first;
313 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, 353 linked_ptr<base::Value> value = set_requests_.front().second;
314 content::Source<OwnerSettingsServiceChromeOS>(this), 354 set_requests_.pop();
315 content::NotificationService::NoDetails()); 355
356 em::ChromeDeviceSettingsProto new_settings(
357 *GetDeviceSettingsService()->device_settings());
358 DeviceSettingsService::UpdateDeviceSettings(setting, *value, new_settings);
Mattias Nissler (ping if slow) 2014/10/17 12:05:26 Is there a good reason to have the UpdateDeviceSet
ygorshenin1 2014/10/20 11:36:10 The reason is to not introduce dependency on chrom
Mattias Nissler (ping if slow) 2014/10/20 12:41:30 What dependencies are we talking about? IMHO, the
ygorshenin1 2014/10/22 09:20:11 Done.
359 scoped_ptr<em::PolicyData> new_policy = DeviceSettingsService::AssemblePolicy(
360 user_id_, GetDeviceSettingsService()->policy_data(), &new_settings);
361 bool rv = AssembleAndSignPolicyAsync(
362 content::BrowserThread::GetBlockingPool(),
363 new_policy.Pass(),
364 base::Bind(&OwnerSettingsServiceChromeOS::OnPolicyAssembledAndSigned,
365 set_requests_callback_factory_.GetWeakPtr(),
366 Passed(&lock)));
367 if (!rv)
368 HandleError();
369 }
370
371 void OwnerSettingsServiceChromeOS::OnPolicyAssembledAndSigned(
372 scoped_ptr<DeviceSettingsServiceLock> lock,
373 scoped_ptr<em::PolicyFetchResponse> policy_response) {
374 lock.reset();
375 if (!policy_response.get()) {
376 HandleError();
377 return;
316 } 378 }
317 service->OnSignAndStoreOperationCompleted(status); 379 GetDeviceSettingsService()->Store(
318 if (!callback.is_null()) 380 policy_response.Pass(),
319 callback.Run(); 381 base::Bind(&OwnerSettingsServiceChromeOS::OnSignedPolicyStored,
382 weak_factory_.GetWeakPtr()));
383 }
320 384
321 pending_operations_.pop_front(); 385 void OwnerSettingsServiceChromeOS::OnSignedPolicyStored() {
322 delete operation; 386 FOR_EACH_OBSERVER(Observer, observers_, OnSetCompleted(true));
323 StartNextOperation(); 387 ProcessNextSetRequestAsync();
388 }
389
390 void OwnerSettingsServiceChromeOS::HandleError() {
391 FOR_EACH_OBSERVER(Observer, observers_, OnSetCompleted(false));
392 ProcessNextSetRequestAsync();
324 } 393 }
325 394
326 } // namespace chromeos 395 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698