bluetooth_device_chromeos.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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)
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsPaired() const {
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Trusted devices are devices that don't support pairing but that the
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // user has explicitly connected; it makes no sense for UI purposes to
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // treat them differently from each other.
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->paired.value() || properties->trusted.value();
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnected() const {
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return properties->connected.value();
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnectable() const {
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothInputClient::Properties* input_properties =
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothInputClient()->
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // GetProperties returns NULL when the device does not implement the given
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // interface. Non HID devices are normally connectable.
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!input_properties)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return input_properties->reconnect_mode.value() != "device";
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnecting() const {
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return num_connecting_calls_ > 0;
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const {
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceClient::Properties* properties =
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetProperties(object_path_);
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(properties);
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<device::BluetoothUUID> uuids;
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const std::vector<std::string> &dbus_uuids = properties->uuids.value();
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin();
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       iter != dbus_uuids.end(); ++iter) {
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    device::BluetoothUUID uuid(*iter);
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(uuid.IsValid());
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    uuids.push_back(uuid);
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return uuids;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingPinCode();
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingPasskey();
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get() && pairing_->ExpectingConfirmation();
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Connect(
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BluetoothDevice::PairingDelegate* pairing_delegate,
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (num_connecting_calls_++ == 0)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " in progress";
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsPaired() || !pairing_delegate || !IsPairable()) {
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // No need to pair, or unable to, skip straight to connection.
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ConnectInternal(false, callback, error_callback);
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Initiate high-security connection with pairing.
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BeginPairing(pairing_delegate);
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        Pair(object_path_,
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             base::Bind(&BluetoothDeviceChromeOS::OnPair,
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        weak_ptr_factory_.GetWeakPtr(),
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        callback, error_callback),
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             base::Bind(&BluetoothDeviceChromeOS::OnPairError,
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        weak_ptr_factory_.GetWeakPtr(),
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        error_callback));
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->SetPinCode(pincode);
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->SetPasskey(passkey);
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConfirmPairing() {
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->ConfirmPairing();
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::RejectPairing() {
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!pairing_.get())
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_->RejectPairing();
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::CancelPairing() {
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool canceled = false;
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If there is a callback in progress that we can reply to then use that
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to cancel the current pairing request.
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (pairing_.get() && pairing_->CancelPairing())
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    canceled = true;
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If not we have to send an explicit CancelPairing() to the device instead.
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!canceled) {
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    VLOG(1) << object_path_.value() << ": No pairing context or callback. "
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            << "Sending explicit cancel";
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CancelPairing(
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            object_path_,
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&base::DoNothing),
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr()));
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Since there is no callback to this method it's possible that the pairing
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // delegate is going to be freed before things complete (indeed it's
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // documented that this is the method you should call while freeing the
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // pairing delegate), so clear our the context holding on to it.
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                         const ErrorCallback& error_callback) {
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Disconnecting";
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Disconnect(
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback),
3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Removing device";
3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RemoveDevice(
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          adapter_->object_path_,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&base::DoNothing),
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnForgetError,
3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConnectToService(
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const device::BluetoothUUID& service_uuid,
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SocketCallback& callback) {
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(scoped_refptr<device::BluetoothSocket>());
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConnectToProfile(
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device::BluetoothProfile* profile,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ConnectToProfileErrorCallback& error_callback) {
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting profile: "
404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value();
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ConnectProfile(
407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          object_path_,
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          profile_chromeos->uuid().canonical_value(),
409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(
4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              &BluetoothDeviceChromeOS::OnConnectProfile,
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              profile,
413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              callback),
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(
4157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              &BluetoothDeviceChromeOS::OnConnectProfileError,
416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr(),
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              profile,
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              error_callback));
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const device::BluetoothOutOfBandPairingData& data,
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing(
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BluetoothDevice::PairingDelegate* pairing_delegate) {
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate));
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get();
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BluetoothDeviceChromeOS::EndPairing() {
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  pairing_.reset();
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const {
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return pairing_.get();
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::GattServiceAdded(
451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path) {
452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (GetGattService(object_path.value())) {
453c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(1) << "Remote GATT service already exists: " << object_path.value();
454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
456c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothGattServiceClient::Properties* properties =
458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          GetProperties(object_path);
460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(properties);
461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (properties->device.value() != object_path_) {
462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(2) << "Remote GATT service does not belong to this device.";
463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Adding new remote GATT service for device: " << GetAddress();
467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothRemoteGattServiceChromeOS* service =
469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new BluetoothRemoteGattServiceChromeOS(this, object_path);
470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gatt_services_[service->GetIdentifier()] = service;
471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->object_path() == object_path);
472c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->GetUUID().IsValid());
473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_,
475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    GattServiceAdded(this, service));
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
478c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothDeviceChromeOS::GattServiceRemoved(
479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const dbus::ObjectPath& object_path) {
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  GattServiceMap::iterator iter = gatt_services_.find(object_path.value());
481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (iter == gatt_services_.end()) {
482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    VLOG(2) << "Unknown GATT service removed: " << object_path.value();
483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "Removing remote GATT service from device: " << GetAddress();
487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BluetoothRemoteGattServiceChromeOS* service =
489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second);
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(service->object_path() == object_path);
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gatt_services_.erase(iter);
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_,
493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    GattServiceRemoved(this, service));
494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  delete service;
495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::ConnectInternal(
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool after_pairing,
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connecting";
5027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Connect(
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          object_path_,
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnConnect,
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
5077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     after_pairing,
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback),
5097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
5117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     after_pairing,
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     error_callback));
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnect(bool after_pairing,
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                        const base::Closure& callback) {
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        << " still in progress";
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetTrusted();
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (after_pairing)
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              UMA_PAIRING_RESULT_SUCCESS,
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              UMA_PAIRING_RESULT_COUNT);
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run();
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectError(
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool after_pairing,
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to connect device: "
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " still in progress";
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine the error code from error_name.
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_name == bluetooth_device::kErrorFailed) {
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_FAILED;
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorInProgress) {
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_INPROGRESS;
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorNotSupported) {
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_UNSUPPORTED_DEVICE;
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (after_pairing)
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordPairingResult(error_code);
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run(error_code);
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnPair(
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Paired";
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectInternal(true, callback, error_callback);
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnPairError(
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (--num_connecting_calls_ == 0)
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(num_connecting_calls_ >= 0);
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to pair device: "
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          << " still in progress";
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndPairing();
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine the error code from error_name.
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_FAILED;
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorFailed) {
593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    error_code = ERROR_FAILED;
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_FAILED;
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_CANCELED;
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_REJECTED;
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_code = ERROR_AUTH_TIMEOUT;
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecordPairingResult(error_code);
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run(error_code);
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnCancelPairingError(
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: "
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::SetTrusted() {
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Unconditionally send the property change, rather than checking the value
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // first; there's no harm in doing this and it solves any race conditions
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // with the property becoming true or false and this call happening before
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we get the D-Bus signal about the earlier change.
6207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetProperties(object_path_)->trusted.Set(
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          true,
6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
6247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG_IF(WARNING, !success) << object_path_.value()
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            << ": Failed to set device as trusted";
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) {
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Disconnected";
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run();
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnDisconnectError(
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback,
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: "
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnForgetError(
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback,
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_name,
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error_message) {
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to remove device: "
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << error_name << ": " << error_message;
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_callback.Run();
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectProfile(
656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    device::BluetoothProfile* profile,
657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::Closure& callback) {
6587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
6597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
660b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile connected: "
661c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value();
662b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run();
663b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
664b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectProfileError(
666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    device::BluetoothProfile* profile,
667c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ConnectToProfileErrorCallback& error_callback,
668b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_name,
669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_message) {
6707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileChromeOS* profile_chromeos =
6717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothProfileChromeOS*>(profile);
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile connection failed: "
673c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          << profile_chromeos->uuid().canonical_value() << ": "
674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          << error_name << ": " << error_message;
675c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  error_callback.Run(error_message);
676b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
679