bluetooth_device_chromeos.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_device_chromeos.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string16.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/bluetooth_adapter_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/bluetooth_agent_service_provider.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/bluetooth_device_client.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/bluetooth_input_client.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/bluetooth_out_of_band_client.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/introspectable_client.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_chromeos.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_service_record.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "device/bluetooth/bluetooth_service_record_chromeos.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_socket_chromeos.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_utils.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using device::BluetoothDevice;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using device::BluetoothOutOfBandPairingData;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using device::BluetoothServiceRecord;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using device::BluetoothSocket;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DoNothingServiceRecordList(const BluetoothDevice::ServiceRecordList&) {}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BluetoothAdapterChromeOS* adapter)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : BluetoothDevice(),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      adapter_(adapter),
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bluetooth_class_(0),
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paired_(false),
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      trusted_(false),
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connected_(false),
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connectable_(true),
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connecting_(false),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pairing_delegate_(NULL),
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connecting_applications_counter_(0),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connecting_calls_(0),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_records_loaded_(false),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      weak_ptr_factory_(this) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return bluetooth_class_;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string BluetoothDeviceChromeOS::GetDeviceName() const {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return name_;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string BluetoothDeviceChromeOS::GetAddress() const {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return address_;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetVendorID() const {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetProductID() const {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint16 BluetoothDeviceChromeOS::GetDeviceID() const {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothDeviceChromeOS::IsPaired() const {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return paired_ || trusted_;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnected() const {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return connected_;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnectable() const {
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return connectable_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool BluetoothDeviceChromeOS::IsConnecting() const {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return connecting_;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)BluetoothDeviceChromeOS::ServiceList
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothDeviceChromeOS::GetServices() const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_uuids_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::GetServiceRecords(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceRecordsCallback& callback,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DiscoverServices(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          object_path_,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "",  // empty pattern to browse all services
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     callback,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::Bind(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         &BluetoothDeviceChromeOS::OnGetServiceRecordsError,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         weak_ptr_factory_.GetWeakPtr(),
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         callback,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         error_callback)));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ProvidesServiceWithName(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProvidesServiceCallback& callback) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetServiceRecords(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameCallback,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 name,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 callback),
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 callback));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !pincode_callback_.is_null();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !passkey_callback_.is_null();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !confirmation_callback_.is_null();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Connect(
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PairingDelegate* pairing_delegate,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is safe because Connect() and its callbacks are called in the same
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // thread.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_calls_++;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!connecting_) {
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connecting_ = true;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    adapter_->NotifyDeviceChanged(this);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_ = !!connecting_calls_;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set the decrement to be issued when either callback is called.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure wrapped_callback = base::Bind(
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &BluetoothDeviceChromeOS::OnConnectCallbackCalled,
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectErrorCallback wrapped_error_callback = base::Bind(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_callback);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsPaired()) {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Connection to already paired device.
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ConnectApplications(wrapped_callback, wrapped_error_callback);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (!pairing_delegate || !IsPairable()) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // No pairing delegate supplied, or unpairable device; initiate
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // low-security connection only.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateDevice(adapter_->object_path_,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     address_,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                weak_ptr_factory_.GetWeakPtr(),
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                wrapped_callback,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                wrapped_error_callback),
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                weak_ptr_factory_.GetWeakPtr(),
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                wrapped_error_callback));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initiate high-security connection with pairing.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!pairing_delegate_);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pairing_delegate_ = pairing_delegate;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The agent path is relatively meaningless, we use the device address
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to generate it as we only support one pairing attempt at a time for
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a given bluetooth device.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(agent_.get() == NULL);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string agent_path_basename;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReplaceChars(address_, ":", "_", &agent_path_basename);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::ObjectPath agent_path("/org/chromium/bluetooth_agent/" +
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                agent_path_basename);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (system_bus) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      agent_.reset(BluetoothAgentServiceProvider::Create(system_bus,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                         agent_path,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                         this));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      agent_.reset(NULL);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Pairing: " << address_;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothAdapterClient()->
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreatePairedDevice(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            adapter_->object_path_,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            address_,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            agent_path,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bluetooth_agent::kDisplayYesNoCapability,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       wrapped_callback,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       wrapped_error_callback),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       wrapped_error_callback));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!agent_.get() || pincode_callback_.is_null())
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pincode_callback_.Run(SUCCESS, pincode);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pincode_callback_.Reset();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!agent_.get() || passkey_callback_.is_null())
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  passkey_callback_.Run(SUCCESS, passkey);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  passkey_callback_.Reset();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ConfirmPairing() {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!agent_.get() || confirmation_callback_.is_null())
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  confirmation_callback_.Run(SUCCESS);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  confirmation_callback_.Reset();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::RejectPairing() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!agent_.get())
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pincode_callback_.is_null()) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pincode_callback_.Run(REJECTED, "");
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pincode_callback_.Reset();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!passkey_callback_.is_null()) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    passkey_callback_.Run(REJECTED, 0);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    passkey_callback_.Reset();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!confirmation_callback_.is_null()) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    confirmation_callback_.Run(REJECTED);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    confirmation_callback_.Reset();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::CancelPairing() {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool have_callback = false;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (agent_.get()) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!pincode_callback_.is_null()) {
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pincode_callback_.Run(CANCELLED, "");
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pincode_callback_.Reset();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      have_callback = true;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!passkey_callback_.is_null()) {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      passkey_callback_.Run(CANCELLED, 0);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      passkey_callback_.Reset();
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      have_callback = true;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!confirmation_callback_.is_null()) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      confirmation_callback_.Run(CANCELLED);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      confirmation_callback_.Reset();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      have_callback = true;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!have_callback) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // User cancels the pairing process.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DBusThreadManager::Get()->GetBluetoothAdapterClient()->CancelDeviceCreation(
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        adapter_->object_path_,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        address_,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&BluetoothDeviceChromeOS::OnCancelDeviceCreation,
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pairing_delegate_ = NULL;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    agent_.reset();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const ErrorCallback& error_callback) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Disconnect(object_path_,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&BluetoothDeviceChromeOS::DisconnectCallback,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            callback,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            error_callback));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveDevice(adapter_->object_path_,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   object_path_,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Bind(&BluetoothDeviceChromeOS::ForgetCallback,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              weak_ptr_factory_.GetWeakPtr(),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              error_callback));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ConnectToService(const std::string& service_uuid,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const SocketCallback& callback) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetServiceRecords(
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 service_uuid,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 callback),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          &BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          weak_ptr_factory_.GetWeakPtr(),
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BluetoothDeviceChromeOS::ConnectToProfile(
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    device::BluetoothProfile* profile,
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& callback,
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ErrorCallback& error_callback) {
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(keybuk): implement
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BluetoothOutOfBandPairingData& data,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddRemoteData(
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          object_path_,
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          address_,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          data,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     callback,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     error_callback));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveRemoteData(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          object_path_,
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          address_,
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     callback,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     error_callback));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SetObjectPath(
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& object_path) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(object_path_ == dbus::ObjectPath(""));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object_path_ = object_path;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::RemoveObjectPath() {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(object_path_ != dbus::ObjectPath(""));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object_path_ = dbus::ObjectPath("");
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Update(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BluetoothDeviceClient::Properties* properties,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool update_state) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string address = properties->address.value();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = properties->name.value();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bluetooth_class = properties->bluetooth_class.value();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<std::string>& uuids = properties->uuids.value();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address.empty())
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    address_ = address;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!name.empty())
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name_ = name;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bluetooth_class)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bluetooth_class_ = bluetooth_class;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!uuids.empty()) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_uuids_.clear();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_uuids_.assign(uuids.begin(), uuids.end());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (update_state) {
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // When the device reconnects and we don't have any service records for it,
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // try to update the cache or fail silently.
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!service_records_loaded_ && !connected_ &&
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        properties->connected.value())
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetServiceRecords(base::Bind(&DoNothingServiceRecordList),
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        base::Bind(&base::DoNothing));
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    paired_ = properties->paired.value();
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    trusted_ = properties->trusted.value();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connected_ = properties->connected.value();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnCreateDevice(
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Connection successful: " << device_path.value();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (object_path_.value().empty()) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object_path_ = device_path;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, object_path_ != device_path)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Conflicting device paths for objects, result gave: "
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << device_path.value() << " but signal gave: "
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << object_path_.value();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetTrusted();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In parallel with the |trusted| property change, call GetServiceRecords to
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // retrieve the SDP from the device and then, either on success or failure,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // call ConnectApplications.
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetServiceRecords(
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 error_callback),
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 error_callback));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnCreateDeviceError(
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_name,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_message) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The default |error_code| is an unknown error.
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Report any error in the log, even if we know the possible source of it.
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG(WARNING) << "Connection failed (on CreatePairedDevice): "
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << "\"" << name_ << "\" (" << address_ << "): "
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << error_name << ": \"" << error_message << "\"";
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Determines the right error code from error_name, assuming the error name
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // comes from CreatePairedDevice bluez function.
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error_name == bluetooth_adapter::kErrorConnectionAttemptFailed) {
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_FAILED;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (error_name == bluetooth_adapter::kErrorAuthenticationFailed) {
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_AUTH_FAILED;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (error_name == bluetooth_adapter::kErrorAuthenticationRejected) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_AUTH_REJECTED;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (error_name == bluetooth_adapter::kErrorAuthenticationTimeout) {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_AUTH_TIMEOUT;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error_code);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::CollectServiceRecordsCallback(
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceRecordsCallback& callback,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BluetoothDeviceClient::ServiceMap& service_map,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update the cache. No other thread is executing a GetServiceRecords
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // callback, so it is safe to delete the previous objects here.
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  service_records_.clear();
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(deymo): Perhaps don't update the cache if the new SDP information is
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // empty and we had something before. Some devices only answer this
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // information while paired, and this callback could be called in any order if
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // several calls to GetServiceRecords are made while initial pairing with the
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // device. This requires more investigation.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (BluetoothDeviceClient::ServiceMap::const_iterator i =
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_map.begin(); i != service_map.end(); ++i) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    service_records_.push_back(
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new BluetoothServiceRecordChromeOS(address_, i->second));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  service_records_loaded_ = true;
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(service_records_);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BluetoothDeviceChromeOS::SetTrusted() {
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Unconditionally send the property change, rather than checking the value
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // first; there's no harm in doing this and it solves any race conditions
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // with the property becoming true or false and this call happening before
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we get the D-Bus signal about the earlier change.
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetProperties(object_path_)->trusted.Set(
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          true,
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              &BluetoothDeviceChromeOS::OnSetTrusted,
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              weak_ptr_factory_.GetWeakPtr()));
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG_IF(WARNING, !success) << "Failed to set device as trusted: " << address_;
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnInitialGetServiceRecords(
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ServiceRecordList& list) {
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Connect application-layer protocols.
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectApplications(callback, error_callback);
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError(
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignore the error retrieving the service records and continue.
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG(WARNING) << "Error retrieving SDP for " << address_ << " after pairing.";
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Connect application-layer protocols.
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectApplications(callback, error_callback);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnGetServiceRecordsError(
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ServiceRecordsCallback& callback,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ErrorCallback& error_callback) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (service_records_loaded_) {
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(service_records_);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectCallbackCalled(
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback) {
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update the connecting status.
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool prev_connecting = connecting_;
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_calls_--;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_ = !!connecting_calls_;
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (prev_connecting != connecting_) adapter_->NotifyDeviceChanged(this);
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled(
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enum ConnectErrorCode error_code) {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update the connecting status.
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool prev_connecting = connecting_;
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_calls_--;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connecting_ = !!connecting_calls_;
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error_code);
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (prev_connecting != connecting_) adapter_->NotifyDeviceChanged(this);
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ConnectApplications(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Introspect the device object to determine supported applications.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetIntrospectableClient()->
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Introspect(bluetooth_device::kBluetoothDeviceServiceName,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 object_path_,
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Bind(&BluetoothDeviceChromeOS::OnIntrospect,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            weak_ptr_factory_.GetWeakPtr(),
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            callback,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            error_callback));
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnIntrospect(
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& callback,
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& service_name,
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& device_path,
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& xml_data,
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool success) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to determine supported applications: " << address_;
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_callback.Run(ERROR_UNKNOWN);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The introspection data for the device object may list one or more
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // additional D-Bus interfaces that BlueZ supports for this particular
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // device. Send appropraite Connect calls for each of those interfaces
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to connect all of the application protocols for this device.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> interfaces =
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IntrospectableClient::GetInterfacesFromIntrospectResult(xml_data);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0, connecting_applications_counter_);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connecting_applications_counter_ = 0;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::iterator iter = interfaces.begin();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != interfaces.end(); ++iter) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*iter == bluetooth_input::kBluetoothInputInterface) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connecting_applications_counter_++;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Supports Input interface.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBusThreadManager::Get()->GetBluetoothInputClient()->
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Connect(object_path_,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  base::Bind(&BluetoothDeviceChromeOS::OnConnect,
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             weak_ptr_factory_.GetWeakPtr(),
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             callback,
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             *iter),
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             weak_ptr_factory_.GetWeakPtr(),
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             error_callback, *iter));
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If OnConnect has been called for every call to Connect above, then this
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will decrement the counter to -1.  In that case, call the callback
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directly as it has not been called by any of the OnConnect callbacks.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is safe because OnIntrospect and OnConnect run on the same thread.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connecting_applications_counter_--;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connecting_applications_counter_ == -1)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run();
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnConnect(const base::Closure& callback,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const std::string& interface_name,
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const dbus::ObjectPath& device_path) {
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Application connection successful: " << device_path.value()
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << ": " << interface_name;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connecting_applications_counter_--;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |callback| should only be called once, meaning it cannot be called before
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all requests have been started.  The extra decrement after all requests
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have been started, and the check for -1 instead of 0 below, insure only a
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single call to |callback| will occur (provided OnConnect and OnIntrospect
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // run on the same thread, which is true).
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connecting_applications_counter_ == -1) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connecting_applications_counter_ = 0;
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetTrusted();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run();
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnConnectError(
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConnectErrorCallback& error_callback,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& interface_name,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_name,
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_message) {
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The default |error_code| is an unknown error.
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectErrorCode error_code = ERROR_UNKNOWN;
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Report any error in the log, even if we know the possible source of it.
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG(WARNING) << "Connection failed (on Connect): "
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << interface_name << ": "
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << "\"" << name_ << "\" (" << address_ << "): "
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << error_name << ": \"" << error_message << "\"";
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Determines the right error code from error_name, assuming the error name
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // comes from Connect bluez function.
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (error_name == bluetooth_adapter::kErrorFailed) {
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_FAILED;
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (error_name == bluetooth_adapter::kErrorInProgress) {
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_INPROGRESS;
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (error_name == bluetooth_adapter::kErrorNotSupported) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_code = ERROR_UNSUPPORTED_DEVICE;
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  error_callback.Run(error_code);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::DisconnectCallback(
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback,
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Disconnection successful: " << address_;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (connected_)  {
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Disconnection failed: " << address_;
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_callback.Run();
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "Disconnection failed on a already disconnected device: "
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              << address_;
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback.Run();
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ForgetCallback(
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback,
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& adapter_path,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's quite normal that this path never gets called on success; we use a
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // weak pointer, and bluetoothd might send the DeviceRemoved signal before
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the method reply, in which case this object is deleted and the
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback never takes place. Therefore don't do anything here for the
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // success case.
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Forget failed: " << address_;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnCancelDeviceCreation(
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const dbus::ObjectPath& adapter_path,
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool success) {
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!success)
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "CancelDeviceCreation failed: " << address_;
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback(
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProvidesServiceCallback& callback) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(false);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::SearchServicesForNameCallback(
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProvidesServiceCallback& callback,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceRecordList& list) {
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ServiceRecordList::const_iterator i = list.begin();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i != list.end(); ++i) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->name() == name) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(true);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(false);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback(
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SocketCallback& callback) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(NULL);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback(
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_uuid,
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SocketCallback& callback,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServiceRecordList& list) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ServiceRecordList::const_iterator i = list.begin();
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i != list.end(); ++i) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->uuid() == service_uuid) {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If multiple service records are found, use the first one that works.
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<BluetoothSocket> socket(
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BluetoothSocketChromeOS::CreateBluetoothSocket(**i));
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (socket.get() != NULL) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback.Run(socket);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(NULL);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::OnRemoteDataCallback(
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ErrorCallback& error_callback,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_callback.Run();
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::DisconnectRequested(
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& object_path) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(object_path == object_path_);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Release() {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Release: " << address_;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->DismissDisplayOrConfirm();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_ = NULL;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pincode_callback_.Reset();
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  passkey_callback_.Reset();
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  confirmation_callback_.Reset();
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  agent_.reset();
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::RequestPinCode(
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PinCodeCallback& callback) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "RequestPinCode: " << device_path.value();
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pincode_callback_.is_null());
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pincode_callback_ = callback;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->RequestPinCode(this);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::RequestPasskey(
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PasskeyCallback& callback) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "RequestPasskey: " << device_path.value();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(passkey_callback_.is_null());
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  passkey_callback_ = callback;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->RequestPasskey(this);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::DisplayPinCode(
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pincode) {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "DisplayPinCode: " << device_path.value() << " " << pincode;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->DisplayPinCode(this, pincode);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::DisplayPasskey(
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 passkey) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "DisplayPasskey: " << device_path.value() << " " << passkey;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->DisplayPasskey(this, passkey);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::RequestConfirmation(
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& device_path,
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 passkey,
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ConfirmationCallback& callback) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "RequestConfirmation: " << device_path.value() << " " << passkey;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(confirmation_callback_.is_null());
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  confirmation_callback_ = callback;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->ConfirmPasskey(this, passkey);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Authorize(const dbus::ObjectPath& device_path,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const std::string& uuid,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const ConfirmationCallback& callback) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(device_path == object_path_);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Rejected authorization for service: " << uuid
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " requested from device: " << device_path.value();
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(REJECTED);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::ConfirmModeChange(
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mode mode,
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ConfirmationCallback& callback) {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Rejected adapter-level mode change: " << mode
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " made on agent for device: " << address_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(REJECTED);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BluetoothDeviceChromeOS::Cancel() {
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(agent_.get());
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "Cancel: " << address_;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pairing_delegate_);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pairing_delegate_->DismissDisplayOrConfirm();
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create(
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BluetoothAdapterChromeOS* adapter) {
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new BluetoothDeviceChromeOS(adapter);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
893