Reland: media-internals: Simplify the code path for creating a media log entry
[chromium-blink-merge.git] / chromeos / cryptohome / async_method_caller.cc
blob8348fd26f992fe4b70e6dc4665fcb70f5d968386
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/message_loop/message_loop_proxy.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
13 using chromeos::DBusThreadManager;
15 namespace cryptohome {
17 namespace {
19 AsyncMethodCaller* g_async_method_caller = NULL;
21 // The implementation of AsyncMethodCaller
22 class AsyncMethodCallerImpl : public AsyncMethodCaller {
23 public:
24 AsyncMethodCallerImpl() : weak_ptr_factory_(this) {
25 DBusThreadManager::Get()->GetCryptohomeClient()->SetAsyncCallStatusHandlers(
26 base::Bind(&AsyncMethodCallerImpl::HandleAsyncResponse,
27 weak_ptr_factory_.GetWeakPtr()),
28 base::Bind(&AsyncMethodCallerImpl::HandleAsyncDataResponse,
29 weak_ptr_factory_.GetWeakPtr()));
32 ~AsyncMethodCallerImpl() override {
33 DBusThreadManager::Get()->GetCryptohomeClient()->
34 ResetAsyncCallStatusHandlers();
37 void AsyncCheckKey(const std::string& user_email,
38 const std::string& passhash,
39 Callback callback) override {
40 DBusThreadManager::Get()->GetCryptohomeClient()->
41 AsyncCheckKey(user_email, passhash, base::Bind(
42 &AsyncMethodCallerImpl::RegisterAsyncCallback,
43 weak_ptr_factory_.GetWeakPtr(),
44 callback,
45 "Couldn't initiate async check of user's key."));
48 void AsyncMigrateKey(const std::string& user_email,
49 const std::string& old_hash,
50 const std::string& new_hash,
51 Callback callback) override {
52 DBusThreadManager::Get()->GetCryptohomeClient()->
53 AsyncMigrateKey(user_email, old_hash, new_hash, base::Bind(
54 &AsyncMethodCallerImpl::RegisterAsyncCallback,
55 weak_ptr_factory_.GetWeakPtr(),
56 callback,
57 "Couldn't initiate aync migration of user's key"));
60 void AsyncMount(const std::string& user_email,
61 const std::string& passhash,
62 int flags,
63 Callback callback) override {
64 DBusThreadManager::Get()->GetCryptohomeClient()->
65 AsyncMount(user_email, passhash, flags, base::Bind(
66 &AsyncMethodCallerImpl::RegisterAsyncCallback,
67 weak_ptr_factory_.GetWeakPtr(),
68 callback,
69 "Couldn't initiate async mount of cryptohome."));
72 void AsyncAddKey(const std::string& user_email,
73 const std::string& passhash,
74 const std::string& new_passhash,
75 Callback callback) override {
76 DBusThreadManager::Get()->GetCryptohomeClient()->
77 AsyncAddKey(user_email, passhash, new_passhash, base::Bind(
78 &AsyncMethodCallerImpl::RegisterAsyncCallback,
79 weak_ptr_factory_.GetWeakPtr(),
80 callback,
81 "Couldn't initiate async key addition."));
84 void AsyncMountGuest(Callback callback) override {
85 DBusThreadManager::Get()->GetCryptohomeClient()->
86 AsyncMountGuest(base::Bind(
87 &AsyncMethodCallerImpl::RegisterAsyncCallback,
88 weak_ptr_factory_.GetWeakPtr(),
89 callback,
90 "Couldn't initiate async mount of cryptohome."));
93 void AsyncMountPublic(const std::string& public_mount_id,
94 int flags,
95 Callback callback) override {
96 DBusThreadManager::Get()->GetCryptohomeClient()->
97 AsyncMountPublic(public_mount_id, flags, base::Bind(
98 &AsyncMethodCallerImpl::RegisterAsyncCallback,
99 weak_ptr_factory_.GetWeakPtr(),
100 callback,
101 "Couldn't initiate async mount public of cryptohome."));
104 void AsyncRemove(const std::string& user_email, Callback callback) override {
105 DBusThreadManager::Get()->GetCryptohomeClient()->
106 AsyncRemove(user_email, base::Bind(
107 &AsyncMethodCallerImpl::RegisterAsyncCallback,
108 weak_ptr_factory_.GetWeakPtr(),
109 callback,
110 "Couldn't initiate async removal of cryptohome."));
113 void AsyncTpmAttestationCreateEnrollRequest(
114 chromeos::attestation::PrivacyCAType pca_type,
115 const DataCallback& callback) override {
116 DBusThreadManager::Get()->GetCryptohomeClient()->
117 AsyncTpmAttestationCreateEnrollRequest(pca_type, base::Bind(
118 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
119 weak_ptr_factory_.GetWeakPtr(),
120 callback,
121 "Couldn't initiate async attestation enroll request."));
124 void AsyncTpmAttestationEnroll(chromeos::attestation::PrivacyCAType pca_type,
125 const std::string& pca_response,
126 const Callback& callback) override {
127 DBusThreadManager::Get()->GetCryptohomeClient()->
128 AsyncTpmAttestationEnroll(pca_type, pca_response, base::Bind(
129 &AsyncMethodCallerImpl::RegisterAsyncCallback,
130 weak_ptr_factory_.GetWeakPtr(),
131 callback,
132 "Couldn't initiate async attestation enroll."));
135 void AsyncTpmAttestationCreateCertRequest(
136 chromeos::attestation::PrivacyCAType pca_type,
137 chromeos::attestation::AttestationCertificateProfile certificate_profile,
138 const std::string& user_id,
139 const std::string& request_origin,
140 const DataCallback& callback) override {
141 DBusThreadManager::Get()->GetCryptohomeClient()->
142 AsyncTpmAttestationCreateCertRequest(
143 pca_type,
144 certificate_profile,
145 user_id,
146 request_origin,
147 base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
148 weak_ptr_factory_.GetWeakPtr(),
149 callback,
150 "Couldn't initiate async attestation cert request."));
153 void AsyncTpmAttestationFinishCertRequest(
154 const std::string& pca_response,
155 chromeos::attestation::AttestationKeyType key_type,
156 const std::string& user_id,
157 const std::string& key_name,
158 const DataCallback& callback) override {
159 DBusThreadManager::Get()->GetCryptohomeClient()->
160 AsyncTpmAttestationFinishCertRequest(
161 pca_response,
162 key_type,
163 user_id,
164 key_name,
165 base::Bind(
166 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
167 weak_ptr_factory_.GetWeakPtr(),
168 callback,
169 "Couldn't initiate async attestation finish cert request."));
172 void TpmAttestationRegisterKey(
173 chromeos::attestation::AttestationKeyType key_type,
174 const std::string& user_id,
175 const std::string& key_name,
176 const Callback& callback) override {
177 DBusThreadManager::Get()->GetCryptohomeClient()->
178 TpmAttestationRegisterKey(
179 key_type,
180 user_id,
181 key_name,
182 base::Bind(
183 &AsyncMethodCallerImpl::RegisterAsyncCallback,
184 weak_ptr_factory_.GetWeakPtr(),
185 callback,
186 "Couldn't initiate async attestation register key."));
189 void TpmAttestationSignEnterpriseChallenge(
190 chromeos::attestation::AttestationKeyType key_type,
191 const std::string& user_id,
192 const std::string& key_name,
193 const std::string& domain,
194 const std::string& device_id,
195 chromeos::attestation::AttestationChallengeOptions options,
196 const std::string& challenge,
197 const DataCallback& callback) override {
198 DBusThreadManager::Get()->GetCryptohomeClient()->
199 TpmAttestationSignEnterpriseChallenge(
200 key_type,
201 user_id,
202 key_name,
203 domain,
204 device_id,
205 options,
206 challenge,
207 base::Bind(
208 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
209 weak_ptr_factory_.GetWeakPtr(),
210 callback,
211 "Couldn't initiate async attestation enterprise challenge."));
214 void TpmAttestationSignSimpleChallenge(
215 chromeos::attestation::AttestationKeyType key_type,
216 const std::string& user_id,
217 const std::string& key_name,
218 const std::string& challenge,
219 const DataCallback& callback) override {
220 DBusThreadManager::Get()->GetCryptohomeClient()->
221 TpmAttestationSignSimpleChallenge(
222 key_type,
223 user_id,
224 key_name,
225 challenge,
226 base::Bind(
227 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
228 weak_ptr_factory_.GetWeakPtr(),
229 callback,
230 "Couldn't initiate async attestation simple challenge."));
233 void AsyncGetSanitizedUsername(const std::string& user,
234 const DataCallback& callback) override {
235 DBusThreadManager::Get()->GetCryptohomeClient()->
236 GetSanitizedUsername(user,
237 base::Bind(
238 &AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
239 weak_ptr_factory_.GetWeakPtr(),
240 callback));
243 virtual void GetSanitizedUsernameCallback(
244 const DataCallback& callback,
245 const chromeos::DBusMethodCallStatus call_status,
246 const std::string& result) {
247 callback.Run(true, result);
250 private:
251 struct CallbackElement {
252 CallbackElement() {}
253 explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
254 : callback(callback),
255 proxy(base::MessageLoopProxy::current()) {
257 AsyncMethodCaller::Callback callback;
258 scoped_refptr<base::MessageLoopProxy> proxy;
261 struct DataCallbackElement {
262 DataCallbackElement() {}
263 explicit DataCallbackElement(
264 const AsyncMethodCaller::DataCallback& callback)
265 : data_callback(callback),
266 proxy(base::MessageLoopProxy::current()) {
268 AsyncMethodCaller::DataCallback data_callback;
269 scoped_refptr<base::MessageLoopProxy> proxy;
272 typedef base::hash_map<int, CallbackElement> CallbackMap;
273 typedef base::hash_map<int, DataCallbackElement> DataCallbackMap;
275 // Handles the response for async calls.
276 // Below is described how async calls work.
277 // 1. CryptohomeClient::AsyncXXX returns "async ID".
278 // 2. RegisterAsyncCallback registers the "async ID" with the user-provided
279 // callback.
280 // 3. Cryptohome will return the result asynchronously as a signal with
281 // "async ID"
282 // 4. "HandleAsyncResponse" handles the result signal and call the registered
283 // callback associated with the "async ID".
284 void HandleAsyncResponse(int async_id, bool return_status, int return_code) {
285 const CallbackMap::iterator it = callback_map_.find(async_id);
286 if (it == callback_map_.end()) {
287 LOG(ERROR) << "Received signal for unknown async_id " << async_id;
288 return;
290 it->second.proxy->PostTask(FROM_HERE,
291 base::Bind(it->second.callback,
292 return_status,
293 static_cast<MountError>(return_code)));
294 callback_map_.erase(it);
297 // Similar to HandleAsyncResponse but for signals with a raw data payload.
298 void HandleAsyncDataResponse(int async_id,
299 bool return_status,
300 const std::string& return_data) {
301 const DataCallbackMap::iterator it = data_callback_map_.find(async_id);
302 if (it == data_callback_map_.end()) {
303 LOG(ERROR) << "Received signal for unknown async_id " << async_id;
304 return;
306 it->second.proxy->PostTask(FROM_HERE,
307 base::Bind(it->second.data_callback, return_status, return_data));
308 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) {
313 if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
314 base::MessageLoopProxy::current()->PostTask(
315 FROM_HERE, base::Bind(callback,
316 false, // return status
317 cryptohome::MOUNT_ERROR_FATAL));
318 return;
321 if (async_id == 0) {
322 LOG(ERROR) << error;
323 return;
325 VLOG(1) << "Adding handler for " << async_id;
326 DCHECK_EQ(callback_map_.count(async_id), 0U);
327 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
328 callback_map_[async_id] = CallbackElement(callback);
331 // Registers a callback which is called when the result for AsyncXXX is ready.
332 void RegisterAsyncDataCallback(
333 DataCallback callback, const char* error, int async_id) {
334 if (async_id == chromeos::CryptohomeClient::kNotReadyAsyncId) {
335 base::MessageLoopProxy::current()->PostTask(
336 FROM_HERE, base::Bind(callback,
337 false, // return status
338 std::string()));
339 return;
341 if (async_id == 0) {
342 LOG(ERROR) << error;
343 return;
345 VLOG(1) << "Adding handler for " << async_id;
346 DCHECK_EQ(callback_map_.count(async_id), 0U);
347 DCHECK_EQ(data_callback_map_.count(async_id), 0U);
348 data_callback_map_[async_id] = DataCallbackElement(callback);
351 CallbackMap callback_map_;
352 DataCallbackMap data_callback_map_;
353 base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;
355 DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
358 } // namespace
360 // static
361 void AsyncMethodCaller::Initialize() {
362 if (g_async_method_caller) {
363 LOG(WARNING) << "AsyncMethodCaller was already initialized";
364 return;
366 g_async_method_caller = new AsyncMethodCallerImpl();
367 VLOG(1) << "AsyncMethodCaller initialized";
370 // static
371 void AsyncMethodCaller::InitializeForTesting(
372 AsyncMethodCaller* async_method_caller) {
373 if (g_async_method_caller) {
374 LOG(WARNING) << "AsyncMethodCaller was already initialized";
375 return;
377 g_async_method_caller = async_method_caller;
378 VLOG(1) << "AsyncMethodCaller initialized";
381 // static
382 void AsyncMethodCaller::Shutdown() {
383 if (!g_async_method_caller) {
384 LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
385 return;
387 delete g_async_method_caller;
388 g_async_method_caller = NULL;
389 VLOG(1) << "AsyncMethodCaller Shutdown completed";
392 // static
393 AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
394 return g_async_method_caller;
397 } // namespace cryptohome