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"
8 #include "base/containers/hash_tables.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "chromeos/dbus/cryptohome_client.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
14 using chromeos::DBusThreadManager
;
16 namespace cryptohome
{
20 AsyncMethodCaller
* g_async_method_caller
= NULL
;
22 // The implementation of AsyncMethodCaller
23 class AsyncMethodCallerImpl
: public AsyncMethodCaller
{
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 virtual ~AsyncMethodCallerImpl() {
34 DBusThreadManager::Get()->GetCryptohomeClient()->
35 ResetAsyncCallStatusHandlers();
38 virtual 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(),
46 "Couldn't initiate async check of user's key."));
49 virtual 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(),
58 "Couldn't initiate aync migration of user's key"));
61 virtual void AsyncMount(const std::string
& user_email
,
62 const std::string
& passhash
,
64 Callback callback
) override
{
65 DBusThreadManager::Get()->GetCryptohomeClient()->
66 AsyncMount(user_email
, passhash
, flags
, base::Bind(
67 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
68 weak_ptr_factory_
.GetWeakPtr(),
70 "Couldn't initiate async mount of cryptohome."));
73 virtual 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(),
82 "Couldn't initiate async key addition."));
85 virtual void AsyncMountGuest(Callback callback
) override
{
86 DBusThreadManager::Get()->GetCryptohomeClient()->
87 AsyncMountGuest(base::Bind(
88 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
89 weak_ptr_factory_
.GetWeakPtr(),
91 "Couldn't initiate async mount of cryptohome."));
94 virtual void AsyncMountPublic(const std::string
& public_mount_id
,
96 Callback callback
) override
{
97 DBusThreadManager::Get()->GetCryptohomeClient()->
98 AsyncMountPublic(public_mount_id
, flags
, base::Bind(
99 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
100 weak_ptr_factory_
.GetWeakPtr(),
102 "Couldn't initiate async mount public of cryptohome."));
105 virtual void AsyncRemove(const std::string
& user_email
,
106 Callback callback
) override
{
107 DBusThreadManager::Get()->GetCryptohomeClient()->
108 AsyncRemove(user_email
, base::Bind(
109 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
110 weak_ptr_factory_
.GetWeakPtr(),
112 "Couldn't initiate async removal of cryptohome."));
115 virtual void AsyncTpmAttestationCreateEnrollRequest(
116 chromeos::attestation::PrivacyCAType pca_type
,
117 const DataCallback
& callback
) override
{
118 DBusThreadManager::Get()->GetCryptohomeClient()->
119 AsyncTpmAttestationCreateEnrollRequest(pca_type
, base::Bind(
120 &AsyncMethodCallerImpl::RegisterAsyncDataCallback
,
121 weak_ptr_factory_
.GetWeakPtr(),
123 "Couldn't initiate async attestation enroll request."));
126 virtual void AsyncTpmAttestationEnroll(
127 chromeos::attestation::PrivacyCAType pca_type
,
128 const std::string
& pca_response
,
129 const Callback
& callback
) override
{
130 DBusThreadManager::Get()->GetCryptohomeClient()->
131 AsyncTpmAttestationEnroll(pca_type
, pca_response
, base::Bind(
132 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
133 weak_ptr_factory_
.GetWeakPtr(),
135 "Couldn't initiate async attestation enroll."));
138 virtual void AsyncTpmAttestationCreateCertRequest(
139 chromeos::attestation::PrivacyCAType pca_type
,
140 chromeos::attestation::AttestationCertificateProfile certificate_profile
,
141 const std::string
& user_id
,
142 const std::string
& request_origin
,
143 const DataCallback
& callback
) override
{
144 DBusThreadManager::Get()->GetCryptohomeClient()->
145 AsyncTpmAttestationCreateCertRequest(
150 base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback
,
151 weak_ptr_factory_
.GetWeakPtr(),
153 "Couldn't initiate async attestation cert request."));
156 virtual void AsyncTpmAttestationFinishCertRequest(
157 const std::string
& pca_response
,
158 chromeos::attestation::AttestationKeyType key_type
,
159 const std::string
& user_id
,
160 const std::string
& key_name
,
161 const DataCallback
& callback
) override
{
162 DBusThreadManager::Get()->GetCryptohomeClient()->
163 AsyncTpmAttestationFinishCertRequest(
169 &AsyncMethodCallerImpl::RegisterAsyncDataCallback
,
170 weak_ptr_factory_
.GetWeakPtr(),
172 "Couldn't initiate async attestation finish cert request."));
175 virtual void TpmAttestationRegisterKey(
176 chromeos::attestation::AttestationKeyType key_type
,
177 const std::string
& user_id
,
178 const std::string
& key_name
,
179 const Callback
& callback
) override
{
180 DBusThreadManager::Get()->GetCryptohomeClient()->
181 TpmAttestationRegisterKey(
186 &AsyncMethodCallerImpl::RegisterAsyncCallback
,
187 weak_ptr_factory_
.GetWeakPtr(),
189 "Couldn't initiate async attestation register key."));
192 virtual void TpmAttestationSignEnterpriseChallenge(
193 chromeos::attestation::AttestationKeyType key_type
,
194 const std::string
& user_id
,
195 const std::string
& key_name
,
196 const std::string
& domain
,
197 const std::string
& device_id
,
198 chromeos::attestation::AttestationChallengeOptions options
,
199 const std::string
& challenge
,
200 const DataCallback
& callback
) override
{
201 DBusThreadManager::Get()->GetCryptohomeClient()->
202 TpmAttestationSignEnterpriseChallenge(
211 &AsyncMethodCallerImpl::RegisterAsyncDataCallback
,
212 weak_ptr_factory_
.GetWeakPtr(),
214 "Couldn't initiate async attestation enterprise challenge."));
217 virtual void TpmAttestationSignSimpleChallenge(
218 chromeos::attestation::AttestationKeyType key_type
,
219 const std::string
& user_id
,
220 const std::string
& key_name
,
221 const std::string
& challenge
,
222 const DataCallback
& callback
) override
{
223 DBusThreadManager::Get()->GetCryptohomeClient()->
224 TpmAttestationSignSimpleChallenge(
230 &AsyncMethodCallerImpl::RegisterAsyncDataCallback
,
231 weak_ptr_factory_
.GetWeakPtr(),
233 "Couldn't initiate async attestation simple challenge."));
236 virtual void AsyncGetSanitizedUsername(
237 const std::string
& user
,
238 const DataCallback
& callback
) override
{
239 DBusThreadManager::Get()->GetCryptohomeClient()->
240 GetSanitizedUsername(user
,
242 &AsyncMethodCallerImpl::GetSanitizedUsernameCallback
,
243 weak_ptr_factory_
.GetWeakPtr(),
247 virtual void GetSanitizedUsernameCallback(
248 const DataCallback
& callback
,
249 const chromeos::DBusMethodCallStatus call_status
,
250 const std::string
& result
) {
251 callback
.Run(true, result
);
255 struct CallbackElement
{
257 explicit CallbackElement(const AsyncMethodCaller::Callback
& callback
)
258 : callback(callback
),
259 proxy(base::MessageLoopProxy::current()) {
261 AsyncMethodCaller::Callback callback
;
262 scoped_refptr
<base::MessageLoopProxy
> proxy
;
265 struct DataCallbackElement
{
266 DataCallbackElement() {}
267 explicit DataCallbackElement(
268 const AsyncMethodCaller::DataCallback
& callback
)
269 : data_callback(callback
),
270 proxy(base::MessageLoopProxy::current()) {
272 AsyncMethodCaller::DataCallback data_callback
;
273 scoped_refptr
<base::MessageLoopProxy
> proxy
;
276 typedef base::hash_map
<int, CallbackElement
> CallbackMap
;
277 typedef base::hash_map
<int, DataCallbackElement
> DataCallbackMap
;
279 // Handles the response for async calls.
280 // Below is described how async calls work.
281 // 1. CryptohomeClient::AsyncXXX returns "async ID".
282 // 2. RegisterAsyncCallback registers the "async ID" with the user-provided
284 // 3. Cryptohome will return the result asynchronously as a signal with
286 // 4. "HandleAsyncResponse" handles the result signal and call the registered
287 // callback associated with the "async ID".
288 void HandleAsyncResponse(int async_id
, bool return_status
, int return_code
) {
289 const CallbackMap::iterator it
= callback_map_
.find(async_id
);
290 if (it
== callback_map_
.end()) {
291 LOG(ERROR
) << "Received signal for unknown async_id " << async_id
;
294 it
->second
.proxy
->PostTask(FROM_HERE
,
295 base::Bind(it
->second
.callback
,
297 static_cast<MountError
>(return_code
)));
298 callback_map_
.erase(it
);
301 // Similar to HandleAsyncResponse but for signals with a raw data payload.
302 void HandleAsyncDataResponse(int async_id
,
304 const std::string
& return_data
) {
305 const DataCallbackMap::iterator it
= data_callback_map_
.find(async_id
);
306 if (it
== data_callback_map_
.end()) {
307 LOG(ERROR
) << "Received signal for unknown async_id " << async_id
;
310 it
->second
.proxy
->PostTask(FROM_HERE
,
311 base::Bind(it
->second
.data_callback
, return_status
, return_data
));
312 data_callback_map_
.erase(it
);
315 // Registers a callback which is called when the result for AsyncXXX is ready.
316 void RegisterAsyncCallback(
317 Callback callback
, const char* error
, int async_id
) {
322 VLOG(1) << "Adding handler for " << async_id
;
323 DCHECK_EQ(callback_map_
.count(async_id
), 0U);
324 DCHECK_EQ(data_callback_map_
.count(async_id
), 0U);
325 callback_map_
[async_id
] = CallbackElement(callback
);
328 // Registers a callback which is called when the result for AsyncXXX is ready.
329 void RegisterAsyncDataCallback(
330 DataCallback callback
, const char* error
, int async_id
) {
335 VLOG(1) << "Adding handler for " << async_id
;
336 DCHECK_EQ(callback_map_
.count(async_id
), 0U);
337 DCHECK_EQ(data_callback_map_
.count(async_id
), 0U);
338 data_callback_map_
[async_id
] = DataCallbackElement(callback
);
341 base::WeakPtrFactory
<AsyncMethodCallerImpl
> weak_ptr_factory_
;
342 CallbackMap callback_map_
;
343 DataCallbackMap data_callback_map_
;
345 DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl
);
351 void AsyncMethodCaller::Initialize() {
352 if (g_async_method_caller
) {
353 LOG(WARNING
) << "AsyncMethodCaller was already initialized";
356 g_async_method_caller
= new AsyncMethodCallerImpl();
357 VLOG(1) << "AsyncMethodCaller initialized";
361 void AsyncMethodCaller::InitializeForTesting(
362 AsyncMethodCaller
* async_method_caller
) {
363 if (g_async_method_caller
) {
364 LOG(WARNING
) << "AsyncMethodCaller was already initialized";
367 g_async_method_caller
= async_method_caller
;
368 VLOG(1) << "AsyncMethodCaller initialized";
372 void AsyncMethodCaller::Shutdown() {
373 if (!g_async_method_caller
) {
374 LOG(WARNING
) << "AsyncMethodCaller::Shutdown() called with NULL manager";
377 delete g_async_method_caller
;
378 g_async_method_caller
= NULL
;
379 VLOG(1) << "AsyncMethodCaller Shutdown completed";
383 AsyncMethodCaller
* AsyncMethodCaller::GetInstance() {
384 return g_async_method_caller
;
387 } // namespace cryptohome