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.
5 #include "chromeos/dbus/bluetooth_agent_service_provider.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"
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"
23 // The BluetoothAgentServiceProvider implementation used in production.
24 class BluetoothAgentServiceProviderImpl
25 : public BluetoothAgentServiceProvider
{
27 BluetoothAgentServiceProviderImpl(dbus::Bus
* bus
,
28 const dbus::ObjectPath
& object_path
,
30 : origin_thread_id_(base::PlatformThread::CurrentId()),
33 object_path_(object_path
),
34 weak_ptr_factory_(this) {
35 VLOG(1) << "Creating Bluetooth Agent: " << object_path_
.value();
37 exported_object_
= bus_
->GetExportedObject(object_path_
);
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()));
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()));
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()));
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()));
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()));
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()));
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()));
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()));
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()));
112 ~BluetoothAgentServiceProviderImpl() override
{
113 VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_
.value();
115 // Unregister the object path so we can reuse with a new agent.
116 bus_
->UnregisterExportedObject(object_path_
);
120 // Returns true if the current thread is on the origin thread.
121 bool OnOriginThread() {
122 return base::PlatformThread::CurrentId() == origin_thread_id_
;
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());
132 delegate_
->Released();
134 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
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());
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();
152 Delegate::PinCodeCallback callback
= base::Bind(
153 &BluetoothAgentServiceProviderImpl::OnPinCode
,
154 weak_ptr_factory_
.GetWeakPtr(),
158 delegate_
->RequestPinCode(device_path
, callback
);
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
164 void DisplayPinCode(dbus::MethodCall
* method_call
,
165 dbus::ExportedObject::ResponseSender response_sender
) {
166 DCHECK(OnOriginThread());
169 dbus::MessageReader
reader(method_call
);
170 dbus::ObjectPath device_path
;
172 if (!reader
.PopObjectPath(&device_path
) ||
173 !reader
.PopString(&pincode
)) {
174 LOG(WARNING
) << "DisplayPinCode called with incorrect paramters: "
175 << method_call
->ToString();
179 delegate_
->DisplayPinCode(device_path
, pincode
);
181 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
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());
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();
199 Delegate::PasskeyCallback callback
= base::Bind(
200 &BluetoothAgentServiceProviderImpl::OnPasskey
,
201 weak_ptr_factory_
.GetWeakPtr(),
205 delegate_
->RequestPasskey(device_path
, callback
);
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
211 void DisplayPasskey(dbus::MethodCall
* method_call
,
212 dbus::ExportedObject::ResponseSender response_sender
) {
213 DCHECK(OnOriginThread());
216 dbus::MessageReader
reader(method_call
);
217 dbus::ObjectPath device_path
;
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();
228 delegate_
->DisplayPasskey(device_path
, passkey
, entered
);
230 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
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());
242 dbus::MessageReader
reader(method_call
);
243 dbus::ObjectPath device_path
;
245 if (!reader
.PopObjectPath(&device_path
) ||
246 !reader
.PopUint32(&passkey
)) {
247 LOG(WARNING
) << "RequestConfirmation called with incorrect paramters: "
248 << method_call
->ToString();
252 Delegate::ConfirmationCallback callback
= base::Bind(
253 &BluetoothAgentServiceProviderImpl::OnConfirmation
,
254 weak_ptr_factory_
.GetWeakPtr(),
258 delegate_
->RequestConfirmation(device_path
, passkey
, callback
);
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());
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();
277 Delegate::ConfirmationCallback callback
= base::Bind(
278 &BluetoothAgentServiceProviderImpl::OnConfirmation
,
279 weak_ptr_factory_
.GetWeakPtr(),
283 delegate_
->RequestAuthorization(device_path
, callback
);
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
289 void AuthorizeService(dbus::MethodCall
* method_call
,
290 dbus::ExportedObject::ResponseSender response_sender
) {
291 DCHECK(OnOriginThread());
294 dbus::MessageReader
reader(method_call
);
295 dbus::ObjectPath device_path
;
297 if (!reader
.PopObjectPath(&device_path
) ||
298 !reader
.PopString(&uuid
)) {
299 LOG(WARNING
) << "AuthorizeService called with incorrect paramters: "
300 << method_call
->ToString();
304 Delegate::ConfirmationCallback callback
= base::Bind(
305 &BluetoothAgentServiceProviderImpl::OnConfirmation
,
306 weak_ptr_factory_
.GetWeakPtr(),
310 delegate_
->AuthorizeService(device_path
, uuid
, callback
);
313 // Called by dbus:: when the request failed before a reply was returned
315 void Cancel(dbus::MethodCall
* method_call
,
316 dbus::ExportedObject::ResponseSender response_sender
) {
317 DCHECK(OnOriginThread());
322 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
325 // Called by dbus:: when a method is exported.
326 void OnExported(const std::string
& interface_name
,
327 const std::string
& method_name
,
329 LOG_IF(WARNING
, !success
) << "Failed to export "
330 << interface_name
<< "." << method_name
;
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());
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());
349 case Delegate::REJECTED
: {
350 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
351 method_call
, bluetooth_agent::kErrorRejected
, "rejected"));
354 case Delegate::CANCELLED
: {
355 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
356 method_call
, bluetooth_agent::kErrorCanceled
, "canceled"));
360 NOTREACHED() << "Unexpected status code from delegate: " << status
;
364 // Called by the Delegate to response to a method requesting a Passkey.
365 void OnPasskey(dbus::MethodCall
* method_call
,
366 dbus::ExportedObject::ResponseSender response_sender
,
367 Delegate::Status status
,
369 DCHECK(OnOriginThread());
372 case Delegate::SUCCESS
: {
373 scoped_ptr
<dbus::Response
> response(
374 dbus::Response::FromMethodCall(method_call
));
375 dbus::MessageWriter
writer(response
.get());
376 writer
.AppendUint32(passkey
);
377 response_sender
.Run(response
.Pass());
380 case Delegate::REJECTED
: {
381 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
382 method_call
, bluetooth_agent::kErrorRejected
, "rejected"));
385 case Delegate::CANCELLED
: {
386 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
387 method_call
, bluetooth_agent::kErrorCanceled
, "canceled"));
391 NOTREACHED() << "Unexpected status code from delegate: " << status
;
395 // Called by the Delegate in response to a method requiring confirmation.
396 void OnConfirmation(dbus::MethodCall
* method_call
,
397 dbus::ExportedObject::ResponseSender response_sender
,
398 Delegate::Status status
) {
399 DCHECK(OnOriginThread());
402 case Delegate::SUCCESS
: {
403 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
406 case Delegate::REJECTED
: {
407 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
408 method_call
, bluetooth_agent::kErrorRejected
, "rejected"));
411 case Delegate::CANCELLED
: {
412 response_sender
.Run(dbus::ErrorResponse::FromMethodCall(
413 method_call
, bluetooth_agent::kErrorCanceled
, "canceled"));
417 NOTREACHED() << "Unexpected status code from delegate: " << status
;
421 // Origin thread (i.e. the UI thread in production).
422 base::PlatformThreadId origin_thread_id_
;
424 // D-Bus bus object is exported on, not owned by this object and must
428 // All incoming method calls are passed on to the Delegate and a callback
429 // passed to generate the reply. |delegate_| is generally the object that
430 // owns this one, and must outlive it.
433 // D-Bus object path of object we are exporting, kept so we can unregister
434 // again in our destructor.
435 dbus::ObjectPath object_path_
;
437 // D-Bus object we are exporting, owned by this object.
438 scoped_refptr
<dbus::ExportedObject
> exported_object_
;
440 // Weak pointer factory for generating 'this' pointers that might live longer
442 // Note: This should remain the last member so it'll be destroyed and
443 // invalidate its weak pointers before any other members are destroyed.
444 base::WeakPtrFactory
<BluetoothAgentServiceProviderImpl
> weak_ptr_factory_
;
446 DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl
);
449 BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {
452 BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {
456 BluetoothAgentServiceProvider
* BluetoothAgentServiceProvider::Create(
458 const dbus::ObjectPath
& object_path
,
459 Delegate
* delegate
) {
460 if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH
)) {
461 return new BluetoothAgentServiceProviderImpl(bus
, object_path
, delegate
);
463 return new FakeBluetoothAgentServiceProvider(object_path
, delegate
);
467 } // namespace chromeos