1 // Copyright (c) 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/experimental_bluetooth_agent_service_provider.h"
10 #include "base/chromeos/chromeos_version.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/threading/platform_thread.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 ExperimentalBluetoothAgentServiceProvider implementation used in
25 class ExperimentalBluetoothAgentServiceProviderImpl
26 : public ExperimentalBluetoothAgentServiceProvider
{
28 ExperimentalBluetoothAgentServiceProviderImpl(
30 const dbus::ObjectPath
& object_path
,
32 : origin_thread_id_(base::PlatformThread::CurrentId()),
35 object_path_(object_path
),
36 weak_ptr_factory_(this) {
37 VLOG(1) << "Creating Bluetooth Agent: " << object_path_
.value();
39 exported_object_
= bus_
->GetExportedObject(object_path_
);
41 exported_object_
->ExportMethod(
42 bluetooth_agent::kBluetoothAgentInterface
,
43 bluetooth_agent::kRelease
,
45 &ExperimentalBluetoothAgentServiceProviderImpl::Release
,
46 weak_ptr_factory_
.GetWeakPtr()),
48 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
49 weak_ptr_factory_
.GetWeakPtr()));
51 exported_object_
->ExportMethod(
52 bluetooth_agent::kBluetoothAgentInterface
,
53 bluetooth_agent::kRequestPinCode
,
55 &ExperimentalBluetoothAgentServiceProviderImpl::RequestPinCode
,
56 weak_ptr_factory_
.GetWeakPtr()),
58 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
59 weak_ptr_factory_
.GetWeakPtr()));
61 exported_object_
->ExportMethod(
62 bluetooth_agent::kBluetoothAgentInterface
,
63 bluetooth_agent::kDisplayPinCode
,
65 &ExperimentalBluetoothAgentServiceProviderImpl::DisplayPinCode
,
66 weak_ptr_factory_
.GetWeakPtr()),
68 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
69 weak_ptr_factory_
.GetWeakPtr()));
71 exported_object_
->ExportMethod(
72 bluetooth_agent::kBluetoothAgentInterface
,
73 bluetooth_agent::kRequestPasskey
,
75 &ExperimentalBluetoothAgentServiceProviderImpl::RequestPasskey
,
76 weak_ptr_factory_
.GetWeakPtr()),
78 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
79 weak_ptr_factory_
.GetWeakPtr()));
81 exported_object_
->ExportMethod(
82 bluetooth_agent::kBluetoothAgentInterface
,
83 bluetooth_agent::kDisplayPasskey
,
85 &ExperimentalBluetoothAgentServiceProviderImpl::DisplayPasskey
,
86 weak_ptr_factory_
.GetWeakPtr()),
88 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
89 weak_ptr_factory_
.GetWeakPtr()));
91 exported_object_
->ExportMethod(
92 bluetooth_agent::kBluetoothAgentInterface
,
93 bluetooth_agent::kRequestConfirmation
,
95 &ExperimentalBluetoothAgentServiceProviderImpl::RequestConfirmation
,
96 weak_ptr_factory_
.GetWeakPtr()),
98 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
99 weak_ptr_factory_
.GetWeakPtr()));
101 exported_object_
->ExportMethod(
102 bluetooth_agent::kBluetoothAgentInterface
,
103 bluetooth_agent::kRequestAuthorization
,
105 &ExperimentalBluetoothAgentServiceProviderImpl::RequestAuthorization
,
106 weak_ptr_factory_
.GetWeakPtr()),
108 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
109 weak_ptr_factory_
.GetWeakPtr()));
111 exported_object_
->ExportMethod(
112 bluetooth_agent::kBluetoothAgentInterface
,
113 bluetooth_agent::kAuthorizeService
,
115 &ExperimentalBluetoothAgentServiceProviderImpl::AuthorizeService
,
116 weak_ptr_factory_
.GetWeakPtr()),
118 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
119 weak_ptr_factory_
.GetWeakPtr()));
121 exported_object_
->ExportMethod(
122 bluetooth_agent::kBluetoothAgentInterface
,
123 bluetooth_agent::kCancel
,
125 &ExperimentalBluetoothAgentServiceProviderImpl::Cancel
,
126 weak_ptr_factory_
.GetWeakPtr()),
128 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported
,
129 weak_ptr_factory_
.GetWeakPtr()));
132 virtual ~ExperimentalBluetoothAgentServiceProviderImpl() {
133 VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_
.value();
135 // Unregister the object path so we can reuse with a new agent.
136 bus_
->UnregisterExportedObject(object_path_
);
140 // Returns true if the current thread is on the origin thread.
141 bool OnOriginThread() {
142 return base::PlatformThread::CurrentId() == origin_thread_id_
;
145 // Called by dbus:: when the agent is unregistered from the Bluetooth
146 // daemon, generally at the end of a pairing request.
147 void Release(dbus::MethodCall
* method_call
,
148 dbus::ExportedObject::ResponseSender response_sender
) {
149 DCHECK(OnOriginThread());
152 delegate_
->Release();
154 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
157 // Called by dbus:: when the Bluetooth daemon requires a PIN Code for
158 // device authentication.
159 void RequestPinCode(dbus::MethodCall
* method_call
,
160 dbus::ExportedObject::ResponseSender response_sender
) {
161 DCHECK(OnOriginThread());
164 dbus::MessageReader
reader(method_call
);
165 dbus::ObjectPath device_path
;
166 if (!reader
.PopObjectPath(&device_path
)) {
167 LOG(WARNING
) << "RequestPinCode called with incorrect paramters: "
168 << method_call
->ToString();
172 Delegate::PinCodeCallback callback
= base::Bind(
173 &ExperimentalBluetoothAgentServiceProviderImpl::OnPinCode
,
174 weak_ptr_factory_
.GetWeakPtr(),
178 delegate_
->RequestPinCode(device_path
, callback
);
181 // Called by dbus:: when the Bluetooth daemon requires that the user
182 // enter a PIN Code into the remote device so that it may be
184 void DisplayPinCode(dbus::MethodCall
* method_call
,
185 dbus::ExportedObject::ResponseSender response_sender
) {
186 DCHECK(OnOriginThread());
189 dbus::MessageReader
reader(method_call
);
190 dbus::ObjectPath device_path
;
192 if (!reader
.PopObjectPath(&device_path
) ||
193 !reader
.PopString(&pincode
)) {
194 LOG(WARNING
) << "DisplayPinCode called with incorrect paramters: "
195 << method_call
->ToString();
199 delegate_
->DisplayPinCode(device_path
, pincode
);
201 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
204 // Called by dbus:: when the Bluetooth daemon requires a Passkey for
205 // device authentication.
206 void RequestPasskey(dbus::MethodCall
* method_call
,
207 dbus::ExportedObject::ResponseSender response_sender
) {
208 DCHECK(OnOriginThread());
211 dbus::MessageReader
reader(method_call
);
212 dbus::ObjectPath device_path
;
213 if (!reader
.PopObjectPath(&device_path
)) {
214 LOG(WARNING
) << "RequestPasskey called with incorrect paramters: "
215 << method_call
->ToString();
219 Delegate::PasskeyCallback callback
= base::Bind(
220 &ExperimentalBluetoothAgentServiceProviderImpl::OnPasskey
,
221 weak_ptr_factory_
.GetWeakPtr(),
225 delegate_
->RequestPasskey(device_path
, callback
);
228 // Called by dbus:: when the Bluetooth daemon requires that the user
229 // enter a Passkey into the remote device so that it may be
231 void DisplayPasskey(dbus::MethodCall
* method_call
,
232 dbus::ExportedObject::ResponseSender response_sender
) {
233 DCHECK(OnOriginThread());
236 dbus::MessageReader
reader(method_call
);
237 dbus::ObjectPath device_path
;
240 if (!reader
.PopObjectPath(&device_path
) ||
241 !reader
.PopUint32(&passkey
) ||
242 !reader
.PopUint16(&entered
)) {
243 LOG(WARNING
) << "DisplayPasskey called with incorrect paramters: "
244 << method_call
->ToString();
248 delegate_
->DisplayPasskey(device_path
, passkey
, entered
);
250 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
253 // Called by dbus:: when the Bluetooth daemon requires that the user
254 // confirm that a Passkey is displayed on the screen of the remote
255 // device so that it may be authenticated.
256 void RequestConfirmation(
257 dbus::MethodCall
* method_call
,
258 dbus::ExportedObject::ResponseSender response_sender
) {
259 DCHECK(OnOriginThread());
262 dbus::MessageReader
reader(method_call
);
263 dbus::ObjectPath device_path
;
265 if (!reader
.PopObjectPath(&device_path
) ||
266 !reader
.PopUint32(&passkey
)) {
267 LOG(WARNING
) << "RequestConfirmation called with incorrect paramters: "
268 << method_call
->ToString();
272 Delegate::ConfirmationCallback callback
= base::Bind(
273 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation
,
274 weak_ptr_factory_
.GetWeakPtr(),
278 delegate_
->RequestConfirmation(device_path
, passkey
, callback
);
281 // Called by dbus:: when the Bluetooth daemon requires that the user
282 // confirm an incoming just-works pairing.
283 void RequestAuthorization(
284 dbus::MethodCall
* method_call
,
285 dbus::ExportedObject::ResponseSender response_sender
) {
286 DCHECK(OnOriginThread());
289 dbus::MessageReader
reader(method_call
);
290 dbus::ObjectPath device_path
;
291 if (!reader
.PopObjectPath(&device_path
)) {
292 LOG(WARNING
) << "RequestAuthorization called with incorrect paramters: "
293 << method_call
->ToString();
297 Delegate::ConfirmationCallback callback
= base::Bind(
298 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation
,
299 weak_ptr_factory_
.GetWeakPtr(),
303 delegate_
->RequestAuthorization(device_path
, callback
);
306 // Called by dbus:: when the Bluetooth daemon requires that the user
307 // confirm that that a remote device is authorized to connect to a service
309 void AuthorizeService(dbus::MethodCall
* method_call
,
310 dbus::ExportedObject::ResponseSender response_sender
) {
311 DCHECK(OnOriginThread());
314 dbus::MessageReader
reader(method_call
);
315 dbus::ObjectPath device_path
;
317 if (!reader
.PopObjectPath(&device_path
) ||
318 !reader
.PopString(&uuid
)) {
319 LOG(WARNING
) << "AuthorizeService called with incorrect paramters: "
320 << method_call
->ToString();
324 Delegate::ConfirmationCallback callback
= base::Bind(
325 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation
,
326 weak_ptr_factory_
.GetWeakPtr(),
330 delegate_
->AuthorizeService(device_path
, uuid
, callback
);
333 // Called by dbus:: when the request failed before a reply was returned
335 void Cancel(dbus::MethodCall
* method_call
,
336 dbus::ExportedObject::ResponseSender response_sender
) {
337 DCHECK(OnOriginThread());
342 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
345 // Called by dbus:: when a method is exported.
346 void OnExported(const std::string
& interface_name
,
347 const std::string
& method_name
,
349 LOG_IF(WARNING
, !success
) << "Failed to export "
350 << interface_name
<< "." << method_name
;
353 // Called by the Delegate to response to a method requesting a PIN code.
354 void OnPinCode(dbus::MethodCall
* method_call
,
355 dbus::ExportedObject::ResponseSender response_sender
,
356 Delegate::Status status
,
357 const std::string
& pincode
) {
358 DCHECK(OnOriginThread());
361 case Delegate::SUCCESS
: {
362 scoped_ptr
<dbus::Response
> response(
363 dbus::Response::FromMethodCall(method_call
));
364 dbus::MessageWriter
writer(response
.get());
365 writer
.AppendString(pincode
);
366 response_sender
.Run(response
.Pass());
369 case Delegate::REJECTED
: {
371 dbus::ErrorResponse::FromMethodCall(
372 method_call
, bluetooth_agent::kErrorRejected
, "rejected")
373 .PassAs
<dbus::Response
>());
376 case Delegate::CANCELLED
: {
378 dbus::ErrorResponse::FromMethodCall(
379 method_call
, bluetooth_agent::kErrorCanceled
, "canceled")
380 .PassAs
<dbus::Response
>());
384 NOTREACHED() << "Unexpected status code from delegate: " << status
;
388 // Called by the Delegate to response to a method requesting a Passkey.
389 void OnPasskey(dbus::MethodCall
* method_call
,
390 dbus::ExportedObject::ResponseSender response_sender
,
391 Delegate::Status status
,
393 DCHECK(OnOriginThread());
396 case Delegate::SUCCESS
: {
397 scoped_ptr
<dbus::Response
> response(
398 dbus::Response::FromMethodCall(method_call
));
399 dbus::MessageWriter
writer(response
.get());
400 writer
.AppendUint32(passkey
);
401 response_sender
.Run(response
.Pass());
404 case Delegate::REJECTED
: {
406 dbus::ErrorResponse::FromMethodCall(
407 method_call
, bluetooth_agent::kErrorRejected
, "rejected")
408 .PassAs
<dbus::Response
>());
411 case Delegate::CANCELLED
: {
413 dbus::ErrorResponse::FromMethodCall(
414 method_call
, bluetooth_agent::kErrorCanceled
, "canceled")
415 .PassAs
<dbus::Response
>());
419 NOTREACHED() << "Unexpected status code from delegate: " << status
;
423 // Called by the Delegate in response to a method requiring confirmation.
424 void OnConfirmation(dbus::MethodCall
* method_call
,
425 dbus::ExportedObject::ResponseSender response_sender
,
426 Delegate::Status status
) {
427 DCHECK(OnOriginThread());
430 case Delegate::SUCCESS
: {
431 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
434 case Delegate::REJECTED
: {
436 dbus::ErrorResponse::FromMethodCall(
437 method_call
, bluetooth_agent::kErrorRejected
, "rejected")
438 .PassAs
<dbus::Response
>());
441 case Delegate::CANCELLED
: {
443 dbus::ErrorResponse::FromMethodCall(
444 method_call
, bluetooth_agent::kErrorCanceled
, "canceled")
445 .PassAs
<dbus::Response
>());
449 NOTREACHED() << "Unexpected status code from delegate: " << status
;
453 // Origin thread (i.e. the UI thread in production).
454 base::PlatformThreadId origin_thread_id_
;
456 // D-Bus bus object is exported on, not owned by this object and must
460 // All incoming method calls are passed on to the Delegate and a callback
461 // passed to generate the reply. |delegate_| is generally the object that
462 // owns this one, and must outlive it.
465 // D-Bus object path of object we are exporting, kept so we can unregister
466 // again in our destructor.
467 dbus::ObjectPath object_path_
;
469 // D-Bus object we are exporting, owned by this object.
470 scoped_refptr
<dbus::ExportedObject
> exported_object_
;
472 // Weak pointer factory for generating 'this' pointers that might live longer
474 // Note: This should remain the last member so it'll be destroyed and
475 // invalidate its weak pointers before any other members are destroyed.
476 base::WeakPtrFactory
<ExperimentalBluetoothAgentServiceProviderImpl
>
479 DISALLOW_COPY_AND_ASSIGN(ExperimentalBluetoothAgentServiceProviderImpl
);
482 ExperimentalBluetoothAgentServiceProvider::
483 ExperimentalBluetoothAgentServiceProvider() {
486 ExperimentalBluetoothAgentServiceProvider::
487 ~ExperimentalBluetoothAgentServiceProvider() {
491 ExperimentalBluetoothAgentServiceProvider
*
492 ExperimentalBluetoothAgentServiceProvider::Create(
494 const dbus::ObjectPath
& object_path
,
495 Delegate
* delegate
) {
496 if (base::chromeos::IsRunningOnChromeOS()) {
497 return new ExperimentalBluetoothAgentServiceProviderImpl(
498 bus
, object_path
, delegate
);
500 return new FakeBluetoothAgentServiceProvider(object_path
, delegate
);
504 } // namespace chromeos