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 const DataCallback& callback) OVERRIDE {
117 DBusThreadManager::Get()->GetCryptohomeClient()->
118 AsyncTpmAttestationCreateEnrollRequest(base::Bind(
119 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
120 weak_ptr_factory_.GetWeakPtr(),
122 "Couldn't initiate async attestation enroll request."));
125 virtual void AsyncTpmAttestationEnroll(const std::string& pca_response,
126 const Callback& callback) OVERRIDE {
127 DBusThreadManager::Get()->GetCryptohomeClient()->
128 AsyncTpmAttestationEnroll(pca_response, base::Bind(
129 &AsyncMethodCallerImpl::RegisterAsyncCallback,
130 weak_ptr_factory_.GetWeakPtr(),
132 "Couldn't initiate async attestation enroll."));
135 virtual void AsyncTpmAttestationCreateCertRequest(
136 chromeos::attestation::AttestationCertificateProfile certificate_profile,
137 const std::string& user_id,
138 const std::string& request_origin,
139 const DataCallback& callback) OVERRIDE {
140 DBusThreadManager::Get()->GetCryptohomeClient()->
141 AsyncTpmAttestationCreateCertRequest(
145 base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
146 weak_ptr_factory_.GetWeakPtr(),
148 "Couldn't initiate async attestation cert request."));
151 virtual void AsyncTpmAttestationFinishCertRequest(
152 const std::string& pca_response,
153 chromeos::attestation::AttestationKeyType key_type,
154 const std::string& user_id,
155 const std::string& key_name,
156 const DataCallback& callback) OVERRIDE {
157 DBusThreadManager::Get()->GetCryptohomeClient()->
158 AsyncTpmAttestationFinishCertRequest(
164 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
165 weak_ptr_factory_.GetWeakPtr(),
167 "Couldn't initiate async attestation finish cert request."));
170 virtual void TpmAttestationRegisterKey(
171 chromeos::attestation::AttestationKeyType key_type,
172 const std::string& user_id,
173 const std::string& key_name,
174 const Callback& callback) OVERRIDE {
175 DBusThreadManager::Get()->GetCryptohomeClient()->
176 TpmAttestationRegisterKey(
181 &AsyncMethodCallerImpl::RegisterAsyncCallback,
182 weak_ptr_factory_.GetWeakPtr(),
184 "Couldn't initiate async attestation register key."));
187 virtual void TpmAttestationSignEnterpriseChallenge(
188 chromeos::attestation::AttestationKeyType key_type,
189 const std::string& user_id,
190 const std::string& key_name,
191 const std::string& domain,
192 const std::string& device_id,
193 chromeos::attestation::AttestationChallengeOptions options,
194 const std::string& challenge,
195 const DataCallback& callback) OVERRIDE {
196 DBusThreadManager::Get()->GetCryptohomeClient()->
197 TpmAttestationSignEnterpriseChallenge(
206 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
207 weak_ptr_factory_.GetWeakPtr(),
209 "Couldn't initiate async attestation enterprise challenge."));
212 virtual void TpmAttestationSignSimpleChallenge(
213 chromeos::attestation::AttestationKeyType key_type,
214 const std::string& user_id,
215 const std::string& key_name,
216 const std::string& challenge,
217 const DataCallback& callback) OVERRIDE {
218 DBusThreadManager::Get()->GetCryptohomeClient()->
219 TpmAttestationSignSimpleChallenge(
225 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
226 weak_ptr_factory_.GetWeakPtr(),
228 "Couldn't initiate async attestation simple challenge."));
231 virtual void AsyncGetSanitizedUsername(
232 const std::string& user,
233 const DataCallback& callback) OVERRIDE {
234 DBusThreadManager::Get()->GetCryptohomeClient()->
235 GetSanitizedUsername(user,
237 &AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
238 weak_ptr_factory_.GetWeakPtr(),
242 virtual void GetSanitizedUsernameCallback(
243 const DataCallback& callback,
244 const chromeos::DBusMethodCallStatus call_status,
245 const std::string& result) {
246 callback.Run(true, result);
250 struct CallbackElement {
252 explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
253 : callback(callback),
254 proxy(base::MessageLoopProxy::current()) {
256 AsyncMethodCaller::Callback callback;
257 scoped_refptr<base::MessageLoopProxy> proxy;
260 struct DataCallbackElement {
261 DataCallbackElement() {}
262 explicit DataCallbackElement(
263 const AsyncMethodCaller::DataCallback& callback)
264 : data_callback(callback),
265 proxy(base::MessageLoopProxy::current()) {
267 AsyncMethodCaller::DataCallback data_callback;
268 scoped_refptr<base::MessageLoopProxy> proxy;
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
279 // 3. Cryptohome will return the result asynchronously as a signal with
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;
289 it->second.proxy->PostTask(FROM_HERE,
290 base::Bind(it->second.callback,
292 static_cast<MountError>(return_code)));
293 callback_map_.erase(it);
296 // Similar to HandleAsyncResponse but for signals with a raw data payload.
297 void HandleAsyncDataResponse(int async_id,
299 const std::string& return_data) {
300 const DataCallbackMap::iterator it = data_callback_map_.find(async_id);
301 if (it == data_callback_map_.end()) {
302 LOG(ERROR) << "Received signal for unknown async_id " << async_id;
305 it->second.proxy->PostTask(FROM_HERE,
306 base::Bind(it->second.data_callback, return_status, return_data));
307 data_callback_map_.erase(it);
310 // Registers a callback which is called when the result for AsyncXXX is ready.
311 void RegisterAsyncCallback(
312 Callback callback, const char* error, int async_id) {
317 VLOG(1) << "Adding handler for " << async_id;
318 DCHECK_EQ(callback_map_.count(async_id), 0U);
319 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
320 callback_map_[async_id] = CallbackElement(callback);
323 // Registers a callback which is called when the result for AsyncXXX is ready.
324 void RegisterAsyncDataCallback(
325 DataCallback callback, const char* error, int async_id) {
330 VLOG(1) << "Adding handler for " << async_id;
331 DCHECK_EQ(callback_map_.count(async_id), 0U);
332 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
333 data_callback_map_[async_id] = DataCallbackElement(callback);
336 base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;
337 CallbackMap callback_map_;
338 DataCallbackMap data_callback_map_;
340 DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
346 void AsyncMethodCaller::Initialize() {
347 if (g_async_method_caller) {
348 LOG(WARNING) << "AsyncMethodCaller was already initialized";
351 g_async_method_caller = new AsyncMethodCallerImpl();
352 VLOG(1) << "AsyncMethodCaller initialized";
356 void AsyncMethodCaller::InitializeForTesting(
357 AsyncMethodCaller* async_method_caller) {
358 if (g_async_method_caller) {
359 LOG(WARNING) << "AsyncMethodCaller was already initialized";
362 g_async_method_caller = async_method_caller;
363 VLOG(1) << "AsyncMethodCaller initialized";
367 void AsyncMethodCaller::Shutdown() {
368 if (!g_async_method_caller) {
369 LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
372 delete g_async_method_caller;
373 g_async_method_caller = NULL;
374 VLOG(1) << "AsyncMethodCaller Shutdown completed";
378 AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
379 return g_async_method_caller;
382 } // namespace cryptohome