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.
5 #include "device/bluetooth/bluetooth_device_chromeos.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/string16.h"
17 #include "base/string_util.h"
18 #include "base/values.h"
19 #include "chromeos/dbus/bluetooth_adapter_client.h"
20 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
21 #include "chromeos/dbus/bluetooth_device_client.h"
22 #include "chromeos/dbus/bluetooth_input_client.h"
23 #include "chromeos/dbus/bluetooth_out_of_band_client.h"
24 #include "chromeos/dbus/dbus_thread_manager.h"
25 #include "chromeos/dbus/introspectable_client.h"
27 #include "dbus/object_path.h"
28 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
29 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
30 #include "device/bluetooth/bluetooth_service_record.h"
31 #include "device/bluetooth/bluetooth_service_record_chromeos.h"
32 #include "device/bluetooth/bluetooth_socket_chromeos.h"
33 #include "device/bluetooth/bluetooth_utils.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
36 using device::BluetoothDevice
;
37 using device::BluetoothOutOfBandPairingData
;
38 using device::BluetoothServiceRecord
;
39 using device::BluetoothSocket
;
43 void DoNothingServiceRecordList(const BluetoothDevice::ServiceRecordList
&) {}
49 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
50 BluetoothAdapterChromeOS
* adapter
)
58 pairing_delegate_(NULL
),
59 connecting_applications_counter_(0),
61 service_records_loaded_(false),
62 weak_ptr_factory_(this) {
65 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
68 uint32
BluetoothDeviceChromeOS::GetBluetoothClass() const {
69 return bluetooth_class_
;
72 std::string
BluetoothDeviceChromeOS::GetDeviceName() const {
76 std::string
BluetoothDeviceChromeOS::GetAddress() const {
80 bool BluetoothDeviceChromeOS::IsPaired() const {
84 bool BluetoothDeviceChromeOS::IsConnected() const {
88 bool BluetoothDeviceChromeOS::IsConnectable() const {
92 bool BluetoothDeviceChromeOS::IsConnecting() const {
96 BluetoothDeviceChromeOS::ServiceList
97 BluetoothDeviceChromeOS::GetServices() const {
98 return service_uuids_
;
101 void BluetoothDeviceChromeOS::GetServiceRecords(
102 const ServiceRecordsCallback
& callback
,
103 const ErrorCallback
& error_callback
) {
104 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
107 "", // empty pattern to browse all services
108 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback
,
109 weak_ptr_factory_
.GetWeakPtr(),
112 &BluetoothDeviceChromeOS::OnGetServiceRecordsError
,
113 weak_ptr_factory_
.GetWeakPtr(),
118 void BluetoothDeviceChromeOS::ProvidesServiceWithName(
119 const std::string
& name
,
120 const ProvidesServiceCallback
& callback
) {
122 base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameCallback
,
123 weak_ptr_factory_
.GetWeakPtr(),
126 base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback
,
127 weak_ptr_factory_
.GetWeakPtr(),
131 bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
132 return !pincode_callback_
.is_null();
135 bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
136 return !passkey_callback_
.is_null();
139 bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
140 return !confirmation_callback_
.is_null();
143 void BluetoothDeviceChromeOS::Connect(
144 PairingDelegate
* pairing_delegate
,
145 const base::Closure
& callback
,
146 const ConnectErrorCallback
& error_callback
) {
147 // This is safe because Connect() and its callbacks are called in the same
150 connecting_
= !!connecting_calls_
;
151 // Set the decrement to be issued when either callback is called.
152 base::Closure wrapped_callback
= base::Bind(
153 &BluetoothDeviceChromeOS::OnConnectCallbackCalled
,
154 weak_ptr_factory_
.GetWeakPtr(),
156 ConnectErrorCallback wrapped_error_callback
= base::Bind(
157 &BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled
,
158 weak_ptr_factory_
.GetWeakPtr(),
161 if (IsPaired() || IsConnected()) {
162 // Connection to already paired or connected device.
163 ConnectApplications(wrapped_callback
, wrapped_error_callback
);
165 } else if (!pairing_delegate
) {
166 // No pairing delegate supplied, initiate low-security connection only.
167 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
168 CreateDevice(adapter_
->object_path_
,
170 base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice
,
171 weak_ptr_factory_
.GetWeakPtr(),
173 wrapped_error_callback
),
174 base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError
,
175 weak_ptr_factory_
.GetWeakPtr(),
176 wrapped_error_callback
));
178 // Initiate high-security connection with pairing.
179 DCHECK(!pairing_delegate_
);
180 pairing_delegate_
= pairing_delegate
;
182 // The agent path is relatively meaningless, we use the device address
183 // to generate it as we only support one pairing attempt at a time for
184 // a given bluetooth device.
185 DCHECK(agent_
.get() == NULL
);
187 std::string agent_path_basename
;
188 ReplaceChars(address_
, ":", "_", &agent_path_basename
);
189 dbus::ObjectPath
agent_path("/org/chromium/bluetooth_agent/" +
190 agent_path_basename
);
192 dbus::Bus
* system_bus
= DBusThreadManager::Get()->GetSystemBus();
194 agent_
.reset(BluetoothAgentServiceProvider::Create(system_bus
,
201 VLOG(1) << "Pairing: " << address_
;
202 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
204 adapter_
->object_path_
,
207 bluetooth_agent::kDisplayYesNoCapability
,
208 base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice
,
209 weak_ptr_factory_
.GetWeakPtr(),
211 wrapped_error_callback
),
212 base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError
,
213 weak_ptr_factory_
.GetWeakPtr(),
214 wrapped_error_callback
));
218 void BluetoothDeviceChromeOS::SetPinCode(const std::string
& pincode
) {
219 if (!agent_
.get() || pincode_callback_
.is_null())
222 pincode_callback_
.Run(SUCCESS
, pincode
);
223 pincode_callback_
.Reset();
226 void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey
) {
227 if (!agent_
.get() || passkey_callback_
.is_null())
230 passkey_callback_
.Run(SUCCESS
, passkey
);
231 passkey_callback_
.Reset();
234 void BluetoothDeviceChromeOS::ConfirmPairing() {
235 if (!agent_
.get() || confirmation_callback_
.is_null())
238 confirmation_callback_
.Run(SUCCESS
);
239 confirmation_callback_
.Reset();
242 void BluetoothDeviceChromeOS::RejectPairing() {
246 if (!pincode_callback_
.is_null()) {
247 pincode_callback_
.Run(REJECTED
, "");
248 pincode_callback_
.Reset();
250 if (!passkey_callback_
.is_null()) {
251 passkey_callback_
.Run(REJECTED
, 0);
252 passkey_callback_
.Reset();
254 if (!confirmation_callback_
.is_null()) {
255 confirmation_callback_
.Run(REJECTED
);
256 confirmation_callback_
.Reset();
260 void BluetoothDeviceChromeOS::CancelPairing() {
261 bool have_callback
= false;
263 if (!pincode_callback_
.is_null()) {
264 pincode_callback_
.Run(CANCELLED
, "");
265 pincode_callback_
.Reset();
266 have_callback
= true;
268 if (!passkey_callback_
.is_null()) {
269 passkey_callback_
.Run(CANCELLED
, 0);
270 passkey_callback_
.Reset();
271 have_callback
= true;
273 if (!confirmation_callback_
.is_null()) {
274 confirmation_callback_
.Run(CANCELLED
);
275 confirmation_callback_
.Reset();
276 have_callback
= true;
280 if (!have_callback
) {
281 // User cancels the pairing process.
282 DBusThreadManager::Get()->GetBluetoothAdapterClient()->CancelDeviceCreation(
283 adapter_
->object_path_
,
285 base::Bind(&BluetoothDeviceChromeOS::OnCancelDeviceCreation
,
286 weak_ptr_factory_
.GetWeakPtr()));
288 pairing_delegate_
= NULL
;
293 void BluetoothDeviceChromeOS::Disconnect(const base::Closure
& callback
,
294 const ErrorCallback
& error_callback
) {
295 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
296 Disconnect(object_path_
,
297 base::Bind(&BluetoothDeviceChromeOS::DisconnectCallback
,
298 weak_ptr_factory_
.GetWeakPtr(),
304 void BluetoothDeviceChromeOS::Forget(const ErrorCallback
& error_callback
) {
305 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
306 RemoveDevice(adapter_
->object_path_
,
308 base::Bind(&BluetoothDeviceChromeOS::ForgetCallback
,
309 weak_ptr_factory_
.GetWeakPtr(),
313 void BluetoothDeviceChromeOS::ConnectToService(const std::string
& service_uuid
,
314 const SocketCallback
& callback
) {
316 base::Bind(&BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback
,
317 weak_ptr_factory_
.GetWeakPtr(),
321 &BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback
,
322 weak_ptr_factory_
.GetWeakPtr(),
326 void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
327 const BluetoothOutOfBandPairingData
& data
,
328 const base::Closure
& callback
,
329 const ErrorCallback
& error_callback
) {
330 DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
335 base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback
,
336 weak_ptr_factory_
.GetWeakPtr(),
341 void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
342 const base::Closure
& callback
,
343 const ErrorCallback
& error_callback
) {
344 DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
348 base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback
,
349 weak_ptr_factory_
.GetWeakPtr(),
354 void BluetoothDeviceChromeOS::SetObjectPath(
355 const dbus::ObjectPath
& object_path
) {
356 DCHECK(object_path_
== dbus::ObjectPath(""));
357 object_path_
= object_path
;
360 void BluetoothDeviceChromeOS::RemoveObjectPath() {
361 DCHECK(object_path_
!= dbus::ObjectPath(""));
362 object_path_
= dbus::ObjectPath("");
365 void BluetoothDeviceChromeOS::Update(
366 const BluetoothDeviceClient::Properties
* properties
,
368 std::string address
= properties
->address
.value();
369 std::string name
= properties
->name
.value();
370 uint32 bluetooth_class
= properties
->bluetooth_class
.value();
371 const std::vector
<std::string
>& uuids
= properties
->uuids
.value();
373 if (!address
.empty())
378 bluetooth_class_
= bluetooth_class
;
379 if (!uuids
.empty()) {
380 service_uuids_
.clear();
381 service_uuids_
.assign(uuids
.begin(), uuids
.end());
385 // When the device reconnects and we don't have any service records for it,
386 // try to update the cache or fail silently.
387 if (!service_records_loaded_
&& !connected_
&&
388 properties
->connected
.value())
389 GetServiceRecords(base::Bind(&DoNothingServiceRecordList
),
390 base::Bind(&base::DoNothing
));
392 paired_
= properties
->paired
.value();
393 connected_
= properties
->connected
.value();
397 void BluetoothDeviceChromeOS::OnCreateDevice(
398 const base::Closure
& callback
,
399 const ConnectErrorCallback
& error_callback
,
400 const dbus::ObjectPath
& device_path
) {
401 VLOG(1) << "Connection successful: " << device_path
.value();
402 if (object_path_
.value().empty()) {
403 object_path_
= device_path
;
405 LOG_IF(WARNING
, object_path_
!= device_path
)
406 << "Conflicting device paths for objects, result gave: "
407 << device_path
.value() << " but signal gave: "
408 << object_path_
.value();
411 // Mark the device trusted so it can connect to us automatically, and
412 // we can connect after rebooting. This information is part of the
413 // pairing information of the device, and is unique to the combination
414 // of our bluetooth address and the device's bluetooth address. A
415 // different host needs a new pairing, so it's not useful to sync.
416 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
417 GetProperties(object_path_
)->trusted
.Set(
419 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted
,
420 weak_ptr_factory_
.GetWeakPtr()));
422 // In parallel with the |trusted| property change, call GetServiceRecords to
423 // retrieve the SDP from the device and then, either on success or failure,
424 // call ConnectApplications.
426 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords
,
427 weak_ptr_factory_
.GetWeakPtr(),
430 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError
,
431 weak_ptr_factory_
.GetWeakPtr(),
436 void BluetoothDeviceChromeOS::OnCreateDeviceError(
437 const ConnectErrorCallback
& error_callback
,
438 const std::string
& error_name
,
439 const std::string
& error_message
) {
440 // The default |error_code| is an unknown error.
441 ConnectErrorCode error_code
= ERROR_UNKNOWN
;
443 // Report any error in the log, even if we know the possible source of it.
444 LOG(WARNING
) << "Connection failed (on CreatePairedDevice): "
445 << "\"" << name_
<< "\" (" << address_
<< "): "
446 << error_name
<< ": \"" << error_message
<< "\"";
448 // Determines the right error code from error_name, assuming the error name
449 // comes from CreatePairedDevice bluez function.
450 if (error_name
== bluetooth_adapter::kErrorConnectionAttemptFailed
) {
451 error_code
= ERROR_FAILED
;
452 } else if (error_name
== bluetooth_adapter::kErrorAuthenticationFailed
) {
453 error_code
= ERROR_AUTH_FAILED
;
454 } else if (error_name
== bluetooth_adapter::kErrorAuthenticationRejected
) {
455 error_code
= ERROR_AUTH_REJECTED
;
456 } else if (error_name
== bluetooth_adapter::kErrorAuthenticationTimeout
) {
457 error_code
= ERROR_AUTH_TIMEOUT
;
459 error_callback
.Run(error_code
);
462 void BluetoothDeviceChromeOS::CollectServiceRecordsCallback(
463 const ServiceRecordsCallback
& callback
,
464 const ErrorCallback
& error_callback
,
465 const dbus::ObjectPath
& device_path
,
466 const BluetoothDeviceClient::ServiceMap
& service_map
,
469 error_callback
.Run();
473 // Update the cache. No other thread is executing a GetServiceRecords
474 // callback, so it is safe to delete the previous objects here.
475 service_records_
.clear();
476 // TODO(deymo): Perhaps don't update the cache if the new SDP information is
477 // empty and we had something before. Some devices only answer this
478 // information while paired, and this callback could be called in any order if
479 // several calls to GetServiceRecords are made while initial pairing with the
480 // device. This requires more investigation.
481 for (BluetoothDeviceClient::ServiceMap::const_iterator i
=
482 service_map
.begin(); i
!= service_map
.end(); ++i
) {
483 service_records_
.push_back(
484 new BluetoothServiceRecordChromeOS(address_
, i
->second
));
486 service_records_loaded_
= true;
488 callback
.Run(service_records_
);
491 void BluetoothDeviceChromeOS::OnSetTrusted(bool success
) {
492 LOG_IF(WARNING
, !success
) << "Failed to set device as trusted: " << address_
;
495 void BluetoothDeviceChromeOS::OnInitialGetServiceRecords(
496 const base::Closure
& callback
,
497 const ConnectErrorCallback
& error_callback
,
498 const ServiceRecordList
& list
) {
499 // Connect application-layer protocols.
500 ConnectApplications(callback
, error_callback
);
503 void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError(
504 const base::Closure
& callback
,
505 const ConnectErrorCallback
& error_callback
) {
506 // Ignore the error retrieving the service records and continue.
507 LOG(WARNING
) << "Error retrieving SDP for " << address_
<< " after pairing.";
508 // Connect application-layer protocols.
509 ConnectApplications(callback
, error_callback
);
512 void BluetoothDeviceChromeOS::OnGetServiceRecordsError(
513 const ServiceRecordsCallback
& callback
,
514 const ErrorCallback
& error_callback
) {
515 if (service_records_loaded_
) {
516 callback
.Run(service_records_
);
518 error_callback
.Run();
522 void BluetoothDeviceChromeOS::OnConnectCallbackCalled(
523 const base::Closure
& callback
) {
524 // Update the connecting status.
526 connecting_
= !!connecting_calls_
;
530 void BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled(
531 const ConnectErrorCallback
& error_callback
,
532 enum ConnectErrorCode error_code
) {
533 // Update the connecting status.
535 connecting_
= !!connecting_calls_
;
536 error_callback
.Run(error_code
);
539 void BluetoothDeviceChromeOS::ConnectApplications(
540 const base::Closure
& callback
,
541 const ConnectErrorCallback
& error_callback
) {
542 // Introspect the device object to determine supported applications.
543 DBusThreadManager::Get()->GetIntrospectableClient()->
544 Introspect(bluetooth_device::kBluetoothDeviceServiceName
,
546 base::Bind(&BluetoothDeviceChromeOS::OnIntrospect
,
547 weak_ptr_factory_
.GetWeakPtr(),
552 void BluetoothDeviceChromeOS::OnIntrospect(
553 const base::Closure
& callback
,
554 const ConnectErrorCallback
& error_callback
,
555 const std::string
& service_name
,
556 const dbus::ObjectPath
& device_path
,
557 const std::string
& xml_data
,
560 LOG(WARNING
) << "Failed to determine supported applications: " << address_
;
561 error_callback
.Run(ERROR_UNKNOWN
);
565 // The introspection data for the device object may list one or more
566 // additional D-Bus interfaces that BlueZ supports for this particular
567 // device. Send appropraite Connect calls for each of those interfaces
568 // to connect all of the application protocols for this device.
569 std::vector
<std::string
> interfaces
=
570 IntrospectableClient::GetInterfacesFromIntrospectResult(xml_data
);
572 DCHECK_EQ(0, connecting_applications_counter_
);
573 connecting_applications_counter_
= 0;
574 for (std::vector
<std::string
>::iterator iter
= interfaces
.begin();
575 iter
!= interfaces
.end(); ++iter
) {
576 if (*iter
== bluetooth_input::kBluetoothInputInterface
) {
577 connecting_applications_counter_
++;
578 // Supports Input interface.
579 DBusThreadManager::Get()->GetBluetoothInputClient()->
580 Connect(object_path_
,
581 base::Bind(&BluetoothDeviceChromeOS::OnConnect
,
582 weak_ptr_factory_
.GetWeakPtr(),
585 base::Bind(&BluetoothDeviceChromeOS::OnConnectError
,
586 weak_ptr_factory_
.GetWeakPtr(),
587 error_callback
, *iter
));
591 // If OnConnect has been called for every call to Connect above, then this
592 // will decrement the counter to -1. In that case, call the callback
593 // directly as it has not been called by any of the OnConnect callbacks.
594 // This is safe because OnIntrospect and OnConnect run on the same thread.
595 connecting_applications_counter_
--;
596 if (connecting_applications_counter_
== -1)
600 void BluetoothDeviceChromeOS::OnConnect(const base::Closure
& callback
,
601 const std::string
& interface_name
,
602 const dbus::ObjectPath
& device_path
) {
603 VLOG(1) << "Application connection successful: " << device_path
.value()
604 << ": " << interface_name
;
606 connecting_applications_counter_
--;
607 // |callback| should only be called once, meaning it cannot be called before
608 // all requests have been started. The extra decrement after all requests
609 // have been started, and the check for -1 instead of 0 below, insure only a
610 // single call to |callback| will occur (provided OnConnect and OnIntrospect
611 // run on the same thread, which is true).
612 if (connecting_applications_counter_
== -1) {
613 connecting_applications_counter_
= 0;
618 void BluetoothDeviceChromeOS::OnConnectError(
619 const ConnectErrorCallback
& error_callback
,
620 const std::string
& interface_name
,
621 const dbus::ObjectPath
& device_path
,
622 const std::string
& error_name
,
623 const std::string
& error_message
) {
624 // The default |error_code| is an unknown error.
625 ConnectErrorCode error_code
= ERROR_UNKNOWN
;
627 // Report any error in the log, even if we know the possible source of it.
628 LOG(WARNING
) << "Connection failed (on Connect): "
629 << interface_name
<< ": "
630 << "\"" << name_
<< "\" (" << address_
<< "): "
631 << error_name
<< ": \"" << error_message
<< "\"";
633 // Determines the right error code from error_name, assuming the error name
634 // comes from Connect bluez function.
635 if (error_name
== bluetooth_adapter::kErrorFailed
) {
636 error_code
= ERROR_FAILED
;
637 } else if (error_name
== bluetooth_adapter::kErrorInProgress
) {
638 error_code
= ERROR_INPROGRESS
;
639 } else if (error_name
== bluetooth_adapter::kErrorNotSupported
) {
640 error_code
= ERROR_UNSUPPORTED_DEVICE
;
643 error_callback
.Run(error_code
);
646 void BluetoothDeviceChromeOS::DisconnectCallback(
647 const base::Closure
& callback
,
648 const ErrorCallback
& error_callback
,
649 const dbus::ObjectPath
& device_path
,
651 DCHECK(device_path
== object_path_
);
653 VLOG(1) << "Disconnection successful: " << address_
;
657 LOG(WARNING
) << "Disconnection failed: " << address_
;
658 error_callback
.Run();
660 VLOG(1) << "Disconnection failed on a already disconnected device: "
667 void BluetoothDeviceChromeOS::ForgetCallback(
668 const ErrorCallback
& error_callback
,
669 const dbus::ObjectPath
& adapter_path
,
671 // It's quite normal that this path never gets called on success; we use a
672 // weak pointer, and bluetoothd might send the DeviceRemoved signal before
673 // the method reply, in which case this object is deleted and the
674 // callback never takes place. Therefore don't do anything here for the
677 LOG(WARNING
) << "Forget failed: " << address_
;
678 error_callback
.Run();
682 void BluetoothDeviceChromeOS::OnCancelDeviceCreation(
683 const dbus::ObjectPath
& adapter_path
,
686 LOG(WARNING
) << "CancelDeviceCreation failed: " << address_
;
689 void BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback(
690 const ProvidesServiceCallback
& callback
) {
694 void BluetoothDeviceChromeOS::SearchServicesForNameCallback(
695 const std::string
& name
,
696 const ProvidesServiceCallback
& callback
,
697 const ServiceRecordList
& list
) {
698 for (ServiceRecordList::const_iterator i
= list
.begin();
699 i
!= list
.end(); ++i
) {
700 if ((*i
)->name() == name
) {
708 void BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback(
709 const SocketCallback
& callback
) {
713 void BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback(
714 const std::string
& service_uuid
,
715 const SocketCallback
& callback
,
716 const ServiceRecordList
& list
) {
717 for (ServiceRecordList::const_iterator i
= list
.begin();
718 i
!= list
.end(); ++i
) {
719 if ((*i
)->uuid() == service_uuid
) {
720 // If multiple service records are found, use the first one that works.
721 scoped_refptr
<BluetoothSocket
> socket(
722 BluetoothSocketChromeOS::CreateBluetoothSocket(**i
));
723 if (socket
.get() != NULL
) {
724 callback
.Run(socket
);
732 void BluetoothDeviceChromeOS::OnRemoteDataCallback(
733 const base::Closure
& callback
,
734 const ErrorCallback
& error_callback
,
739 error_callback
.Run();
742 void BluetoothDeviceChromeOS::DisconnectRequested(
743 const dbus::ObjectPath
& object_path
) {
744 DCHECK(object_path
== object_path_
);
747 void BluetoothDeviceChromeOS::Release() {
748 DCHECK(agent_
.get());
749 VLOG(1) << "Release: " << address_
;
751 DCHECK(pairing_delegate_
);
752 pairing_delegate_
->DismissDisplayOrConfirm();
753 pairing_delegate_
= NULL
;
755 pincode_callback_
.Reset();
756 passkey_callback_
.Reset();
757 confirmation_callback_
.Reset();
762 void BluetoothDeviceChromeOS::RequestPinCode(
763 const dbus::ObjectPath
& device_path
,
764 const PinCodeCallback
& callback
) {
765 DCHECK(agent_
.get());
766 VLOG(1) << "RequestPinCode: " << device_path
.value();
768 DCHECK(pairing_delegate_
);
769 DCHECK(pincode_callback_
.is_null());
770 pincode_callback_
= callback
;
771 pairing_delegate_
->RequestPinCode(this);
774 void BluetoothDeviceChromeOS::RequestPasskey(
775 const dbus::ObjectPath
& device_path
,
776 const PasskeyCallback
& callback
) {
777 DCHECK(agent_
.get());
778 DCHECK(device_path
== object_path_
);
779 VLOG(1) << "RequestPasskey: " << device_path
.value();
781 DCHECK(pairing_delegate_
);
782 DCHECK(passkey_callback_
.is_null());
783 passkey_callback_
= callback
;
784 pairing_delegate_
->RequestPasskey(this);
787 void BluetoothDeviceChromeOS::DisplayPinCode(
788 const dbus::ObjectPath
& device_path
,
789 const std::string
& pincode
) {
790 DCHECK(agent_
.get());
791 DCHECK(device_path
== object_path_
);
792 VLOG(1) << "DisplayPinCode: " << device_path
.value() << " " << pincode
;
794 DCHECK(pairing_delegate_
);
795 pairing_delegate_
->DisplayPinCode(this, pincode
);
798 void BluetoothDeviceChromeOS::DisplayPasskey(
799 const dbus::ObjectPath
& device_path
,
801 DCHECK(agent_
.get());
802 DCHECK(device_path
== object_path_
);
803 VLOG(1) << "DisplayPasskey: " << device_path
.value() << " " << passkey
;
805 DCHECK(pairing_delegate_
);
806 pairing_delegate_
->DisplayPasskey(this, passkey
);
809 void BluetoothDeviceChromeOS::RequestConfirmation(
810 const dbus::ObjectPath
& device_path
,
812 const ConfirmationCallback
& callback
) {
813 DCHECK(agent_
.get());
814 DCHECK(device_path
== object_path_
);
815 VLOG(1) << "RequestConfirmation: " << device_path
.value() << " " << passkey
;
817 DCHECK(pairing_delegate_
);
818 DCHECK(confirmation_callback_
.is_null());
819 confirmation_callback_
= callback
;
820 pairing_delegate_
->ConfirmPasskey(this, passkey
);
823 void BluetoothDeviceChromeOS::Authorize(const dbus::ObjectPath
& device_path
,
824 const std::string
& uuid
,
825 const ConfirmationCallback
& callback
) {
826 DCHECK(agent_
.get());
827 DCHECK(device_path
== object_path_
);
828 LOG(WARNING
) << "Rejected authorization for service: " << uuid
829 << " requested from device: " << device_path
.value();
830 callback
.Run(REJECTED
);
833 void BluetoothDeviceChromeOS::ConfirmModeChange(
835 const ConfirmationCallback
& callback
) {
836 DCHECK(agent_
.get());
837 LOG(WARNING
) << "Rejected adapter-level mode change: " << mode
838 << " made on agent for device: " << address_
;
839 callback
.Run(REJECTED
);
842 void BluetoothDeviceChromeOS::Cancel() {
843 DCHECK(agent_
.get());
844 VLOG(1) << "Cancel: " << address_
;
846 DCHECK(pairing_delegate_
);
847 pairing_delegate_
->DismissDisplayOrConfirm();
852 BluetoothDeviceChromeOS
* BluetoothDeviceChromeOS::Create(
853 BluetoothAdapterChromeOS
* adapter
) {
854 return new BluetoothDeviceChromeOS(adapter
);
857 } // namespace chromeos