Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / device / bluetooth / bluetooth_device_chromeos.cc
blob62be52a245ca09967012be9cc82886ab48260a70
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 "device/bluetooth/bluetooth_device_chromeos.h"
7 #include <stdio.h>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/histogram.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "chromeos/dbus/bluetooth_adapter_client.h"
15 #include "chromeos/dbus/bluetooth_device_client.h"
16 #include "chromeos/dbus/bluetooth_gatt_service_client.h"
17 #include "chromeos/dbus/bluetooth_input_client.h"
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "dbus/bus.h"
20 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
21 #include "device/bluetooth/bluetooth_gatt_connection_chromeos.h"
22 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
23 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
24 #include "device/bluetooth/bluetooth_socket.h"
25 #include "device/bluetooth/bluetooth_socket_chromeos.h"
26 #include "device/bluetooth/bluetooth_socket_thread.h"
27 #include "device/bluetooth/bluetooth_uuid.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
30 using device::BluetoothDevice;
31 using device::BluetoothSocket;
32 using device::BluetoothUUID;
34 namespace {
36 // Histogram enumerations for pairing results.
37 enum UMAPairingResult {
38 UMA_PAIRING_RESULT_SUCCESS,
39 UMA_PAIRING_RESULT_INPROGRESS,
40 UMA_PAIRING_RESULT_FAILED,
41 UMA_PAIRING_RESULT_AUTH_FAILED,
42 UMA_PAIRING_RESULT_AUTH_CANCELED,
43 UMA_PAIRING_RESULT_AUTH_REJECTED,
44 UMA_PAIRING_RESULT_AUTH_TIMEOUT,
45 UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE,
46 UMA_PAIRING_RESULT_UNKNOWN_ERROR,
47 // NOTE: Add new pairing results immediately above this line. Make sure to
48 // update the enum list in tools/histogram/histograms.xml accordinly.
49 UMA_PAIRING_RESULT_COUNT
52 void ParseModalias(const dbus::ObjectPath& object_path,
53 BluetoothDevice::VendorIDSource* vendor_id_source,
54 uint16* vendor_id,
55 uint16* product_id,
56 uint16* device_id) {
57 chromeos::BluetoothDeviceClient::Properties* properties =
58 chromeos::DBusThreadManager::Get()->GetBluetoothDeviceClient()->
59 GetProperties(object_path);
60 DCHECK(properties);
62 std::string modalias = properties->modalias.value();
63 BluetoothDevice::VendorIDSource source_value;
64 int vendor_value, product_value, device_value;
66 if (sscanf(modalias.c_str(), "bluetooth:v%04xp%04xd%04x",
67 &vendor_value, &product_value, &device_value) == 3) {
68 source_value = BluetoothDevice::VENDOR_ID_BLUETOOTH;
69 } else if (sscanf(modalias.c_str(), "usb:v%04xp%04xd%04x",
70 &vendor_value, &product_value, &device_value) == 3) {
71 source_value = BluetoothDevice::VENDOR_ID_USB;
72 } else {
73 return;
76 if (vendor_id_source != NULL)
77 *vendor_id_source = source_value;
78 if (vendor_id != NULL)
79 *vendor_id = vendor_value;
80 if (product_id != NULL)
81 *product_id = product_value;
82 if (device_id != NULL)
83 *device_id = device_value;
86 void RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code) {
87 UMAPairingResult pairing_result;
88 switch (error_code) {
89 case BluetoothDevice::ERROR_INPROGRESS:
90 pairing_result = UMA_PAIRING_RESULT_INPROGRESS;
91 break;
92 case BluetoothDevice::ERROR_FAILED:
93 pairing_result = UMA_PAIRING_RESULT_FAILED;
94 break;
95 case BluetoothDevice::ERROR_AUTH_FAILED:
96 pairing_result = UMA_PAIRING_RESULT_AUTH_FAILED;
97 break;
98 case BluetoothDevice::ERROR_AUTH_CANCELED:
99 pairing_result = UMA_PAIRING_RESULT_AUTH_CANCELED;
100 break;
101 case BluetoothDevice::ERROR_AUTH_REJECTED:
102 pairing_result = UMA_PAIRING_RESULT_AUTH_REJECTED;
103 break;
104 case BluetoothDevice::ERROR_AUTH_TIMEOUT:
105 pairing_result = UMA_PAIRING_RESULT_AUTH_TIMEOUT;
106 break;
107 case BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
108 pairing_result = UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE;
109 break;
110 default:
111 pairing_result = UMA_PAIRING_RESULT_UNKNOWN_ERROR;
114 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
115 pairing_result,
116 UMA_PAIRING_RESULT_COUNT);
119 } // namespace
121 namespace chromeos {
123 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
124 BluetoothAdapterChromeOS* adapter,
125 const dbus::ObjectPath& object_path,
126 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
127 scoped_refptr<device::BluetoothSocketThread> socket_thread)
128 : BluetoothDevice(adapter),
129 object_path_(object_path),
130 num_connecting_calls_(0),
131 connection_monitor_started_(false),
132 ui_task_runner_(ui_task_runner),
133 socket_thread_(socket_thread),
134 weak_ptr_factory_(this) {
135 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
137 // Add all known GATT services.
138 const std::vector<dbus::ObjectPath> gatt_services =
139 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices();
140 for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin();
141 it != gatt_services.end(); ++it) {
142 GattServiceAdded(*it);
146 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
147 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
148 RemoveObserver(this);
150 // Copy the GATT services list here and clear the original so that when we
151 // send GattServiceRemoved(), GetGattServices() returns no services.
152 GattServiceMap gatt_services = gatt_services_;
153 gatt_services_.clear();
154 for (GattServiceMap::iterator iter = gatt_services.begin();
155 iter != gatt_services.end(); ++iter) {
156 DCHECK(adapter_);
157 adapter()->NotifyGattServiceRemoved(
158 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second));
159 delete iter->second;
163 uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
164 BluetoothDeviceClient::Properties* properties =
165 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
166 GetProperties(object_path_);
167 DCHECK(properties);
169 return properties->bluetooth_class.value();
172 std::string BluetoothDeviceChromeOS::GetDeviceName() const {
173 BluetoothDeviceClient::Properties* properties =
174 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
175 GetProperties(object_path_);
176 DCHECK(properties);
178 return properties->alias.value();
181 void BluetoothDeviceChromeOS::CreateGattConnectionImpl() {
182 // ChromeOS implementation does not use the default CreateGattConnection
183 // implementation.
184 NOTIMPLEMENTED();
187 void BluetoothDeviceChromeOS::DisconnectGatt() {
188 // ChromeOS implementation does not use the default CreateGattConnection
189 // implementation.
190 NOTIMPLEMENTED();
193 std::string BluetoothDeviceChromeOS::GetAddress() const {
194 BluetoothDeviceClient::Properties* properties =
195 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
196 GetProperties(object_path_);
197 DCHECK(properties);
199 return CanonicalizeAddress(properties->address.value());
202 BluetoothDevice::VendorIDSource
203 BluetoothDeviceChromeOS::GetVendorIDSource() const {
204 VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN;
205 ParseModalias(object_path_, &vendor_id_source, NULL, NULL, NULL);
206 return vendor_id_source;
209 uint16 BluetoothDeviceChromeOS::GetVendorID() const {
210 uint16 vendor_id = 0;
211 ParseModalias(object_path_, NULL, &vendor_id, NULL, NULL);
212 return vendor_id;
215 uint16 BluetoothDeviceChromeOS::GetProductID() const {
216 uint16 product_id = 0;
217 ParseModalias(object_path_, NULL, NULL, &product_id, NULL);
218 return product_id;
221 uint16 BluetoothDeviceChromeOS::GetDeviceID() const {
222 uint16 device_id = 0;
223 ParseModalias(object_path_, NULL, NULL, NULL, &device_id);
224 return device_id;
227 bool BluetoothDeviceChromeOS::IsPaired() const {
228 BluetoothDeviceClient::Properties* properties =
229 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
230 GetProperties(object_path_);
231 DCHECK(properties);
233 // Trusted devices are devices that don't support pairing but that the
234 // user has explicitly connected; it makes no sense for UI purposes to
235 // treat them differently from each other.
236 return properties->paired.value() || properties->trusted.value();
239 bool BluetoothDeviceChromeOS::IsConnected() const {
240 BluetoothDeviceClient::Properties* properties =
241 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
242 GetProperties(object_path_);
243 DCHECK(properties);
245 return properties->connected.value();
248 bool BluetoothDeviceChromeOS::IsGattConnected() const {
249 NOTIMPLEMENTED();
250 return false;
253 bool BluetoothDeviceChromeOS::IsConnectable() const {
254 BluetoothInputClient::Properties* input_properties =
255 DBusThreadManager::Get()->GetBluetoothInputClient()->
256 GetProperties(object_path_);
257 // GetProperties returns NULL when the device does not implement the given
258 // interface. Non HID devices are normally connectable.
259 if (!input_properties)
260 return true;
262 return input_properties->reconnect_mode.value() != "device";
265 bool BluetoothDeviceChromeOS::IsConnecting() const {
266 return num_connecting_calls_ > 0;
269 BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const {
270 BluetoothDeviceClient::Properties* properties =
271 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
272 GetProperties(object_path_);
273 DCHECK(properties);
275 std::vector<device::BluetoothUUID> uuids;
276 const std::vector<std::string> &dbus_uuids = properties->uuids.value();
277 for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin();
278 iter != dbus_uuids.end(); ++iter) {
279 device::BluetoothUUID uuid(*iter);
280 DCHECK(uuid.IsValid());
281 uuids.push_back(uuid);
283 return uuids;
286 int16 BluetoothDeviceChromeOS::GetInquiryRSSI() const {
287 BluetoothDeviceClient::Properties* properties =
288 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
289 GetProperties(object_path_);
290 DCHECK(properties);
292 if (!properties->rssi.is_valid())
293 return kUnknownPower;
295 return properties->rssi.value();
298 int16 BluetoothDeviceChromeOS::GetInquiryTxPower() const {
299 BluetoothDeviceClient::Properties* properties =
300 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
301 GetProperties(object_path_);
302 DCHECK(properties);
304 if (!properties->tx_power.is_valid())
305 return kUnknownPower;
307 return properties->tx_power.value();
310 bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
311 return pairing_.get() && pairing_->ExpectingPinCode();
314 bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
315 return pairing_.get() && pairing_->ExpectingPasskey();
318 bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
319 return pairing_.get() && pairing_->ExpectingConfirmation();
322 void BluetoothDeviceChromeOS::GetConnectionInfo(
323 const ConnectionInfoCallback& callback) {
324 // DBus method call should gracefully return an error if the device is not
325 // currently connected.
326 DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetConnInfo(
327 object_path_, base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfo,
328 weak_ptr_factory_.GetWeakPtr(), callback),
329 base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfoError,
330 weak_ptr_factory_.GetWeakPtr(), callback));
333 void BluetoothDeviceChromeOS::Connect(
334 BluetoothDevice::PairingDelegate* pairing_delegate,
335 const base::Closure& callback,
336 const ConnectErrorCallback& error_callback) {
337 if (num_connecting_calls_++ == 0)
338 adapter()->NotifyDeviceChanged(this);
340 VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_
341 << " in progress";
343 if (IsPaired() || !pairing_delegate || !IsPairable()) {
344 // No need to pair, or unable to, skip straight to connection.
345 ConnectInternal(false, callback, error_callback);
346 } else {
347 // Initiate high-security connection with pairing.
348 BeginPairing(pairing_delegate);
350 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
351 Pair(object_path_,
352 base::Bind(&BluetoothDeviceChromeOS::OnPair,
353 weak_ptr_factory_.GetWeakPtr(),
354 callback, error_callback),
355 base::Bind(&BluetoothDeviceChromeOS::OnPairError,
356 weak_ptr_factory_.GetWeakPtr(),
357 error_callback));
361 void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
362 if (!pairing_.get())
363 return;
365 pairing_->SetPinCode(pincode);
368 void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
369 if (!pairing_.get())
370 return;
372 pairing_->SetPasskey(passkey);
375 void BluetoothDeviceChromeOS::ConfirmPairing() {
376 if (!pairing_.get())
377 return;
379 pairing_->ConfirmPairing();
382 void BluetoothDeviceChromeOS::RejectPairing() {
383 if (!pairing_.get())
384 return;
386 pairing_->RejectPairing();
389 void BluetoothDeviceChromeOS::CancelPairing() {
390 bool canceled = false;
392 // If there is a callback in progress that we can reply to then use that
393 // to cancel the current pairing request.
394 if (pairing_.get() && pairing_->CancelPairing())
395 canceled = true;
397 // If not we have to send an explicit CancelPairing() to the device instead.
398 if (!canceled) {
399 VLOG(1) << object_path_.value() << ": No pairing context or callback. "
400 << "Sending explicit cancel";
401 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
402 CancelPairing(
403 object_path_,
404 base::Bind(&base::DoNothing),
405 base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
406 weak_ptr_factory_.GetWeakPtr()));
409 // Since there is no callback to this method it's possible that the pairing
410 // delegate is going to be freed before things complete (indeed it's
411 // documented that this is the method you should call while freeing the
412 // pairing delegate), so clear our the context holding on to it.
413 EndPairing();
416 void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
417 const ErrorCallback& error_callback) {
418 VLOG(1) << object_path_.value() << ": Disconnecting";
419 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
420 Disconnect(
421 object_path_,
422 base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
423 weak_ptr_factory_.GetWeakPtr(),
424 callback),
425 base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
426 weak_ptr_factory_.GetWeakPtr(),
427 error_callback));
430 void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
431 VLOG(1) << object_path_.value() << ": Removing device";
432 DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveDevice(
433 adapter()->object_path(), object_path_, base::Bind(&base::DoNothing),
434 base::Bind(&BluetoothDeviceChromeOS::OnForgetError,
435 weak_ptr_factory_.GetWeakPtr(), error_callback));
438 void BluetoothDeviceChromeOS::ConnectToService(
439 const BluetoothUUID& uuid,
440 const ConnectToServiceCallback& callback,
441 const ConnectToServiceErrorCallback& error_callback) {
442 VLOG(1) << object_path_.value() << ": Connecting to service: "
443 << uuid.canonical_value();
444 scoped_refptr<BluetoothSocketChromeOS> socket =
445 BluetoothSocketChromeOS::CreateBluetoothSocket(
446 ui_task_runner_, socket_thread_);
447 socket->Connect(this, uuid, BluetoothSocketChromeOS::SECURITY_LEVEL_MEDIUM,
448 base::Bind(callback, socket), error_callback);
451 void BluetoothDeviceChromeOS::ConnectToServiceInsecurely(
452 const BluetoothUUID& uuid,
453 const ConnectToServiceCallback& callback,
454 const ConnectToServiceErrorCallback& error_callback) {
455 VLOG(1) << object_path_.value() << ": Connecting insecurely to service: "
456 << uuid.canonical_value();
457 scoped_refptr<BluetoothSocketChromeOS> socket =
458 BluetoothSocketChromeOS::CreateBluetoothSocket(
459 ui_task_runner_, socket_thread_);
460 socket->Connect(this, uuid, BluetoothSocketChromeOS::SECURITY_LEVEL_LOW,
461 base::Bind(callback, socket), error_callback);
464 void BluetoothDeviceChromeOS::CreateGattConnection(
465 const GattConnectionCallback& callback,
466 const ConnectErrorCallback& error_callback) {
467 // TODO(sacomoto): Workaround to retrieve the connection for already connected
468 // devices. Currently, BluetoothGattConnection::Disconnect doesn't do
469 // anything, the unique underlying physical GATT connection is kept. This
470 // should be removed once the correct behavour is implemented and the GATT
471 // connections are reference counted (see todo below).
472 if (IsConnected()) {
473 OnCreateGattConnection(callback);
474 return;
477 // TODO(armansito): Until there is a way to create a reference counted GATT
478 // connection in bluetoothd, simply do a regular connect.
479 Connect(NULL,
480 base::Bind(&BluetoothDeviceChromeOS::OnCreateGattConnection,
481 weak_ptr_factory_.GetWeakPtr(),
482 callback),
483 error_callback);
486 BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing(
487 BluetoothDevice::PairingDelegate* pairing_delegate) {
488 pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate));
489 return pairing_.get();
492 void BluetoothDeviceChromeOS::EndPairing() {
493 pairing_.reset();
496 BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const {
497 return pairing_.get();
500 BluetoothAdapterChromeOS* BluetoothDeviceChromeOS::adapter() const {
501 return static_cast<BluetoothAdapterChromeOS*>(adapter_);
504 void BluetoothDeviceChromeOS::GattServiceAdded(
505 const dbus::ObjectPath& object_path) {
506 if (GetGattService(object_path.value())) {
507 VLOG(1) << "Remote GATT service already exists: " << object_path.value();
508 return;
511 BluetoothGattServiceClient::Properties* properties =
512 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
513 GetProperties(object_path);
514 DCHECK(properties);
515 if (properties->device.value() != object_path_) {
516 VLOG(2) << "Remote GATT service does not belong to this device.";
517 return;
520 VLOG(1) << "Adding new remote GATT service for device: " << GetAddress();
522 BluetoothRemoteGattServiceChromeOS* service =
523 new BluetoothRemoteGattServiceChromeOS(adapter(), this, object_path);
525 gatt_services_[service->GetIdentifier()] = service;
526 DCHECK(service->object_path() == object_path);
527 DCHECK(service->GetUUID().IsValid());
529 DCHECK(adapter_);
530 adapter()->NotifyGattServiceAdded(service);
533 void BluetoothDeviceChromeOS::GattServiceRemoved(
534 const dbus::ObjectPath& object_path) {
535 GattServiceMap::iterator iter = gatt_services_.find(object_path.value());
536 if (iter == gatt_services_.end()) {
537 VLOG(3) << "Unknown GATT service removed: " << object_path.value();
538 return;
541 VLOG(1) << "Removing remote GATT service from device: " << GetAddress();
543 BluetoothRemoteGattServiceChromeOS* service =
544 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second);
545 DCHECK(service->object_path() == object_path);
546 gatt_services_.erase(iter);
548 DCHECK(adapter_);
549 adapter()->NotifyGattServiceRemoved(service);
551 delete service;
554 void BluetoothDeviceChromeOS::OnGetConnInfo(
555 const ConnectionInfoCallback& callback,
556 int16 rssi,
557 int16 transmit_power,
558 int16 max_transmit_power) {
559 callback.Run(ConnectionInfo(rssi, transmit_power, max_transmit_power));
562 void BluetoothDeviceChromeOS::OnGetConnInfoError(
563 const ConnectionInfoCallback& callback,
564 const std::string& error_name,
565 const std::string& error_message) {
566 LOG(WARNING) << object_path_.value()
567 << ": Failed to get connection info: " << error_name << ": "
568 << error_message;
569 callback.Run(ConnectionInfo());
572 void BluetoothDeviceChromeOS::ConnectInternal(
573 bool after_pairing,
574 const base::Closure& callback,
575 const ConnectErrorCallback& error_callback) {
576 VLOG(1) << object_path_.value() << ": Connecting";
577 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
578 Connect(
579 object_path_,
580 base::Bind(&BluetoothDeviceChromeOS::OnConnect,
581 weak_ptr_factory_.GetWeakPtr(),
582 after_pairing,
583 callback),
584 base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
585 weak_ptr_factory_.GetWeakPtr(),
586 after_pairing,
587 error_callback));
590 void BluetoothDeviceChromeOS::OnConnect(bool after_pairing,
591 const base::Closure& callback) {
592 if (--num_connecting_calls_ == 0)
593 adapter()->NotifyDeviceChanged(this);
595 DCHECK(num_connecting_calls_ >= 0);
596 VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_
597 << " still in progress";
599 SetTrusted();
601 if (after_pairing)
602 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
603 UMA_PAIRING_RESULT_SUCCESS,
604 UMA_PAIRING_RESULT_COUNT);
606 callback.Run();
609 void BluetoothDeviceChromeOS::OnCreateGattConnection(
610 const GattConnectionCallback& callback) {
611 scoped_ptr<device::BluetoothGattConnection> conn(
612 new BluetoothGattConnectionChromeOS(
613 adapter_, GetAddress(), object_path_));
614 callback.Run(conn.Pass());
617 void BluetoothDeviceChromeOS::OnConnectError(
618 bool after_pairing,
619 const ConnectErrorCallback& error_callback,
620 const std::string& error_name,
621 const std::string& error_message) {
622 if (--num_connecting_calls_ == 0)
623 adapter()->NotifyDeviceChanged(this);
625 DCHECK(num_connecting_calls_ >= 0);
626 LOG(WARNING) << object_path_.value() << ": Failed to connect device: "
627 << error_name << ": " << error_message;
628 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
629 << " still in progress";
631 // Determine the error code from error_name.
632 ConnectErrorCode error_code = ERROR_UNKNOWN;
633 if (error_name == bluetooth_device::kErrorFailed) {
634 error_code = ERROR_FAILED;
635 } else if (error_name == bluetooth_device::kErrorInProgress) {
636 error_code = ERROR_INPROGRESS;
637 } else if (error_name == bluetooth_device::kErrorNotSupported) {
638 error_code = ERROR_UNSUPPORTED_DEVICE;
641 if (after_pairing)
642 RecordPairingResult(error_code);
643 error_callback.Run(error_code);
646 void BluetoothDeviceChromeOS::OnPair(
647 const base::Closure& callback,
648 const ConnectErrorCallback& error_callback) {
649 VLOG(1) << object_path_.value() << ": Paired";
651 EndPairing();
653 ConnectInternal(true, callback, error_callback);
656 void BluetoothDeviceChromeOS::OnPairError(
657 const ConnectErrorCallback& error_callback,
658 const std::string& error_name,
659 const std::string& error_message) {
660 if (--num_connecting_calls_ == 0)
661 adapter()->NotifyDeviceChanged(this);
663 DCHECK(num_connecting_calls_ >= 0);
664 LOG(WARNING) << object_path_.value() << ": Failed to pair device: "
665 << error_name << ": " << error_message;
666 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
667 << " still in progress";
669 EndPairing();
671 // Determine the error code from error_name.
672 ConnectErrorCode error_code = ERROR_UNKNOWN;
673 if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
674 error_code = ERROR_FAILED;
675 } else if (error_name == bluetooth_device::kErrorFailed) {
676 error_code = ERROR_FAILED;
677 } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
678 error_code = ERROR_AUTH_FAILED;
679 } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
680 error_code = ERROR_AUTH_CANCELED;
681 } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
682 error_code = ERROR_AUTH_REJECTED;
683 } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
684 error_code = ERROR_AUTH_TIMEOUT;
687 RecordPairingResult(error_code);
688 error_callback.Run(error_code);
691 void BluetoothDeviceChromeOS::OnCancelPairingError(
692 const std::string& error_name,
693 const std::string& error_message) {
694 LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: "
695 << error_name << ": " << error_message;
698 void BluetoothDeviceChromeOS::SetTrusted() {
699 // Unconditionally send the property change, rather than checking the value
700 // first; there's no harm in doing this and it solves any race conditions
701 // with the property becoming true or false and this call happening before
702 // we get the D-Bus signal about the earlier change.
703 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
704 GetProperties(object_path_)->trusted.Set(
705 true,
706 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
707 weak_ptr_factory_.GetWeakPtr()));
710 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
711 LOG_IF(WARNING, !success) << object_path_.value()
712 << ": Failed to set device as trusted";
715 void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) {
716 VLOG(1) << object_path_.value() << ": Disconnected";
717 callback.Run();
720 void BluetoothDeviceChromeOS::OnDisconnectError(
721 const ErrorCallback& error_callback,
722 const std::string& error_name,
723 const std::string& error_message) {
724 LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: "
725 << error_name << ": " << error_message;
726 error_callback.Run();
729 void BluetoothDeviceChromeOS::OnForgetError(
730 const ErrorCallback& error_callback,
731 const std::string& error_name,
732 const std::string& error_message) {
733 LOG(WARNING) << object_path_.value() << ": Failed to remove device: "
734 << error_name << ": " << error_message;
735 error_callback.Run();
738 } // namespace chromeos