Update To 11.40.268.0
[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       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(),
122             callback,
123             "Couldn't initiate async attestation enroll request."));
124   }
125
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(),
134             callback,
135             "Couldn't initiate async attestation enroll."));
136   }
137
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(
146             pca_type,
147             certificate_profile,
148             user_id,
149             request_origin,
150             base::Bind(&AsyncMethodCallerImpl::RegisterAsyncDataCallback,
151                        weak_ptr_factory_.GetWeakPtr(),
152                        callback,
153                        "Couldn't initiate async attestation cert request."));
154   }
155
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(
164             pca_response,
165             key_type,
166             user_id,
167             key_name,
168             base::Bind(
169                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
170                 weak_ptr_factory_.GetWeakPtr(),
171                 callback,
172                 "Couldn't initiate async attestation finish cert request."));
173   }
174
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(
182             key_type,
183             user_id,
184             key_name,
185             base::Bind(
186                 &AsyncMethodCallerImpl::RegisterAsyncCallback,
187                 weak_ptr_factory_.GetWeakPtr(),
188                 callback,
189                 "Couldn't initiate async attestation register key."));
190   }
191
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(
203             key_type,
204             user_id,
205             key_name,
206             domain,
207             device_id,
208             options,
209             challenge,
210             base::Bind(
211                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
212                 weak_ptr_factory_.GetWeakPtr(),
213                 callback,
214                 "Couldn't initiate async attestation enterprise challenge."));
215   }
216
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(
225             key_type,
226             user_id,
227             key_name,
228             challenge,
229             base::Bind(
230                 &AsyncMethodCallerImpl::RegisterAsyncDataCallback,
231                 weak_ptr_factory_.GetWeakPtr(),
232                 callback,
233                 "Couldn't initiate async attestation simple challenge."));
234   }
235
236   virtual void AsyncGetSanitizedUsername(
237       const std::string& user,
238       const DataCallback& callback) override {
239     DBusThreadManager::Get()->GetCryptohomeClient()->
240         GetSanitizedUsername(user,
241         base::Bind(
242             &AsyncMethodCallerImpl::GetSanitizedUsernameCallback,
243             weak_ptr_factory_.GetWeakPtr(),
244             callback));
245   }
246
247   virtual void GetSanitizedUsernameCallback(
248       const DataCallback& callback,
249       const chromeos::DBusMethodCallStatus call_status,
250       const std::string& result) {
251     callback.Run(true, result);
252   }
253
254  private:
255   struct CallbackElement {
256     CallbackElement() {}
257     explicit CallbackElement(const AsyncMethodCaller::Callback& callback)
258         : callback(callback),
259           proxy(base::MessageLoopProxy::current()) {
260     }
261     AsyncMethodCaller::Callback callback;
262     scoped_refptr<base::MessageLoopProxy> proxy;
263   };
264
265   struct DataCallbackElement {
266     DataCallbackElement() {}
267     explicit DataCallbackElement(
268         const AsyncMethodCaller::DataCallback& callback)
269         : data_callback(callback),
270           proxy(base::MessageLoopProxy::current()) {
271     }
272     AsyncMethodCaller::DataCallback data_callback;
273     scoped_refptr<base::MessageLoopProxy> proxy;
274   };
275
276   typedef base::hash_map<int, CallbackElement> CallbackMap;
277   typedef base::hash_map<int, DataCallbackElement> DataCallbackMap;
278
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
283   //    callback.
284   // 3. Cryptohome will return the result asynchronously as a signal with
285   //    "async ID"
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;
292       return;
293     }
294     it->second.proxy->PostTask(FROM_HERE,
295         base::Bind(it->second.callback,
296                    return_status,
297                    static_cast<MountError>(return_code)));
298     callback_map_.erase(it);
299   }
300
301   // Similar to HandleAsyncResponse but for signals with a raw data payload.
302   void HandleAsyncDataResponse(int async_id,
303                                bool return_status,
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;
308       return;
309     }
310     it->second.proxy->PostTask(FROM_HERE,
311         base::Bind(it->second.data_callback, return_status, return_data));
312     data_callback_map_.erase(it);
313   }
314
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) {
318     if (async_id == 0) {
319       LOG(ERROR) << error;
320       return;
321     }
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);
326   }
327
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) {
331     if (async_id == 0) {
332       LOG(ERROR) << error;
333       return;
334     }
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);
339   }
340
341   base::WeakPtrFactory<AsyncMethodCallerImpl> weak_ptr_factory_;
342   CallbackMap callback_map_;
343   DataCallbackMap data_callback_map_;
344
345   DISALLOW_COPY_AND_ASSIGN(AsyncMethodCallerImpl);
346 };
347
348 }  // namespace
349
350 // static
351 void AsyncMethodCaller::Initialize() {
352   if (g_async_method_caller) {
353     LOG(WARNING) << "AsyncMethodCaller was already initialized";
354     return;
355   }
356   g_async_method_caller = new AsyncMethodCallerImpl();
357   VLOG(1) << "AsyncMethodCaller initialized";
358 }
359
360 // static
361 void AsyncMethodCaller::InitializeForTesting(
362     AsyncMethodCaller* async_method_caller) {
363   if (g_async_method_caller) {
364     LOG(WARNING) << "AsyncMethodCaller was already initialized";
365     return;
366   }
367   g_async_method_caller = async_method_caller;
368   VLOG(1) << "AsyncMethodCaller initialized";
369 }
370
371 // static
372 void AsyncMethodCaller::Shutdown() {
373   if (!g_async_method_caller) {
374     LOG(WARNING) << "AsyncMethodCaller::Shutdown() called with NULL manager";
375     return;
376   }
377   delete g_async_method_caller;
378   g_async_method_caller = NULL;
379   VLOG(1) << "AsyncMethodCaller Shutdown completed";
380 }
381
382 // static
383 AsyncMethodCaller* AsyncMethodCaller::GetInstance() {
384   return g_async_method_caller;
385 }
386
387 }  // namespace cryptohome