- add sources.
[platform/framework/web/crosswalk.git] / src / chromeos / cryptohome / async_method_caller.cc
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.
4
5 #include "chromeos/cryptohome/async_method_caller.h"
6
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/cryptohome_client.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13
14 using chromeos::DBusThreadManager;
15
16 namespace cryptohome {
17
18 namespace {
19
20 AsyncMethodCaller* g_async_method_caller = NULL;
21
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()));
31   }
32
33   virtual ~AsyncMethodCallerImpl() {
34     DBusThreadManager::Get()->GetCryptohomeClient()->
35         ResetAsyncCallStatusHandlers();
36   }
37
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(),
45             callback,
46             "Couldn't initiate async check of user's key."));
47   }
48
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(),
57             callback,
58             "Couldn't initiate aync migration of user's key"));
59   }
60
61   virtual 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."));
71   }
72
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(),
81             callback,
82             "Couldn't initiate async key addition."));
83   }
84
85   virtual 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."));
92   }
93
94   virtual 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."));
103   }
104
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(),
111             callback,
112             "Couldn't initiate async removal of cryptohome."));
113   }
114
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(),
121             callback,
122             "Couldn't initiate async attestation enroll request."));
123   }
124
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(),
131             callback,
132             "Couldn't initiate async attestation enroll."));
133   }
134
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(
142             certificate_profile,
143             user_id,
144             request_origin,
145             base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
146                        weak_ptr_factory_.GetWeakPtr(),
147                        callback,
148                        "Couldn't initiate async attestation cert request."));
149   }
150
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(
159             pca_response,
160             key_type,
161             user_id,
162             key_name,
163             base::Bind(
164                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
165                 weak_ptr_factory_.GetWeakPtr(),
166                 callback,
167                 "Couldn't initiate async attestation finish cert request."));
168   }
169
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(
177             key_type,
178             user_id,
179             key_name,
180             base::Bind(
181                 &AsyncMethodCallerImpl::RegisterAsyncCallback,
182                 weak_ptr_factory_.GetWeakPtr(),
183                 callback,
184                 "Couldn't initiate async attestation register key."));
185   }
186
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(
198             key_type,
199             user_id,
200             key_name,
201             domain,
202             device_id,
203             options,
204             challenge,
205             base::Bind(
206                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
207                 weak_ptr_factory_.GetWeakPtr(),
208                 callback,
209                 "Couldn't initiate async attestation enterprise challenge."));
210   }
211
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(
220             key_type,
221             user_id,
222             key_name,
223             challenge,
224             base::Bind(
225                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
226                 weak_ptr_factory_.GetWeakPtr(),
227                 callback,
228                 "Couldn't initiate async attestation simple challenge."));
229   }
230
231   virtual void AsyncGetSanitizedUsername(
232       const std::string& user,
233       const DataCallback& callback) OVERRIDE {
234     DBusThreadManager::Get()->GetCryptohomeClient()->
235         GetSanitizedUsername(user,
236         base::Bind(
237             &AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
238             weak_ptr_factory_.GetWeakPtr(),
239             callback));
240   }
241
242   virtual void GetSanitizedUsernameCallback(
243       const DataCallback& callback,
244       const chromeos::DBusMethodCallStatus call_status,
245       const std::string& result) {
246     callback.Run(true, result);
247   }
248
249  private:
250   struct CallbackElement {
251     CallbackElement() {}
252     explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
253         : callback(callback),
254           proxy(base::MessageLoopProxy::current()) {
255     }
256     AsyncMethodCaller::Callback callback;
257     scoped_refptr<base::MessageLoopProxy> proxy;
258   };
259
260   struct DataCallbackElement {
261     DataCallbackElement() {}
262     explicit DataCallbackElement(
263         const AsyncMethodCaller::DataCallback& callback)
264         : data_callback(callback),
265           proxy(base::MessageLoopProxy::current()) {
266     }
267     AsyncMethodCaller::DataCallback data_callback;
268     scoped_refptr<base::MessageLoopProxy> proxy;
269   };
270
271   typedef base::hash_map<int, CallbackElement> CallbackMap;
272   typedef base::hash_map<int, DataCallbackElement> DataCallbackMap;
273
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;
288     }
289     it->second.proxy->PostTask(FROM_HERE,
290         base::Bind(it->second.callback,
291                    return_status,
292                    static_cast<MountError>(return_code)));
293     callback_map_.erase(it);
294   }
295
296   // Similar to HandleAsyncResponse but for signals with a raw data payload.
297   void HandleAsyncDataResponse(int async_id,
298                                bool return_status,
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;
303       return;
304     }
305     it->second.proxy->PostTask(FROM_HERE,
306         base::Bind(it->second.data_callback, return_status, return_data));
307     data_callback_map_.erase(it);
308   }
309
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 == 0) {
314       LOG(ERROR) << error;
315       return;
316     }
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);
321   }
322
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) {
326     if (async_id == 0) {
327       LOG(ERROR) << error;
328       return;
329     }
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);
334   }
335
336   base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;
337   CallbackMap callback_map_;
338   DataCallbackMap data_callback_map_;
339
340   DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
341 };
342
343 }  // namespace
344
345 // static
346 void AsyncMethodCaller::Initialize() {
347   if (g_async_method_caller) {
348     LOG(WARNING) << "AsyncMethodCaller was already initialized";
349     return;
350   }
351   g_async_method_caller = new AsyncMethodCallerImpl();
352   VLOG(1) << "AsyncMethodCaller initialized";
353 }
354
355 // static
356 void AsyncMethodCaller::InitializeForTesting(
357     AsyncMethodCaller* async_method_caller) {
358   if (g_async_method_caller) {
359     LOG(WARNING) << "AsyncMethodCaller was already initialized";
360     return;
361   }
362   g_async_method_caller = async_method_caller;
363   VLOG(1) << "AsyncMethodCaller initialized";
364 }
365
366 // static
367 void AsyncMethodCaller::Shutdown() {
368   if (!g_async_method_caller) {
369     LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
370     return;
371   }
372   delete g_async_method_caller;
373   g_async_method_caller = NULL;
374   VLOG(1) << "AsyncMethodCaller Shutdown completed";
375 }
376
377 // static
378 AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
379   return g_async_method_caller;
380 }
381
382 }  // namespace cryptohome