17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// found in the LICENSE file.
4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_profile_chromeos.h"
6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include <string>
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/basictypes.h"
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/bind.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/callback.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/logging.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/memory/weak_ptr.h"
159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/task_runner_util.h"
18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/threading/worker_pool.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_profile_manager_client.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_profile_service_provider.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "dbus/bus.h"
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "dbus/file_descriptor.h"
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "dbus/object_path.h"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_chromeos.h"
27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "device/bluetooth/bluetooth_device.h"
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_device_chromeos.h"
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "device/bluetooth/bluetooth_profile.h"
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "device/bluetooth/bluetooth_socket.h"
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "device/bluetooth/bluetooth_socket_chromeos.h"
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using device::BluetoothAdapter;
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using device::BluetoothAdapterFactory;
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using device::BluetoothDevice;
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using device::BluetoothProfile;
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using device::BluetoothSocket;
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace {
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Check the validity of a file descriptor received from D-Bus. Must be run
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// on a thread where i/o is permitted.
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)scoped_ptr<dbus::FileDescriptor> CheckValidity(
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scoped_ptr<dbus::FileDescriptor> fd) {
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  fd->CheckValidity();
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return fd.Pass();
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace
52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace chromeos {
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothProfileChromeOS::BluetoothProfileChromeOS()
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    : weak_ptr_factory_(this) {
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothProfileChromeOS::~BluetoothProfileChromeOS() {
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(object_path_.value().empty());
62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile_.get() == NULL);
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::Init(
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& uuid,
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const device::BluetoothProfile::Options& options,
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ProfileCallback& callback) {
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(object_path_.value().empty());
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile_.get() == NULL);
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!BluetoothDevice::IsUUIDValid(uuid)) {
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    callback.Run(NULL);
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  uuid_ = uuid;
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothProfileManagerClient::Options bluetooth_options;
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.name = options.name;
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.service = uuid;
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.channel = options.channel;
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.psm = options.psm;
84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.require_authentication = options.require_authentication;
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.require_authorization = options.require_authorization;
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.auto_connect = options.auto_connect;
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.version = options.version;
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bluetooth_options.features = options.features;
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The object path is relatively meaningless, but has to be unique, so we
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // use the UUID of the profile.
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::string uuid_path;
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::ReplaceChars(uuid, ":-", "_", &uuid_path);
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" +
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                  uuid_path);
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  profile_.reset(BluetoothProfileServiceProvider::Create(
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      system_bus, object_path_, this));
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile_.get());
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Register profile";
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      RegisterProfile(
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          object_path_,
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          uuid,
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          bluetooth_options,
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothProfileChromeOS::OnRegisterProfile,
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback),
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothProfileChromeOS::OnRegisterProfileError,
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     callback));
115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::Unregister() {
118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(!object_path_.value().empty());
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(profile_.get());
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  profile_.reset();
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Unregister profile";
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      UnregisterProfile(
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          object_path_,
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfile,
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfileError,
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::SetConnectionCallback(
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ConnectionCallback& callback) {
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  connection_callback_ = callback;
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::Release() {
139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Release";
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::NewConnection(
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const dbus::ObjectPath& device_path,
144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scoped_ptr<dbus::FileDescriptor> fd,
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const BluetoothProfileServiceProvider::Delegate::Options& options,
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ConfirmationCallback& callback) {
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": New connection from device: "
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          << device_path.value();;
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (connection_callback_.is_null()) {
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    callback.Run(REJECTED);
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Punt descriptor validity check to a worker thread where i/o is permitted;
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // on return we'll fetch the adapter and then call the connection callback.
156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  //
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // base::Passed is used to take ownership of the file descriptor during the
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // CheckValidity() call and pass that ownership to the GetAdapter() call.
159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::WorkerPool::GetTaskRunner(false).get(),
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      FROM_HERE,
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&CheckValidity, base::Passed(&fd)),
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&BluetoothProfileChromeOS::GetAdapter,
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 device_path,
166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 options,
167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 callback));
168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::RequestDisconnection(
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const dbus::ObjectPath& device_path,
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ConfirmationCallback& callback) {
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Request disconnection";
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run(SUCCESS);
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::Cancel() {
178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Cancel";
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::OnRegisterProfile(
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ProfileCallback& callback) {
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile registered";
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run(this);
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::OnRegisterProfileError(
188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ProfileCallback& callback,
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_name,
190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_message) {
191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               << error_name << ": " << error_message;
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run(NULL);
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  Unregister();
196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::OnUnregisterProfile() {
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Profile unregistered";
200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  object_path_ = dbus::ObjectPath("");
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  delete this;
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::OnUnregisterProfileError(
205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_name,
206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& error_message) {
207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: "
208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               << error_name << ": " << error_message;
209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  object_path_ = dbus::ObjectPath("");
210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  delete this;
211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::GetAdapter(
214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const dbus::ObjectPath& device_path,
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const BluetoothProfileServiceProvider::Delegate::Options& options,
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const ConfirmationCallback& callback,
217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      scoped_ptr<dbus::FileDescriptor> fd) {
218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Validity check complete";
219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!fd->is_valid()) {
220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    callback.Run(REJECTED);
221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  BluetoothAdapterFactory::GetAdapter(
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&BluetoothProfileChromeOS::OnGetAdapter,
226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
227b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 device_path,
228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 options,
229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 callback,
230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 base::Passed(&fd)));
231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void BluetoothProfileChromeOS::OnGetAdapter(
234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const dbus::ObjectPath& device_path,
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const BluetoothProfileServiceProvider::Delegate::Options&
236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        options,
237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const ConfirmationCallback& callback,
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scoped_ptr<dbus::FileDescriptor> fd,
239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scoped_refptr<BluetoothAdapter> adapter) {
240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  VLOG(1) << object_path_.value() << ": Obtained adapter reference";
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  callback.Run(SUCCESS);
242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothDeviceChromeOS* device =
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<BluetoothAdapterChromeOS*>(adapter.get())->
245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          GetDeviceWithPath(device_path);
246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(device);
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_refptr<BluetoothSocket> socket((
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      BluetoothSocketChromeOS::Create(fd.get())));
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  connection_callback_.Run(device, socket);
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace chromeos
254