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