Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chromeos / cryptohome / async_method_caller.cc
blobeab0bd5c73a476c9c87dd4752d2efb9e1536be3c
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.
5 #include "chromeos/cryptohome/async_method_caller.h"
7 #include "base/bind.h"
8 #include "base/containers/hash_tables.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
14 using chromeos::DBusThreadManager;
16 namespace cryptohome {
18 namespace {
20 AsyncMethodCaller* g_async_method_caller = NULL;
22 // The implementation of AsyncMethodCaller
23 class AsyncMethodCallerImpl : public AsyncMethodCaller {
24 public:
25 AsyncMethodCallerImpl() : weak_ptr_factory_(this) {
26 DBusThreadManager::Get()->GetCryptohomeClient()->SetAsyncCallStatusHandlers(
27 base::Bind(&AsyncMethodCallerImpl::HandleAsyncResponse,
28 weak_ptr_factory_.GetWeakPtr()),
29 base::Bind(&AsyncMethodCallerImpl::HandleAsyncDataResponse,
30 weak_ptr_factory_.GetWeakPtr()));
33 ~AsyncMethodCallerImpl() override {
34 DBusThreadManager::Get()->GetCryptohomeClient()->
35 ResetAsyncCallStatusHandlers();
38 void AsyncCheckKey(const std::string& user_email,
39 const std::string& passhash,
40 Callback callback) override {
41 DBusThreadManager::Get()->GetCryptohomeClient()->
42 AsyncCheckKey(user_email, passhash, base::Bind(
43 &AsyncMethodCallerImpl::RegisterAsyncCallback,
44 weak_ptr_factory_.GetWeakPtr(),
45 callback,
46 "Couldn't initiate async check of user's key."));
49 void AsyncMigrateKey(const std::string& user_email,
50 const std::string& old_hash,
51 const std::string& new_hash,
52 Callback callback) override {
53 DBusThreadManager::Get()->GetCryptohomeClient()->
54 AsyncMigrateKey(user_email, old_hash, new_hash, base::Bind(
55 &AsyncMethodCallerImpl::RegisterAsyncCallback,
56 weak_ptr_factory_.GetWeakPtr(),
57 callback,
58 "Couldn't initiate aync migration of user's key"));
61 void AsyncMount(const std::string& user_email,
62 const std::string& passhash,
63 int flags,
64 Callback callback) override {
65 DBusThreadManager::Get()->GetCryptohomeClient()->
66 AsyncMount(user_email, passhash, flags, base::Bind(
67 &AsyncMethodCallerImpl::RegisterAsyncCallback,
68 weak_ptr_factory_.GetWeakPtr(),
69 callback,
70 "Couldn't initiate async mount of cryptohome."));
73 void AsyncAddKey(const std::string& user_email,
74 const std::string& passhash,
75 const std::string& new_passhash,
76 Callback callback) override {
77 DBusThreadManager::Get()->GetCryptohomeClient()->
78 AsyncAddKey(user_email, passhash, new_passhash, base::Bind(
79 &AsyncMethodCallerImpl::RegisterAsyncCallback,
80 weak_ptr_factory_.GetWeakPtr(),
81 callback,
82 "Couldn't initiate async key addition."));
85 void AsyncMountGuest(Callback callback) override {
86 DBusThreadManager::Get()->GetCryptohomeClient()->
87 AsyncMountGuest(base::Bind(
88 &AsyncMethodCallerImpl::RegisterAsyncCallback,
89 weak_ptr_factory_.GetWeakPtr(),
90 callback,
91 "Couldn't initiate async mount of cryptohome."));
94 void AsyncMountPublic(const std::string& public_mount_id,
95 int flags,
96 Callback callback) override {
97 DBusThreadManager::Get()->GetCryptohomeClient()->
98 AsyncMountPublic(public_mount_id, flags, base::Bind(
99 &AsyncMethodCallerImpl::RegisterAsyncCallback,
100 weak_ptr_factory_.GetWeakPtr(),
101 callback,
102 "Couldn't initiate async mount public of cryptohome."));
105 void AsyncRemove(const std::string& user_email, Callback callback) override {
106 DBusThreadManager::Get()->GetCryptohomeClient()->
107 AsyncRemove(user_email, base::Bind(
108 &AsyncMethodCallerImpl::RegisterAsyncCallback,
109 weak_ptr_factory_.GetWeakPtr(),
110 callback,
111 "Couldn't initiate async removal of cryptohome."));
114 void AsyncTpmAttestationCreateEnrollRequest(
115 chromeos::attestation::PrivacyCAType pca_type,
116 const DataCallback& callback) override {
117 DBusThreadManager::Get()->GetCryptohomeClient()->
118 AsyncTpmAttestationCreateEnrollRequest(pca_type, base::Bind(
119 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
120 weak_ptr_factory_.GetWeakPtr(),
121 callback,
122 "Couldn't initiate async attestation enroll request."));
125 void AsyncTpmAttestationEnroll(chromeos::attestation::PrivacyCAType pca_type,
126 const std::string& pca_response,
127 const Callback& callback) override {
128 DBusThreadManager::Get()->GetCryptohomeClient()->
129 AsyncTpmAttestationEnroll(pca_type, pca_response, base::Bind(
130 &AsyncMethodCallerImpl::RegisterAsyncCallback,
131 weak_ptr_factory_.GetWeakPtr(),
132 callback,
133 "Couldn't initiate async attestation enroll."));
136 void AsyncTpmAttestationCreateCertRequest(
137 chromeos::attestation::PrivacyCAType pca_type,
138 chromeos::attestation::AttestationCertificateProfile certificate_profile,
139 const std::string& user_id,
140 const std::string& request_origin,
141 const DataCallback& callback) override {
142 DBusThreadManager::Get()->GetCryptohomeClient()->
143 AsyncTpmAttestationCreateCertRequest(
144 pca_type,
145 certificate_profile,
146 user_id,
147 request_origin,
148 base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
149 weak_ptr_factory_.GetWeakPtr(),
150 callback,
151 "Couldn't initiate async attestation cert request."));
154 void AsyncTpmAttestationFinishCertRequest(
155 const std::string& pca_response,
156 chromeos::attestation::AttestationKeyType key_type,
157 const std::string& user_id,
158 const std::string& key_name,
159 const DataCallback& callback) override {
160 DBusThreadManager::Get()->GetCryptohomeClient()->
161 AsyncTpmAttestationFinishCertRequest(
162 pca_response,
163 key_type,
164 user_id,
165 key_name,
166 base::Bind(
167 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
168 weak_ptr_factory_.GetWeakPtr(),
169 callback,
170 "Couldn't initiate async attestation finish cert request."));
173 void TpmAttestationRegisterKey(
174 chromeos::attestation::AttestationKeyType key_type,
175 const std::string& user_id,
176 const std::string& key_name,
177 const Callback& callback) override {
178 DBusThreadManager::Get()->GetCryptohomeClient()->
179 TpmAttestationRegisterKey(
180 key_type,
181 user_id,
182 key_name,
183 base::Bind(
184 &AsyncMethodCallerImpl::RegisterAsyncCallback,
185 weak_ptr_factory_.GetWeakPtr(),
186 callback,
187 "Couldn't initiate async attestation register key."));
190 void TpmAttestationSignEnterpriseChallenge(
191 chromeos::attestation::AttestationKeyType key_type,
192 const std::string& user_id,
193 const std::string& key_name,
194 const std::string& domain,
195 const std::string& device_id,
196 chromeos::attestation::AttestationChallengeOptions options,
197 const std::string& challenge,
198 const DataCallback& callback) override {
199 DBusThreadManager::Get()->GetCryptohomeClient()->
200 TpmAttestationSignEnterpriseChallenge(
201 key_type,
202 user_id,
203 key_name,
204 domain,
205 device_id,
206 options,
207 challenge,
208 base::Bind(
209 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
210 weak_ptr_factory_.GetWeakPtr(),
211 callback,
212 "Couldn't initiate async attestation enterprise challenge."));
215 void TpmAttestationSignSimpleChallenge(
216 chromeos::attestation::AttestationKeyType key_type,
217 const std::string& user_id,
218 const std::string& key_name,
219 const std::string& challenge,
220 const DataCallback& callback) override {
221 DBusThreadManager::Get()->GetCryptohomeClient()->
222 TpmAttestationSignSimpleChallenge(
223 key_type,
224 user_id,
225 key_name,
226 challenge,
227 base::Bind(
228 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
229 weak_ptr_factory_.GetWeakPtr(),
230 callback,
231 "Couldn't initiate async attestation simple challenge."));
234 void AsyncGetSanitizedUsername(const std::string& user,
235 const DataCallback& callback) override {
236 DBusThreadManager::Get()->GetCryptohomeClient()->
237 GetSanitizedUsername(user,
238 base::Bind(
239 &AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
240 weak_ptr_factory_.GetWeakPtr(),
241 callback));
244 virtual void GetSanitizedUsernameCallback(
245 const DataCallback& callback,
246 const chromeos::DBusMethodCallStatus call_status,
247 const std::string& result) {
248 callback.Run(true, result);
251 private:
252 struct CallbackElement {
253 CallbackElement() {}
254 explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
255 : callback(callback),
256 task_runner(base::ThreadTaskRunnerHandle::Get()) {}
257 AsyncMethodCaller::Callback callback;
258 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
261 struct DataCallbackElement {
262 DataCallbackElement() {}
263 explicit DataCallbackElement(
264 const AsyncMethodCaller::DataCallback& callback)
265 : data_callback(callback),
266 task_runner(base::ThreadTaskRunnerHandle::Get()) {}
267 AsyncMethodCaller::DataCallback data_callback;
268 scoped_refptr<base::SingleThreadTaskRunner> task_runner;
271 typedef base::hash_map<int, CallbackElement> CallbackMap;
272 typedef base::hash_map<int, DataCallbackElement> DataCallbackMap;
274 // Handles the response for async calls.
275 // Below is described how async calls work.
276 // 1. CryptohomeClient::AsyncXXX returns "async ID".
277 // 2. RegisterAsyncCallback registers the "async ID" with the user-provided
278 // callback.
279 // 3. Cryptohome will return the result asynchronously as a signal with
280 // "async ID"
281 // 4. "HandleAsyncResponse" handles the result signal and call the registered
282 // callback associated with the "async ID".
283 void HandleAsyncResponse(int async_id, bool return_status, int return_code) {
284 const CallbackMap::iterator it = callback_map_.find(async_id);
285 if (it == callback_map_.end()) {
286 LOG(ERROR) << "Received signal for unknown async_id " << async_id;
287 return;
289 it->second.task_runner->PostTask(
290 FROM_HERE, base::Bind(it->second.callback, return_status,
291 static_cast<MountError>(return_code)));
292 callback_map_.erase(it);
295 // Similar to HandleAsyncResponse but for signals with a raw data payload.
296 void HandleAsyncDataResponse(int async_id,
297 bool return_status,
298 const std::string& return_data) {
299 const DataCallbackMap::iterator it = data_callback_map_.find(async_id);
300 if (it == data_callback_map_.end()) {
301 LOG(ERROR) << "Received signal for unknown async_id " << async_id;
302 return;
304 it->second.task_runner->PostTask(
305 FROM_HERE,
306 base::Bind(it->second.data_callback, return_status, return_data));
307 data_callback_map_.erase(it);
309 // Registers a callback which is called when the result for AsyncXXX is ready.
310 void RegisterAsyncCallback(
311 Callback callback, const char* error, int async_id) {
312 if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
313 base::ThreadTaskRunnerHandle::Get()->PostTask(
314 FROM_HERE, base::Bind(callback,
315 false, // return status
316 cryptohome::MOUNT_ERROR_FATAL));
317 return;
320 if (async_id == 0) {
321 LOG(ERROR) << error;
322 return;
324 VLOG(1) << "Adding handler for " << async_id;
325 DCHECK_EQ(callback_map_.count(async_id), 0U);
326 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
327 callback_map_[async_id] = CallbackElement(callback);
330 // Registers a callback which is called when the result for AsyncXXX is ready.
331 void RegisterAsyncDataCallback(
332 DataCallback callback, const char* error, int async_id) {
333 if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
334 base::ThreadTaskRunnerHandle::Get()->PostTask(
335 FROM_HERE, base::Bind(callback,
336 false, // return status
337 std::string()));
338 return;
340 if (async_id == 0) {
341 LOG(ERROR) << error;
342 return;
344 VLOG(1) << "Adding handler for " << async_id;
345 DCHECK_EQ(callback_map_.count(async_id), 0U);
346 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
347 data_callback_map_[async_id] = DataCallbackElement(callback);
350 CallbackMap callback_map_;
351 DataCallbackMap data_callback_map_;
352 base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;
354 DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
357 } // namespace
359 // static
360 void AsyncMethodCaller::Initialize() {
361 if (g_async_method_caller) {
362 LOG(WARNING) << "AsyncMethodCaller was already initialized";
363 return;
365 g_async_method_caller = new AsyncMethodCallerImpl();
366 VLOG(1) << "AsyncMethodCaller initialized";
369 // static
370 void AsyncMethodCaller::InitializeForTesting(
371 AsyncMethodCaller* async_method_caller) {
372 if (g_async_method_caller) {
373 LOG(WARNING) << "AsyncMethodCaller was already initialized";
374 return;
376 g_async_method_caller = async_method_caller;
377 VLOG(1) << "AsyncMethodCaller initialized";
380 // static
381 void AsyncMethodCaller::Shutdown() {
382 if (!g_async_method_caller) {
383 LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
384 return;
386 delete g_async_method_caller;
387 g_async_method_caller = NULL;
388 VLOG(1) << "AsyncMethodCaller Shutdown completed";
391 // static
392 AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
393 return g_async_method_caller;
396 } // namespace cryptohome