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

Side by Side Diff: chrome/browser/chromeos/settings/device_oauth2_token_service_factory.cc

Issue 39443002: settings: Add async system salt retrieval logic in DeviceOAuth2TokenServiceFactory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 7 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 | 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/chromeos/settings/device_oauth2_token_service_factory.h " 5 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h "
6 6
7 #include "base/bind.h"
8 #include "base/callback.h"
7 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
8 #include "base/tracked_objects.h" 10 #include "base/tracked_objects.h"
9 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 12 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
11 #include "chrome/browser/chromeos/settings/token_encryptor.h" 13 #include "chrome/browser/chromeos/settings/token_encryptor.h"
14 #include "chromeos/cryptohome/system_salt_getter.h"
12 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
13 16
14 namespace chromeos { 17 namespace chromeos {
15 namespace { 18 namespace {
16 19
17 DeviceOAuth2TokenServiceFactory* g_factory = NULL; 20 DeviceOAuth2TokenServiceFactory* g_factory = NULL;
18 21
19 } // namespace 22 } // namespace
20 23
21 DeviceOAuth2TokenServiceFactory::DeviceOAuth2TokenServiceFactory() 24 DeviceOAuth2TokenServiceFactory::DeviceOAuth2TokenServiceFactory()
22 : token_service_(new DeviceOAuth2TokenService( 25 : initialized_(false),
23 g_browser_process->system_request_context(), 26 token_service_(NULL),
24 g_browser_process->local_state(), 27 weak_ptr_factory_(this) {
25 new CryptohomeTokenEncryptor)) {
26 } 28 }
27 29
28 DeviceOAuth2TokenServiceFactory::~DeviceOAuth2TokenServiceFactory() { 30 DeviceOAuth2TokenServiceFactory::~DeviceOAuth2TokenServiceFactory() {
29 delete token_service_; 31 delete token_service_;
30 } 32 }
31 33
32 // static 34 // static
33 void DeviceOAuth2TokenServiceFactory::Get(const GetCallback& callback) { 35 void DeviceOAuth2TokenServiceFactory::Get(const GetCallback& callback) {
34 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 36 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
35 37
36 DeviceOAuth2TokenService* token_service = NULL; 38 if (!g_factory) {
37 if (g_factory) 39 base::MessageLoop::current()->PostTask(
38 token_service = g_factory->token_service_; 40 FROM_HERE,
41 base::Bind(callback,
42 static_cast<DeviceOAuth2TokenService*>(NULL)));
43 return;
44 }
39 45
40 // TODO(satorux): Implement async initialization logic for 46 g_factory->RunAsync(callback);
41 // DeviceOAuth2TokenService. crbug.com/309959.
42 // Here's how that should work:
43 //
44 // if token_service is ready:
45 // run callback asynchronously via MessageLoop
46 // return
47 //
48 // add callback to the pending callback list
49 //
50 // if there is only one pending callback:
51 // start getting the system salt asynchronously...
52 //
53 // upon receiving the system salt:
54 // create CryptohomeTokenEncryptor with that key
55 // create DeviceOAuth2TokenService
56 // run all the pending callbacks
57 base::MessageLoop::current()->PostTask(
58 FROM_HERE,
59 base::Bind(callback, token_service));
60 } 47 }
61 48
62 // static 49 // static
63 void DeviceOAuth2TokenServiceFactory::Initialize() { 50 void DeviceOAuth2TokenServiceFactory::Initialize() {
64 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 51 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
65 52
66 DCHECK(!g_factory); 53 DCHECK(!g_factory);
67 g_factory = new DeviceOAuth2TokenServiceFactory; 54 g_factory = new DeviceOAuth2TokenServiceFactory;
55 g_factory->CreateTokenService();
68 } 56 }
69 57
70 // static 58 // static
71 void DeviceOAuth2TokenServiceFactory::Shutdown() { 59 void DeviceOAuth2TokenServiceFactory::Shutdown() {
72 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 60 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
73 61
74 if (g_factory) { 62 if (g_factory) {
75 delete g_factory; 63 delete g_factory;
76 g_factory = NULL; 64 g_factory = NULL;
77 } 65 }
78 } 66 }
79 67
68 void DeviceOAuth2TokenServiceFactory::CreateTokenService() {
69 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
70
71 SystemSaltGetter::Get()->GetSystemSalt(
72 base::Bind(&DeviceOAuth2TokenServiceFactory::DidGetSystemSalt,
73 weak_ptr_factory_.GetWeakPtr()));
74 }
75
76 void DeviceOAuth2TokenServiceFactory::DidGetSystemSalt(
77 const std::string& system_salt) {
78 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
79 DCHECK(!token_service_);
80
81 if (system_salt.empty()) {
82 LOG(ERROR) << "Failed to get the system salt";
83 } else {
84 token_service_= new DeviceOAuth2TokenService(
85 g_browser_process->system_request_context(),
86 g_browser_process->local_state(),
87 new CryptohomeTokenEncryptor(system_salt));
88 }
89
90 // Run callbacks regardless of whether token_service_ is created or not,
91 // but don't run callbacks immediately. This is tricky, but running
92 // callbacks directly here can introduce a subtle bug, as these callbacks
93 // may call Get(), which in turn appends new callbacks to
94 // pending_callbacks_, while the vector is being accessed here.
95 for (size_t i = 0; i < pending_callbacks_.size(); ++i) {
pastarmovj 2013/10/24 09:43:20 You can create a local empty vector here and swap(
satorux1 2013/10/24 10:23:14 I considered, but it's still complicated, as we'll
satorux1 2013/10/24 10:53:01 oops. I misunderstood your comment. If we are to s
pastarmovj 2013/10/24 11:28:49 How are they going to be run with the current setu
satorux1 2013/10/24 13:15:52 New callbacks are posted to MessageLoop in RunAsyn
pastarmovj 2013/10/24 13:21:30 This makes sense. Thanks for clarifying this! :)
satorux1 2013/10/24 13:22:00 Let me drop "by the time they are added"...
pneubeck (no reviews) 2013/10/24 19:44:13 nit: use vector<>::const_iterator instead of an in
satorux1 2013/10/25 02:36:02 IMHO that's verbose for little benefit. :) but I c
96 base::MessageLoop::current()->PostTask(
97 FROM_HERE,
98 base::Bind(pending_callbacks_[i], token_service_));
99 }
100 pending_callbacks_.clear();
101 // Also mark that the factory is initialized.
102 initialized_ = true;
pneubeck (no reviews) 2013/10/24 19:44:13 you could move this "initialized_=true" to the mor
satorux1 2013/10/25 02:36:02 Thank you for the suggestion. Moved initialized=tr
103 }
104
105 void DeviceOAuth2TokenServiceFactory::RunAsync(const GetCallback& callback) {
106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
107
108 if (initialized_) {
109 // No pending callbacks should be left.
110 DCHECK(pending_callbacks_.empty());
111 base::MessageLoop::current()->PostTask(
112 FROM_HERE,
113 base::Bind(callback, token_service_));
114 return;
115 }
116
117 pending_callbacks_.push_back(callback);
118 }
119
80 } // namespace chromeos 120 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698