bluetooth_device_chromeos.cc revision 010d83a9304c5a91596085d917d248abff47903a
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 "device/bluetooth/bluetooth_device_chromeos.h" 6 7#include <stdio.h> 8 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_pairing_chromeos.h" 22#include "device/bluetooth/bluetooth_profile_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" 29 30using device::BluetoothDevice; 31using device::BluetoothSocket; 32using device::BluetoothUUID; 33 34namespace { 35 36// Histogram enumerations for pairing results. 37enum 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 50}; 51 52void 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); 61 62 std::string modalias = properties->modalias.value(); 63 BluetoothDevice::VendorIDSource source_value; 64 int vendor_value, product_value, device_value; 65 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; 74 } 75 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; 84} 85 86void 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; 112 } 113 114 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult", 115 pairing_result, 116 UMA_PAIRING_RESULT_COUNT); 117} 118 119} // namespace 120 121namespace chromeos { 122 123BluetoothDeviceChromeOS::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 : adapter_(adapter), 129 object_path_(object_path), 130 num_connecting_calls_(0), 131 ui_task_runner_(ui_task_runner), 132 socket_thread_(socket_thread), 133 weak_ptr_factory_(this) { 134 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); 135 136 // Add all known GATT services. 137 const std::vector<dbus::ObjectPath> gatt_services = 138 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices(); 139 for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin(); 140 it != gatt_services.end(); ++it) { 141 GattServiceAdded(*it); 142 } 143} 144 145BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { 146 DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 147 RemoveObserver(this); 148 149 // Copy the GATT services list here and clear the original so that when we 150 // send GattServiceRemoved(), GetGattServices() returns no services. 151 GattServiceMap gatt_services = gatt_services_; 152 gatt_services_.clear(); 153 for (GattServiceMap::iterator iter = gatt_services.begin(); 154 iter != gatt_services.end(); ++iter) { 155 FOR_EACH_OBSERVER(BluetoothDevice::Observer, observers_, 156 GattServiceRemoved(this, iter->second)); 157 delete iter->second; 158 } 159} 160 161void BluetoothDeviceChromeOS::AddObserver( 162 device::BluetoothDevice::Observer* observer) { 163 DCHECK(observer); 164 observers_.AddObserver(observer); 165} 166 167void BluetoothDeviceChromeOS::RemoveObserver( 168 device::BluetoothDevice::Observer* observer) { 169 DCHECK(observer); 170 observers_.RemoveObserver(observer); 171} 172 173uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const { 174 BluetoothDeviceClient::Properties* properties = 175 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 176 GetProperties(object_path_); 177 DCHECK(properties); 178 179 return properties->bluetooth_class.value(); 180} 181 182std::string BluetoothDeviceChromeOS::GetDeviceName() const { 183 BluetoothDeviceClient::Properties* properties = 184 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 185 GetProperties(object_path_); 186 DCHECK(properties); 187 188 return properties->alias.value(); 189} 190 191std::string BluetoothDeviceChromeOS::GetAddress() const { 192 BluetoothDeviceClient::Properties* properties = 193 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 194 GetProperties(object_path_); 195 DCHECK(properties); 196 197 return properties->address.value(); 198} 199 200BluetoothDevice::VendorIDSource 201BluetoothDeviceChromeOS::GetVendorIDSource() const { 202 VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN; 203 ParseModalias(object_path_, &vendor_id_source, NULL, NULL, NULL); 204 return vendor_id_source; 205} 206 207uint16 BluetoothDeviceChromeOS::GetVendorID() const { 208 uint16 vendor_id = 0; 209 ParseModalias(object_path_, NULL, &vendor_id, NULL, NULL); 210 return vendor_id; 211} 212 213uint16 BluetoothDeviceChromeOS::GetProductID() const { 214 uint16 product_id = 0; 215 ParseModalias(object_path_, NULL, NULL, &product_id, NULL); 216 return product_id; 217} 218 219uint16 BluetoothDeviceChromeOS::GetDeviceID() const { 220 uint16 device_id = 0; 221 ParseModalias(object_path_, NULL, NULL, NULL, &device_id); 222 return device_id; 223} 224 225int BluetoothDeviceChromeOS::GetRSSI() const { 226 NOTIMPLEMENTED(); 227 return kUnknownPower; 228} 229 230int BluetoothDeviceChromeOS::GetCurrentHostTransmitPower() const { 231 NOTIMPLEMENTED(); 232 return kUnknownPower; 233} 234 235int BluetoothDeviceChromeOS::GetMaximumHostTransmitPower() const { 236 NOTIMPLEMENTED(); 237 return kUnknownPower; 238} 239 240bool BluetoothDeviceChromeOS::IsPaired() const { 241 BluetoothDeviceClient::Properties* properties = 242 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 243 GetProperties(object_path_); 244 DCHECK(properties); 245 246 // Trusted devices are devices that don't support pairing but that the 247 // user has explicitly connected; it makes no sense for UI purposes to 248 // treat them differently from each other. 249 return properties->paired.value() || properties->trusted.value(); 250} 251 252bool BluetoothDeviceChromeOS::IsConnected() const { 253 BluetoothDeviceClient::Properties* properties = 254 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 255 GetProperties(object_path_); 256 DCHECK(properties); 257 258 return properties->connected.value(); 259} 260 261bool BluetoothDeviceChromeOS::IsConnectable() const { 262 BluetoothInputClient::Properties* input_properties = 263 DBusThreadManager::Get()->GetBluetoothInputClient()-> 264 GetProperties(object_path_); 265 // GetProperties returns NULL when the device does not implement the given 266 // interface. Non HID devices are normally connectable. 267 if (!input_properties) 268 return true; 269 270 return input_properties->reconnect_mode.value() != "device"; 271} 272 273bool BluetoothDeviceChromeOS::IsConnecting() const { 274 return num_connecting_calls_ > 0; 275} 276 277BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const { 278 BluetoothDeviceClient::Properties* properties = 279 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 280 GetProperties(object_path_); 281 DCHECK(properties); 282 283 std::vector<device::BluetoothUUID> uuids; 284 const std::vector<std::string> &dbus_uuids = properties->uuids.value(); 285 for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin(); 286 iter != dbus_uuids.end(); ++iter) { 287 device::BluetoothUUID uuid(*iter); 288 DCHECK(uuid.IsValid()); 289 uuids.push_back(uuid); 290 } 291 return uuids; 292} 293 294bool BluetoothDeviceChromeOS::ExpectingPinCode() const { 295 return pairing_.get() && pairing_->ExpectingPinCode(); 296} 297 298bool BluetoothDeviceChromeOS::ExpectingPasskey() const { 299 return pairing_.get() && pairing_->ExpectingPasskey(); 300} 301 302bool BluetoothDeviceChromeOS::ExpectingConfirmation() const { 303 return pairing_.get() && pairing_->ExpectingConfirmation(); 304} 305 306void BluetoothDeviceChromeOS::Connect( 307 BluetoothDevice::PairingDelegate* pairing_delegate, 308 const base::Closure& callback, 309 const ConnectErrorCallback& error_callback) { 310 if (num_connecting_calls_++ == 0) 311 adapter_->NotifyDeviceChanged(this); 312 313 VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_ 314 << " in progress"; 315 316 if (IsPaired() || !pairing_delegate || !IsPairable()) { 317 // No need to pair, or unable to, skip straight to connection. 318 ConnectInternal(false, callback, error_callback); 319 } else { 320 // Initiate high-security connection with pairing. 321 BeginPairing(pairing_delegate); 322 323 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 324 Pair(object_path_, 325 base::Bind(&BluetoothDeviceChromeOS::OnPair, 326 weak_ptr_factory_.GetWeakPtr(), 327 callback, error_callback), 328 base::Bind(&BluetoothDeviceChromeOS::OnPairError, 329 weak_ptr_factory_.GetWeakPtr(), 330 error_callback)); 331 } 332} 333 334void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) { 335 if (!pairing_.get()) 336 return; 337 338 pairing_->SetPinCode(pincode); 339} 340 341void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) { 342 if (!pairing_.get()) 343 return; 344 345 pairing_->SetPasskey(passkey); 346} 347 348void BluetoothDeviceChromeOS::ConfirmPairing() { 349 if (!pairing_.get()) 350 return; 351 352 pairing_->ConfirmPairing(); 353} 354 355void BluetoothDeviceChromeOS::RejectPairing() { 356 if (!pairing_.get()) 357 return; 358 359 pairing_->RejectPairing(); 360} 361 362void BluetoothDeviceChromeOS::CancelPairing() { 363 bool canceled = false; 364 365 // If there is a callback in progress that we can reply to then use that 366 // to cancel the current pairing request. 367 if (pairing_.get() && pairing_->CancelPairing()) 368 canceled = true; 369 370 // If not we have to send an explicit CancelPairing() to the device instead. 371 if (!canceled) { 372 VLOG(1) << object_path_.value() << ": No pairing context or callback. " 373 << "Sending explicit cancel"; 374 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 375 CancelPairing( 376 object_path_, 377 base::Bind(&base::DoNothing), 378 base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError, 379 weak_ptr_factory_.GetWeakPtr())); 380 } 381 382 // Since there is no callback to this method it's possible that the pairing 383 // delegate is going to be freed before things complete (indeed it's 384 // documented that this is the method you should call while freeing the 385 // pairing delegate), so clear our the context holding on to it. 386 EndPairing(); 387} 388 389void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback, 390 const ErrorCallback& error_callback) { 391 VLOG(1) << object_path_.value() << ": Disconnecting"; 392 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 393 Disconnect( 394 object_path_, 395 base::Bind(&BluetoothDeviceChromeOS::OnDisconnect, 396 weak_ptr_factory_.GetWeakPtr(), 397 callback), 398 base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError, 399 weak_ptr_factory_.GetWeakPtr(), 400 error_callback)); 401} 402 403void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) { 404 VLOG(1) << object_path_.value() << ": Removing device"; 405 DBusThreadManager::Get()->GetBluetoothAdapterClient()-> 406 RemoveDevice( 407 adapter_->object_path_, 408 object_path_, 409 base::Bind(&base::DoNothing), 410 base::Bind(&BluetoothDeviceChromeOS::OnForgetError, 411 weak_ptr_factory_.GetWeakPtr(), 412 error_callback)); 413} 414 415void BluetoothDeviceChromeOS::ConnectToProfile( 416 device::BluetoothProfile* profile, 417 const base::Closure& callback, 418 const ConnectToProfileErrorCallback& error_callback) { 419 BluetoothProfileChromeOS* profile_chromeos = 420 static_cast<BluetoothProfileChromeOS*>(profile); 421 VLOG(1) << object_path_.value() << ": Connecting profile: " 422 << profile_chromeos->uuid().canonical_value(); 423 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 424 ConnectProfile( 425 object_path_, 426 profile_chromeos->uuid().canonical_value(), 427 base::Bind( 428 &BluetoothDeviceChromeOS::OnConnectProfile, 429 weak_ptr_factory_.GetWeakPtr(), 430 profile, 431 callback), 432 base::Bind( 433 &BluetoothDeviceChromeOS::OnConnectProfileError, 434 weak_ptr_factory_.GetWeakPtr(), 435 profile, 436 error_callback)); 437} 438 439void BluetoothDeviceChromeOS::ConnectToService( 440 const BluetoothUUID& uuid, 441 const ConnectToServiceCallback& callback, 442 const ConnectToServiceErrorCallback& error_callback) { 443 // TODO(keybuk): implement 444 NOTIMPLEMENTED(); 445} 446 447void BluetoothDeviceChromeOS::SetOutOfBandPairingData( 448 const device::BluetoothOutOfBandPairingData& data, 449 const base::Closure& callback, 450 const ErrorCallback& error_callback) { 451 // TODO(keybuk): implement 452 error_callback.Run(); 453} 454 455void BluetoothDeviceChromeOS::ClearOutOfBandPairingData( 456 const base::Closure& callback, 457 const ErrorCallback& error_callback) { 458 // TODO(keybuk): implement 459 error_callback.Run(); 460} 461 462BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing( 463 BluetoothDevice::PairingDelegate* pairing_delegate) { 464 pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate)); 465 return pairing_.get(); 466} 467 468void BluetoothDeviceChromeOS::EndPairing() { 469 pairing_.reset(); 470} 471 472BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const { 473 return pairing_.get(); 474} 475 476void BluetoothDeviceChromeOS::GattServiceAdded( 477 const dbus::ObjectPath& object_path) { 478 if (GetGattService(object_path.value())) { 479 VLOG(1) << "Remote GATT service already exists: " << object_path.value(); 480 return; 481 } 482 483 BluetoothGattServiceClient::Properties* properties = 484 DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 485 GetProperties(object_path); 486 DCHECK(properties); 487 if (properties->device.value() != object_path_) { 488 VLOG(2) << "Remote GATT service does not belong to this device."; 489 return; 490 } 491 492 VLOG(1) << "Adding new remote GATT service for device: " << GetAddress(); 493 494 BluetoothRemoteGattServiceChromeOS* service = 495 new BluetoothRemoteGattServiceChromeOS(this, object_path); 496 gatt_services_[service->GetIdentifier()] = service; 497 DCHECK(service->object_path() == object_path); 498 DCHECK(service->GetUUID().IsValid()); 499 500 FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, 501 GattServiceAdded(this, service)); 502} 503 504void BluetoothDeviceChromeOS::GattServiceRemoved( 505 const dbus::ObjectPath& object_path) { 506 GattServiceMap::iterator iter = gatt_services_.find(object_path.value()); 507 if (iter == gatt_services_.end()) { 508 VLOG(2) << "Unknown GATT service removed: " << object_path.value(); 509 return; 510 } 511 512 VLOG(1) << "Removing remote GATT service from device: " << GetAddress(); 513 514 BluetoothRemoteGattServiceChromeOS* service = 515 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second); 516 DCHECK(service->object_path() == object_path); 517 gatt_services_.erase(iter); 518 FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, 519 GattServiceRemoved(this, service)); 520 delete service; 521} 522 523void BluetoothDeviceChromeOS::ConnectInternal( 524 bool after_pairing, 525 const base::Closure& callback, 526 const ConnectErrorCallback& error_callback) { 527 VLOG(1) << object_path_.value() << ": Connecting"; 528 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 529 Connect( 530 object_path_, 531 base::Bind(&BluetoothDeviceChromeOS::OnConnect, 532 weak_ptr_factory_.GetWeakPtr(), 533 after_pairing, 534 callback), 535 base::Bind(&BluetoothDeviceChromeOS::OnConnectError, 536 weak_ptr_factory_.GetWeakPtr(), 537 after_pairing, 538 error_callback)); 539} 540 541void BluetoothDeviceChromeOS::OnConnect(bool after_pairing, 542 const base::Closure& callback) { 543 if (--num_connecting_calls_ == 0) 544 adapter_->NotifyDeviceChanged(this); 545 546 DCHECK(num_connecting_calls_ >= 0); 547 VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_ 548 << " still in progress"; 549 550 SetTrusted(); 551 552 if (after_pairing) 553 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult", 554 UMA_PAIRING_RESULT_SUCCESS, 555 UMA_PAIRING_RESULT_COUNT); 556 557 callback.Run(); 558} 559 560void BluetoothDeviceChromeOS::OnConnectError( 561 bool after_pairing, 562 const ConnectErrorCallback& error_callback, 563 const std::string& error_name, 564 const std::string& error_message) { 565 if (--num_connecting_calls_ == 0) 566 adapter_->NotifyDeviceChanged(this); 567 568 DCHECK(num_connecting_calls_ >= 0); 569 LOG(WARNING) << object_path_.value() << ": Failed to connect device: " 570 << error_name << ": " << error_message; 571 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_ 572 << " still in progress"; 573 574 // Determine the error code from error_name. 575 ConnectErrorCode error_code = ERROR_UNKNOWN; 576 if (error_name == bluetooth_device::kErrorFailed) { 577 error_code = ERROR_FAILED; 578 } else if (error_name == bluetooth_device::kErrorInProgress) { 579 error_code = ERROR_INPROGRESS; 580 } else if (error_name == bluetooth_device::kErrorNotSupported) { 581 error_code = ERROR_UNSUPPORTED_DEVICE; 582 } 583 584 if (after_pairing) 585 RecordPairingResult(error_code); 586 error_callback.Run(error_code); 587} 588 589void BluetoothDeviceChromeOS::OnPair( 590 const base::Closure& callback, 591 const ConnectErrorCallback& error_callback) { 592 VLOG(1) << object_path_.value() << ": Paired"; 593 594 EndPairing(); 595 596 ConnectInternal(true, callback, error_callback); 597} 598 599void BluetoothDeviceChromeOS::OnPairError( 600 const ConnectErrorCallback& error_callback, 601 const std::string& error_name, 602 const std::string& error_message) { 603 if (--num_connecting_calls_ == 0) 604 adapter_->NotifyDeviceChanged(this); 605 606 DCHECK(num_connecting_calls_ >= 0); 607 LOG(WARNING) << object_path_.value() << ": Failed to pair device: " 608 << error_name << ": " << error_message; 609 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_ 610 << " still in progress"; 611 612 EndPairing(); 613 614 // Determine the error code from error_name. 615 ConnectErrorCode error_code = ERROR_UNKNOWN; 616 if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) { 617 error_code = ERROR_FAILED; 618 } else if (error_name == bluetooth_device::kErrorFailed) { 619 error_code = ERROR_FAILED; 620 } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) { 621 error_code = ERROR_AUTH_FAILED; 622 } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) { 623 error_code = ERROR_AUTH_CANCELED; 624 } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) { 625 error_code = ERROR_AUTH_REJECTED; 626 } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) { 627 error_code = ERROR_AUTH_TIMEOUT; 628 } 629 630 RecordPairingResult(error_code); 631 error_callback.Run(error_code); 632} 633 634void BluetoothDeviceChromeOS::OnCancelPairingError( 635 const std::string& error_name, 636 const std::string& error_message) { 637 LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: " 638 << error_name << ": " << error_message; 639} 640 641void BluetoothDeviceChromeOS::SetTrusted() { 642 // Unconditionally send the property change, rather than checking the value 643 // first; there's no harm in doing this and it solves any race conditions 644 // with the property becoming true or false and this call happening before 645 // we get the D-Bus signal about the earlier change. 646 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> 647 GetProperties(object_path_)->trusted.Set( 648 true, 649 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, 650 weak_ptr_factory_.GetWeakPtr())); 651} 652 653void BluetoothDeviceChromeOS::OnSetTrusted(bool success) { 654 LOG_IF(WARNING, !success) << object_path_.value() 655 << ": Failed to set device as trusted"; 656} 657 658void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) { 659 VLOG(1) << object_path_.value() << ": Disconnected"; 660 callback.Run(); 661} 662 663void BluetoothDeviceChromeOS::OnDisconnectError( 664 const ErrorCallback& error_callback, 665 const std::string& error_name, 666 const std::string& error_message) { 667 LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: " 668 << error_name << ": " << error_message; 669 error_callback.Run(); 670} 671 672void BluetoothDeviceChromeOS::OnForgetError( 673 const ErrorCallback& error_callback, 674 const std::string& error_name, 675 const std::string& error_message) { 676 LOG(WARNING) << object_path_.value() << ": Failed to remove device: " 677 << error_name << ": " << error_message; 678 error_callback.Run(); 679} 680 681void BluetoothDeviceChromeOS::OnConnectProfile( 682 device::BluetoothProfile* profile, 683 const base::Closure& callback) { 684 BluetoothProfileChromeOS* profile_chromeos = 685 static_cast<BluetoothProfileChromeOS*>(profile); 686 VLOG(1) << object_path_.value() << ": Profile connected: " 687 << profile_chromeos->uuid().canonical_value(); 688 callback.Run(); 689} 690 691void BluetoothDeviceChromeOS::OnConnectProfileError( 692 device::BluetoothProfile* profile, 693 const ConnectToProfileErrorCallback& error_callback, 694 const std::string& error_name, 695 const std::string& error_message) { 696 BluetoothProfileChromeOS* profile_chromeos = 697 static_cast<BluetoothProfileChromeOS*>(profile); 698 VLOG(1) << object_path_.value() << ": Profile connection failed: " 699 << profile_chromeos->uuid().canonical_value() << ": " 700 << error_name << ": " << error_message; 701 error_callback.Run(error_message); 702} 703 704} // namespace chromeos 705