Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / bluetooth_agent_service_provider.cc
1 // Copyright 2013 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/dbus/bluetooth_agent_service_provider.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/threading/platform_thread.h"
13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
15 #include "dbus/bus.h"
16 #include "dbus/exported_object.h"
17 #include "dbus/message.h"
18 #include "dbus/object_path.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
20
21 namespace chromeos {
22
23 // The BluetoothAgentServiceProvider implementation used in production.
24 class BluetoothAgentServiceProviderImpl
25     : public BluetoothAgentServiceProvider {
26  public:
27   BluetoothAgentServiceProviderImpl(dbus::Bus* bus,
28                                     const dbus::ObjectPath& object_path,
29                                     Delegate* delegate)
30       : origin_thread_id_(base::PlatformThread::CurrentId()),
31         bus_(bus),
32         delegate_(delegate),
33         object_path_(object_path),
34         weak_ptr_factory_(this) {
35     VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value();
36
37     exported_object_ = bus_->GetExportedObject(object_path_);
38
39     exported_object_->ExportMethod(
40         bluetooth_agent::kBluetoothAgentInterface,
41         bluetooth_agent::kRelease,
42         base::Bind(&BluetoothAgentServiceProviderImpl::Release,
43                    weak_ptr_factory_.GetWeakPtr()),
44         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
45                    weak_ptr_factory_.GetWeakPtr()));
46
47     exported_object_->ExportMethod(
48         bluetooth_agent::kBluetoothAgentInterface,
49         bluetooth_agent::kRequestPinCode,
50         base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode,
51                    weak_ptr_factory_.GetWeakPtr()),
52         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
53                    weak_ptr_factory_.GetWeakPtr()));
54
55     exported_object_->ExportMethod(
56         bluetooth_agent::kBluetoothAgentInterface,
57         bluetooth_agent::kDisplayPinCode,
58         base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode,
59                    weak_ptr_factory_.GetWeakPtr()),
60         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
61                    weak_ptr_factory_.GetWeakPtr()));
62
63     exported_object_->ExportMethod(
64         bluetooth_agent::kBluetoothAgentInterface,
65         bluetooth_agent::kRequestPasskey,
66         base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey,
67                    weak_ptr_factory_.GetWeakPtr()),
68         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
69                    weak_ptr_factory_.GetWeakPtr()));
70
71     exported_object_->ExportMethod(
72         bluetooth_agent::kBluetoothAgentInterface,
73         bluetooth_agent::kDisplayPasskey,
74         base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey,
75                    weak_ptr_factory_.GetWeakPtr()),
76         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
77                    weak_ptr_factory_.GetWeakPtr()));
78
79     exported_object_->ExportMethod(
80         bluetooth_agent::kBluetoothAgentInterface,
81         bluetooth_agent::kRequestConfirmation,
82         base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation,
83                    weak_ptr_factory_.GetWeakPtr()),
84         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
85                    weak_ptr_factory_.GetWeakPtr()));
86
87     exported_object_->ExportMethod(
88         bluetooth_agent::kBluetoothAgentInterface,
89         bluetooth_agent::kRequestAuthorization,
90         base::Bind(&BluetoothAgentServiceProviderImpl::RequestAuthorization,
91                    weak_ptr_factory_.GetWeakPtr()),
92         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
93                    weak_ptr_factory_.GetWeakPtr()));
94
95     exported_object_->ExportMethod(
96         bluetooth_agent::kBluetoothAgentInterface,
97         bluetooth_agent::kAuthorizeService,
98         base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeService,
99                    weak_ptr_factory_.GetWeakPtr()),
100         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
101                    weak_ptr_factory_.GetWeakPtr()));
102
103     exported_object_->ExportMethod(
104         bluetooth_agent::kBluetoothAgentInterface,
105         bluetooth_agent::kCancel,
106         base::Bind(&BluetoothAgentServiceProviderImpl::Cancel,
107                    weak_ptr_factory_.GetWeakPtr()),
108         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
109                    weak_ptr_factory_.GetWeakPtr()));
110   }
111
112   virtual ~BluetoothAgentServiceProviderImpl() {
113     VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value();
114
115     // Unregister the object path so we can reuse with a new agent.
116     bus_->UnregisterExportedObject(object_path_);
117   }
118
119  private:
120   // Returns true if the current thread is on the origin thread.
121   bool OnOriginThread() {
122     return base::PlatformThread::CurrentId() == origin_thread_id_;
123   }
124
125   // Called by dbus:: when the agent is unregistered from the Bluetooth
126   // daemon, generally at the end of a pairing request.
127   void Release(dbus::MethodCall* method_call,
128                dbus::ExportedObject::ResponseSender response_sender) {
129     DCHECK(OnOriginThread());
130     DCHECK(delegate_);
131
132     delegate_->Released();
133
134     response_sender.Run(dbus::Response::FromMethodCall(method_call));
135   }
136
137   // Called by dbus:: when the Bluetooth daemon requires a PIN Code for
138   // device authentication.
139   void RequestPinCode(dbus::MethodCall* method_call,
140                       dbus::ExportedObject::ResponseSender response_sender) {
141     DCHECK(OnOriginThread());
142     DCHECK(delegate_);
143
144     dbus::MessageReader reader(method_call);
145     dbus::ObjectPath device_path;
146     if (!reader.PopObjectPath(&device_path)) {
147       LOG(WARNING) << "RequestPinCode called with incorrect paramters: "
148                    << method_call->ToString();
149       return;
150     }
151
152     Delegate::PinCodeCallback callback = base::Bind(
153         &BluetoothAgentServiceProviderImpl::OnPinCode,
154         weak_ptr_factory_.GetWeakPtr(),
155         method_call,
156         response_sender);
157
158     delegate_->RequestPinCode(device_path, callback);
159   }
160
161   // Called by dbus:: when the Bluetooth daemon requires that the user
162   // enter a PIN Code into the remote device so that it may be
163   // authenticated.
164   void DisplayPinCode(dbus::MethodCall* method_call,
165                       dbus::ExportedObject::ResponseSender response_sender) {
166     DCHECK(OnOriginThread());
167     DCHECK(delegate_);
168
169     dbus::MessageReader reader(method_call);
170     dbus::ObjectPath device_path;
171     std::string pincode;
172     if (!reader.PopObjectPath(&device_path) ||
173         !reader.PopString(&pincode)) {
174       LOG(WARNING) << "DisplayPinCode called with incorrect paramters: "
175                    << method_call->ToString();
176       return;
177     }
178
179     delegate_->DisplayPinCode(device_path, pincode);
180
181     response_sender.Run(dbus::Response::FromMethodCall(method_call));
182   }
183
184   // Called by dbus:: when the Bluetooth daemon requires a Passkey for
185   // device authentication.
186   void RequestPasskey(dbus::MethodCall* method_call,
187                       dbus::ExportedObject::ResponseSender response_sender) {
188     DCHECK(OnOriginThread());
189     DCHECK(delegate_);
190
191     dbus::MessageReader reader(method_call);
192     dbus::ObjectPath device_path;
193     if (!reader.PopObjectPath(&device_path)) {
194       LOG(WARNING) << "RequestPasskey called with incorrect paramters: "
195                    << method_call->ToString();
196       return;
197     }
198
199     Delegate::PasskeyCallback callback = base::Bind(
200         &BluetoothAgentServiceProviderImpl::OnPasskey,
201         weak_ptr_factory_.GetWeakPtr(),
202         method_call,
203         response_sender);
204
205     delegate_->RequestPasskey(device_path, callback);
206   }
207
208   // Called by dbus:: when the Bluetooth daemon requires that the user
209   // enter a Passkey into the remote device so that it may be
210   // authenticated.
211   void DisplayPasskey(dbus::MethodCall* method_call,
212                       dbus::ExportedObject::ResponseSender response_sender) {
213     DCHECK(OnOriginThread());
214     DCHECK(delegate_);
215
216     dbus::MessageReader reader(method_call);
217     dbus::ObjectPath device_path;
218     uint32 passkey;
219     uint16 entered;
220     if (!reader.PopObjectPath(&device_path) ||
221         !reader.PopUint32(&passkey) ||
222         !reader.PopUint16(&entered)) {
223       LOG(WARNING) << "DisplayPasskey called with incorrect paramters: "
224                    << method_call->ToString();
225       return;
226     }
227
228     delegate_->DisplayPasskey(device_path, passkey, entered);
229
230     response_sender.Run(dbus::Response::FromMethodCall(method_call));
231   }
232
233   // Called by dbus:: when the Bluetooth daemon requires that the user
234   // confirm that a Passkey is displayed on the screen of the remote
235   // device so that it may be authenticated.
236   void RequestConfirmation(
237       dbus::MethodCall* method_call,
238       dbus::ExportedObject::ResponseSender response_sender) {
239     DCHECK(OnOriginThread());
240     DCHECK(delegate_);
241
242     dbus::MessageReader reader(method_call);
243     dbus::ObjectPath device_path;
244     uint32 passkey;
245     if (!reader.PopObjectPath(&device_path) ||
246         !reader.PopUint32(&passkey)) {
247       LOG(WARNING) << "RequestConfirmation called with incorrect paramters: "
248                    << method_call->ToString();
249       return;
250     }
251
252     Delegate::ConfirmationCallback callback = base::Bind(
253         &BluetoothAgentServiceProviderImpl::OnConfirmation,
254         weak_ptr_factory_.GetWeakPtr(),
255         method_call,
256         response_sender);
257
258     delegate_->RequestConfirmation(device_path, passkey, callback);
259   }
260
261   // Called by dbus:: when the Bluetooth daemon requires that the user
262   // confirm an incoming just-works pairing.
263   void RequestAuthorization(
264         dbus::MethodCall* method_call,
265         dbus::ExportedObject::ResponseSender response_sender) {
266     DCHECK(OnOriginThread());
267     DCHECK(delegate_);
268
269     dbus::MessageReader reader(method_call);
270     dbus::ObjectPath device_path;
271     if (!reader.PopObjectPath(&device_path)) {
272       LOG(WARNING) << "RequestAuthorization called with incorrect paramters: "
273                    << method_call->ToString();
274       return;
275     }
276
277     Delegate::ConfirmationCallback callback = base::Bind(
278         &BluetoothAgentServiceProviderImpl::OnConfirmation,
279         weak_ptr_factory_.GetWeakPtr(),
280         method_call,
281         response_sender);
282
283     delegate_->RequestAuthorization(device_path, callback);
284   }
285
286   // Called by dbus:: when the Bluetooth daemon requires that the user
287   // confirm that that a remote device is authorized to connect to a service
288   // UUID.
289   void AuthorizeService(dbus::MethodCall* method_call,
290                         dbus::ExportedObject::ResponseSender response_sender) {
291     DCHECK(OnOriginThread());
292     DCHECK(delegate_);
293
294     dbus::MessageReader reader(method_call);
295     dbus::ObjectPath device_path;
296     std::string uuid;
297     if (!reader.PopObjectPath(&device_path) ||
298         !reader.PopString(&uuid)) {
299       LOG(WARNING) << "AuthorizeService called with incorrect paramters: "
300                    << method_call->ToString();
301       return;
302     }
303
304     Delegate::ConfirmationCallback callback = base::Bind(
305         &BluetoothAgentServiceProviderImpl::OnConfirmation,
306         weak_ptr_factory_.GetWeakPtr(),
307         method_call,
308         response_sender);
309
310     delegate_->AuthorizeService(device_path, uuid, callback);
311   }
312
313   // Called by dbus:: when the request failed before a reply was returned
314   // from the device.
315   void Cancel(dbus::MethodCall* method_call,
316               dbus::ExportedObject::ResponseSender response_sender) {
317     DCHECK(OnOriginThread());
318     DCHECK(delegate_);
319
320     delegate_->Cancel();
321
322     response_sender.Run(dbus::Response::FromMethodCall(method_call));
323   }
324
325   // Called by dbus:: when a method is exported.
326   void OnExported(const std::string& interface_name,
327                   const std::string& method_name,
328                   bool success) {
329     LOG_IF(WARNING, !success) << "Failed to export "
330                               << interface_name << "." << method_name;
331   }
332
333   // Called by the Delegate to response to a method requesting a PIN code.
334   void OnPinCode(dbus::MethodCall* method_call,
335                  dbus::ExportedObject::ResponseSender response_sender,
336                  Delegate::Status status,
337                  const std::string& pincode) {
338     DCHECK(OnOriginThread());
339
340     switch (status) {
341       case Delegate::SUCCESS: {
342         scoped_ptr<dbus::Response> response(
343             dbus::Response::FromMethodCall(method_call));
344         dbus::MessageWriter writer(response.get());
345         writer.AppendString(pincode);
346         response_sender.Run(response.Pass());
347         break;
348       }
349       case Delegate::REJECTED: {
350         response_sender.Run(
351             dbus::ErrorResponse::FromMethodCall(
352                 method_call, bluetooth_agent::kErrorRejected, "rejected")
353             .PassAs<dbus::Response>());
354         break;
355       }
356       case Delegate::CANCELLED: {
357         response_sender.Run(
358             dbus::ErrorResponse::FromMethodCall(
359                 method_call, bluetooth_agent::kErrorCanceled, "canceled")
360             .PassAs<dbus::Response>());
361         break;
362       }
363       default:
364         NOTREACHED() << "Unexpected status code from delegate: " << status;
365     }
366   }
367
368   // Called by the Delegate to response to a method requesting a Passkey.
369   void OnPasskey(dbus::MethodCall* method_call,
370                  dbus::ExportedObject::ResponseSender response_sender,
371                  Delegate::Status status,
372                  uint32 passkey) {
373     DCHECK(OnOriginThread());
374
375     switch (status) {
376       case Delegate::SUCCESS: {
377         scoped_ptr<dbus::Response> response(
378             dbus::Response::FromMethodCall(method_call));
379         dbus::MessageWriter writer(response.get());
380         writer.AppendUint32(passkey);
381         response_sender.Run(response.Pass());
382         break;
383       }
384       case Delegate::REJECTED: {
385         response_sender.Run(
386             dbus::ErrorResponse::FromMethodCall(
387                 method_call, bluetooth_agent::kErrorRejected, "rejected")
388             .PassAs<dbus::Response>());
389         break;
390       }
391       case Delegate::CANCELLED: {
392         response_sender.Run(
393             dbus::ErrorResponse::FromMethodCall(
394                 method_call, bluetooth_agent::kErrorCanceled, "canceled")
395             .PassAs<dbus::Response>());
396         break;
397       }
398       default:
399         NOTREACHED() << "Unexpected status code from delegate: " << status;
400     }
401   }
402
403   // Called by the Delegate in response to a method requiring confirmation.
404   void OnConfirmation(dbus::MethodCall* method_call,
405                       dbus::ExportedObject::ResponseSender response_sender,
406                       Delegate::Status status) {
407     DCHECK(OnOriginThread());
408
409     switch (status) {
410       case Delegate::SUCCESS: {
411         response_sender.Run(dbus::Response::FromMethodCall(method_call));
412         break;
413       }
414       case Delegate::REJECTED: {
415         response_sender.Run(
416             dbus::ErrorResponse::FromMethodCall(
417                 method_call, bluetooth_agent::kErrorRejected, "rejected")
418             .PassAs<dbus::Response>());
419         break;
420       }
421       case Delegate::CANCELLED: {
422         response_sender.Run(
423             dbus::ErrorResponse::FromMethodCall(
424                 method_call, bluetooth_agent::kErrorCanceled, "canceled")
425             .PassAs<dbus::Response>());
426         break;
427       }
428       default:
429         NOTREACHED() << "Unexpected status code from delegate: " << status;
430     }
431   }
432
433   // Origin thread (i.e. the UI thread in production).
434   base::PlatformThreadId origin_thread_id_;
435
436   // D-Bus bus object is exported on, not owned by this object and must
437   // outlive it.
438   dbus::Bus* bus_;
439
440   // All incoming method calls are passed on to the Delegate and a callback
441   // passed to generate the reply. |delegate_| is generally the object that
442   // owns this one, and must outlive it.
443   Delegate* delegate_;
444
445   // D-Bus object path of object we are exporting, kept so we can unregister
446   // again in our destructor.
447   dbus::ObjectPath object_path_;
448
449   // D-Bus object we are exporting, owned by this object.
450   scoped_refptr<dbus::ExportedObject> exported_object_;
451
452   // Weak pointer factory for generating 'this' pointers that might live longer
453   // than we do.
454   // Note: This should remain the last member so it'll be destroyed and
455   // invalidate its weak pointers before any other members are destroyed.
456   base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_;
457
458   DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl);
459 };
460
461 BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {
462 }
463
464 BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {
465 }
466
467 // static
468 BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create(
469     dbus::Bus* bus,
470     const dbus::ObjectPath& object_path,
471     Delegate* delegate) {
472   if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
473     return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate);
474   } else {
475     return new FakeBluetoothAgentServiceProvider(object_path, delegate);
476   }
477 }
478
479 }  // namespace chromeos