bluetooth_device_chromeos.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_device_chromeos.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <stdio.h>
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_adapter_client.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_device_client.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/bluetooth_gatt_service_client.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_input_client.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/bus.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_chromeos.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "device/bluetooth/bluetooth_pairing_chromeos.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_profile_chromeos.h"
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "device/bluetooth/bluetooth_socket.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using device::BluetoothDevice;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Histogram enumerations for pairing results.
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum UMAPairingResult {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_SUCCESS,
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_INPROGRESS,
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_FAILED,
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_AUTH_FAILED,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_AUTH_CANCELED,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_AUTH_REJECTED,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_AUTH_TIMEOUT,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE,
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_UNKNOWN_ERROR,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // NOTE: Add new pairing results immediately above this line. Make sure to
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // update the enum list in tools/histogram/histograms.xml accordinly.
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_PAIRING_RESULT_COUNT
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ParseModalias(const dbus::ObjectPath& object_path,
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   BluetoothDevice::VendorIDSource* vendor_id_source,
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   uint16* vendor_id,
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   uint16* product_id,
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   uint16* device_id) {
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  chromeos::BluetoothDeviceClient::Properties* properties =
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetBluetoothDeviceClient()->
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          GetProperties(object_path);
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string modalias = properties->modalias.value();
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BluetoothDevice::VendorIDSource source_value;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int vendor_value, product_value, device_value;
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (sscanf(modalias.c_str(), "bluetooth:v%04xp%04xd%04x",
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             &vendor_value, &product_value, &device_value) == 3) {
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    source_value = BluetoothDevice::VENDOR_ID_BLUETOOTH;
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (sscanf(modalias.c_str(), "usb:v%04xp%04xd%04x",
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    &vendor_value, &product_value, &device_value) == 3) {
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    source_value = BluetoothDevice::VENDOR_ID_USB;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (vendor_id_source != NULL)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *vendor_id_source = source_value;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (vendor_id != NULL)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *vendor_id = vendor_value;
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (product_id != NULL)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *product_id = product_value;
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (device_id != NULL)
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *device_id = device_value;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code) {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMAPairingResult pairing_result;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (error_code) {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_INPROGRESS:
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_INPROGRESS;
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_FAILED:
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_FAILED;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_AUTH_FAILED:
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_AUTH_FAILED;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_AUTH_CANCELED:
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_AUTH_CANCELED;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_AUTH_REJECTED:
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_AUTH_REJECTED;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_AUTH_TIMEOUT:
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_AUTH_TIMEOUT;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pairing_result = UMA_PAIRING_RESULT_UNKNOWN_ERROR;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            pairing_result,
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            UMA_PAIRING_RESULT_COUNT);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BluetoothAdapterChromeOS* adapter,
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const dbus::ObjectPath& object_path)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : adapter_(adapter),
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      object_path_(object_path),
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      num_connecting_calls_(0),
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Add all known GATT services.
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::vector<dbus::ObjectPath> gatt_services =
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices();
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin();
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       it != gatt_services.end(); ++it) {
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    GattServiceAdded(*it);
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      RemoveObserver(this);
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Copy the GATT services list here and clear the original so that when we
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // send GattServiceRemoved(), GetGattServices() returns no services.
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  GattServiceMap gatt_services = gatt_services_;
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gatt_services_.clear();
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (GattServiceMap::iterator iter = gatt_services.begin();
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       iter != gatt_services.end(); ++iter) {
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FOR_EACH_OBSERVER(BluetoothDevice::Observer, observers_,
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      GattServiceRemoved(this, iter->second));
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    delete iter->second;
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::AddObserver(
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothDevice::Observer* observer) {
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(observer);
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  observers_.AddObserver(observer);
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::RemoveObserver(
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothDevice::Observer* observer) {
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(observer);
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  observers_.RemoveObserver(observer);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->bluetooth_class.value();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string BluetoothDeviceChromeOS::GetDeviceName() const {
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->alias.value();
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string BluetoothDeviceChromeOS::GetAddress() const {
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->address.value();
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothDevice::VendorIDSource
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothDeviceChromeOS::GetVendorIDSource() const {
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN;
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ParseModalias(object_path_, &vendor_id_source, NULL, NULL, NULL);
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return vendor_id_source;
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetVendorID() const {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16 vendor_id  = 0;
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ParseModalias(object_path_, NULL, &vendor_id, NULL, NULL);
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return vendor_id;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetProductID() const {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16 product_id  = 0;
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ParseModalias(object_path_, NULL, NULL, &product_id, NULL);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return product_id;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetDeviceID() const {
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16 device_id  = 0;
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ParseModalias(object_path_, NULL, NULL, NULL, &device_id);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return device_id;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint BluetoothDeviceChromeOS::GetRSSI() const {
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NOTIMPLEMENTED();
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return kUnknownPower;
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint BluetoothDeviceChromeOS::GetCurrentHostTransmitPower() const {
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NOTIMPLEMENTED();
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return kUnknownPower;
2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuint BluetoothDeviceChromeOS::GetMaximumHostTransmitPower() const {
2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NOTIMPLEMENTED();
2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return kUnknownPower;
2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsPaired() const {
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Trusted devices are devices that don't support pairing but that the
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // user has explicitly connected; it makes no sense for UI purposes to
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // treat them differently from each other.
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->paired.value() || properties->trusted.value();
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnected() const {
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->connected.value();
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnectable() const {
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothInputClient::Properties* input_properties =
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothInputClient()->
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // GetProperties returns NULL when the device does not implement the given
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // interface. Non HID devices are normally connectable.
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!input_properties)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return input_properties->reconnect_mode.value() != "device";
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnecting() const {
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return num_connecting_calls_ > 0;
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const {
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<device::BluetoothUUID> uuids;
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::vector<std::string> &dbus_uuids = properties->uuids.value();
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin();
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       iter != dbus_uuids.end(); ++iter) {
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothUUID uuid(*iter);
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(uuid.IsValid());
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    uuids.push_back(uuid);
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return uuids;
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingPinCode();
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingPasskey();
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingConfirmation();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Connect(
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BluetoothDevice::PairingDelegate* pairing_delegate,
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (num_connecting_calls_++ == 0)
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " in progress";
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsPaired() || !pairing_delegate || !IsPairable()) {
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // No need to pair, or unable to, skip straight to connection.
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ConnectInternal(false, callback, error_callback);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Initiate high-security connection with pairing.
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BeginPairing(pairing_delegate);
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        Pair(object_path_,
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             base::Bind(&BluetoothDeviceChromeOS::OnPair,
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        weak_ptr_factory_.GetWeakPtr(),
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        callback, error_callback),
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             base::Bind(&BluetoothDeviceChromeOS::OnPairError,
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        weak_ptr_factory_.GetWeakPtr(),
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        error_callback));
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->SetPinCode(pincode);
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->SetPasskey(passkey);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConfirmPairing() {
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->ConfirmPairing();
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::RejectPairing() {
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->RejectPairing();
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::CancelPairing() {
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool canceled = false;
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If there is a callback in progress that we can reply to then use that
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to cancel the current pairing request.
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (pairing_.get() && pairing_->CancelPairing())
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    canceled = true;
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If not we have to send an explicit CancelPairing() to the device instead.
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!canceled) {
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    VLOG(1) << object_path_.value() << ": No pairing context or callback. "
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            << "Sending explicit cancel";
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CancelPairing(
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            object_path_,
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&base::DoNothing),
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr()));
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Since there is no callback to this method it's possible that the pairing
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // delegate is going to be freed before things complete (indeed it's
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // documented that this is the method you should call while freeing the
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // pairing delegate), so clear our the context holding on to it.
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                         const ErrorCallback& error_callback) {
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Disconnecting";
3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Disconnect(
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback),
3887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Removing device";
3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RemoveDevice(
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          adapter_->object_path_,
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&base::DoNothing),
4007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnForgetError,
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConnectToProfile(
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device::BluetoothProfile* profile,
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ConnectToProfileErrorCallback& error_callback) {
4097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting profile: "
412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value();
4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ConnectProfile(
415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          object_path_,
416c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          profile_chromeos->uuid().canonical_value(),
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(
4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              &BluetoothDeviceChromeOS::OnConnectProfile,
419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              profile,
421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              callback),
422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(
4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              &BluetoothDeviceChromeOS::OnConnectProfileError,
424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              profile,
426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              error_callback));
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const device::BluetoothOutOfBandPairingData& data,
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing(
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BluetoothDevice::PairingDelegate* pairing_delegate) {
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate));
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get();
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BluetoothDeviceChromeOS::EndPairing() {
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_.reset();
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const {
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get();
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::GattServiceAdded(
459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path) {
460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (GetGattService(object_path.value())) {
461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(1) << "Remote GATT service already exists: " << object_path.value();
462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothGattServiceClient::Properties* properties =
466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          GetProperties(object_path);
468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(properties);
469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (properties->device.value() != object_path_) {
470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(2) << "Remote GATT service does not belong to this device.";
471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
472c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Adding new remote GATT service for device: " << GetAddress();
475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothRemoteGattServiceChromeOS* service =
477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new BluetoothRemoteGattServiceChromeOS(this, object_path);
478c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gatt_services_[service->GetIdentifier()] = service;
479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->object_path() == object_path);
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->GetUUID().IsValid());
481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_,
483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    GattServiceAdded(this, service));
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::GattServiceRemoved(
487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path) {
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  GattServiceMap::iterator iter = gatt_services_.find(object_path.value());
489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (iter == gatt_services_.end()) {
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(2) << "Unknown GATT service removed: " << object_path.value();
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Removing remote GATT service from device: " << GetAddress();
495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothRemoteGattServiceChromeOS* service =
497c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second);
498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->object_path() == object_path);
499c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gatt_services_.erase(iter);
500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_,
501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    GattServiceRemoved(this, service));
502c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  delete service;
503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
504c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConnectInternal(
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool after_pairing,
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting";
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnConnect,
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     after_pairing,
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback),
5177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     after_pairing,
5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
5217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnect(bool after_pairing,
5247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                        const base::Closure& callback) {
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        << " still in progress";
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetTrusted();
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (after_pairing)
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              UMA_PAIRING_RESULT_SUCCESS,
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              UMA_PAIRING_RESULT_COUNT);
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run();
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectError(
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool after_pairing,
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to connect device: "
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " still in progress";
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine the error code from error_name.
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_name == bluetooth_device::kErrorFailed) {
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_FAILED;
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorInProgress) {
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_INPROGRESS;
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorNotSupported) {
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_UNSUPPORTED_DEVICE;
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (after_pairing)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordPairingResult(error_code);
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run(error_code);
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnPair(
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Paired";
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectInternal(true, callback, error_callback);
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnPairError(
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to pair device: "
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " still in progress";
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine the error code from error_name.
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_FAILED;
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorFailed) {
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    error_code = ERROR_FAILED;
602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_FAILED;
604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_CANCELED;
606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_REJECTED;
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_TIMEOUT;
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecordPairingResult(error_code);
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run(error_code);
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnCancelPairingError(
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: "
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetTrusted() {
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Unconditionally send the property change, rather than checking the value
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // first; there's no harm in doing this and it solves any race conditions
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // with the property becoming true or false and this call happening before
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we get the D-Bus signal about the earlier change.
6287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetProperties(object_path_)->trusted.Set(
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          true,
6317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
6327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG_IF(WARNING, !success) << object_path_.value()
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            << ": Failed to set device as trusted";
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) {
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Disconnected";
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run();
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnDisconnectError(
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback,
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: "
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnForgetError(
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback,
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to remove device: "
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectProfile(
664b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    device::BluetoothProfile* profile,
665b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::Closure& callback) {
6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
6677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
668b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile connected: "
669c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value();
670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run();
671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectProfileError(
674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    device::BluetoothProfile* profile,
675c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ConnectToProfileErrorCallback& error_callback,
676b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_name,
677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_message) {
6787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
6797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
680b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile connection failed: "
681c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value() << ": "
682b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          << error_name << ": " << error_message;
683c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  error_callback.Run(error_message);
684b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
687