Relanding this change. The bug 332430 which caused this to be reverted will be addres...
[chromium-blink-merge.git] / device / bluetooth / bluetooth_profile_chromeos.cc
blob7d6b786fa460066b71f04b1582cc24061789b7e9
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/bluetooth/bluetooth_profile_chromeos.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/strings/string_util.h"
17 #include "base/task_runner_util.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "base/threading/worker_pool.h"
20 #include "chromeos/dbus/bluetooth_profile_manager_client.h"
21 #include "chromeos/dbus/bluetooth_profile_service_provider.h"
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "dbus/bus.h"
24 #include "dbus/file_descriptor.h"
25 #include "dbus/object_path.h"
26 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
27 #include "device/bluetooth/bluetooth_adapter_factory.h"
28 #include "device/bluetooth/bluetooth_device.h"
29 #include "device/bluetooth/bluetooth_device_chromeos.h"
30 #include "device/bluetooth/bluetooth_profile.h"
31 #include "device/bluetooth/bluetooth_socket.h"
32 #include "device/bluetooth/bluetooth_socket_chromeos.h"
33 #include "third_party/cros_system_api/dbus/service_constants.h"
35 using device::BluetoothAdapter;
36 using device::BluetoothAdapterFactory;
37 using device::BluetoothDevice;
38 using device::BluetoothProfile;
39 using device::BluetoothSocket;
41 namespace {
43 // Check the validity of a file descriptor received from D-Bus. Must be run
44 // on a thread where i/o is permitted.
45 scoped_ptr<dbus::FileDescriptor> CheckValidity(
46 scoped_ptr<dbus::FileDescriptor> fd) {
47 base::ThreadRestrictions::AssertIOAllowed();
48 fd->CheckValidity();
49 return fd.Pass();
52 } // namespace
55 namespace chromeos {
57 BluetoothProfileChromeOS::BluetoothProfileChromeOS()
58 : weak_ptr_factory_(this) {
61 BluetoothProfileChromeOS::~BluetoothProfileChromeOS() {
62 DCHECK(object_path_.value().empty());
63 DCHECK(profile_.get() == NULL);
65 if (adapter_.get()) {
66 adapter_->RemoveObserver(this);
67 adapter_ = NULL;
71 void BluetoothProfileChromeOS::Init(
72 const device::BluetoothUUID& uuid,
73 const device::BluetoothProfile::Options& options,
74 const ProfileCallback& callback) {
75 DCHECK(object_path_.value().empty());
76 DCHECK(profile_.get() == NULL);
78 if (!uuid.IsValid()) {
79 callback.Run(NULL);
80 return;
83 uuid_ = uuid;
85 options_.name = options.name;
86 options_.service = uuid.canonical_value();
87 options_.channel = options.channel;
88 options_.psm = options.psm;
89 options_.require_authentication = options.require_authentication;
90 options_.require_authorization = options.require_authorization;
91 options_.auto_connect = options.auto_connect;
92 options_.version = options.version;
93 options_.features = options.features;
95 // The object path is relatively meaningless, but has to be unique, so we
96 // use the UUID of the profile.
97 std::string uuid_path;
98 base::ReplaceChars(uuid.canonical_value(), ":-", "_", &uuid_path);
100 object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" +
101 uuid_path);
103 dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
104 profile_.reset(BluetoothProfileServiceProvider::Create(
105 system_bus, object_path_, this));
106 DCHECK(profile_.get());
108 // Now the profile object is registered we need an adapter to register it
109 // with.
110 BluetoothAdapterFactory::GetAdapter(
111 base::Bind(&BluetoothProfileChromeOS::OnGetAdapter,
112 weak_ptr_factory_.GetWeakPtr(),
113 callback));
116 void BluetoothProfileChromeOS::Unregister() {
117 DCHECK(!object_path_.value().empty());
118 DCHECK(profile_.get());
120 profile_.reset();
122 VLOG(1) << object_path_.value() << ": Unregister profile";
123 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
124 UnregisterProfile(
125 object_path_,
126 base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfile,
127 weak_ptr_factory_.GetWeakPtr()),
128 base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfileError,
129 weak_ptr_factory_.GetWeakPtr()));
132 void BluetoothProfileChromeOS::SetConnectionCallback(
133 const ConnectionCallback& callback) {
134 connection_callback_ = callback;
137 void BluetoothProfileChromeOS::AdapterPresentChanged(BluetoothAdapter* adapter,
138 bool present) {
139 if (!present)
140 return;
142 VLOG(1) << object_path_.value() << ": Register profile";
143 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
144 RegisterProfile(
145 object_path_,
146 uuid_.canonical_value(),
147 options_,
148 base::Bind(&BluetoothProfileChromeOS::OnInternalRegisterProfile,
149 weak_ptr_factory_.GetWeakPtr()),
150 base::Bind(&BluetoothProfileChromeOS::OnInternalRegisterProfileError,
151 weak_ptr_factory_.GetWeakPtr()));
154 void BluetoothProfileChromeOS::OnGetAdapter(
155 const ProfileCallback& callback,
156 scoped_refptr<device::BluetoothAdapter> adapter) {
157 DCHECK(!adapter_.get());
158 adapter_ = adapter;
159 adapter_->AddObserver(this);
161 VLOG(1) << object_path_.value() << ": Register profile";
162 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
163 RegisterProfile(
164 object_path_,
165 uuid_.canonical_value(),
166 options_,
167 base::Bind(&BluetoothProfileChromeOS::OnRegisterProfile,
168 weak_ptr_factory_.GetWeakPtr(),
169 callback),
170 base::Bind(&BluetoothProfileChromeOS::OnRegisterProfileError,
171 weak_ptr_factory_.GetWeakPtr(),
172 callback));
175 void BluetoothProfileChromeOS::Release() {
176 VLOG(1) << object_path_.value() << ": Release";
179 void BluetoothProfileChromeOS::NewConnection(
180 const dbus::ObjectPath& device_path,
181 scoped_ptr<dbus::FileDescriptor> fd,
182 const BluetoothProfileServiceProvider::Delegate::Options& options,
183 const ConfirmationCallback& callback) {
184 VLOG(1) << object_path_.value() << ": New connection from device: "
185 << device_path.value();
186 if (connection_callback_.is_null()) {
187 callback.Run(REJECTED);
188 return;
191 // Punt descriptor validity check to a worker thread where i/o is permitted;
192 // on return we'll call the connection callback.
194 // base::Passed is used to take ownership of the file descriptor during the
195 // CheckValidity() call and pass that ownership to callback.
196 base::PostTaskAndReplyWithResult(
197 base::WorkerPool::GetTaskRunner(false).get(),
198 FROM_HERE,
199 base::Bind(&CheckValidity, base::Passed(&fd)),
200 base::Bind(&BluetoothProfileChromeOS::OnCheckValidity,
201 weak_ptr_factory_.GetWeakPtr(),
202 device_path,
203 options,
204 callback));
207 void BluetoothProfileChromeOS::RequestDisconnection(
208 const dbus::ObjectPath& device_path,
209 const ConfirmationCallback& callback) {
210 VLOG(1) << object_path_.value() << ": Request disconnection";
211 callback.Run(SUCCESS);
214 void BluetoothProfileChromeOS::Cancel() {
215 VLOG(1) << object_path_.value() << ": Cancel";
218 void BluetoothProfileChromeOS::OnInternalRegisterProfile() {
219 VLOG(1) << object_path_.value() << ": Profile registered";
222 void BluetoothProfileChromeOS::OnInternalRegisterProfileError(
223 const std::string& error_name,
224 const std::string& error_message) {
225 // It's okay if the profile already exists, it means we registered it on
226 // initialization.
227 if (error_name == bluetooth_profile_manager::kErrorAlreadyExists)
228 return;
230 LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
231 << error_name << ": " << error_message;
234 void BluetoothProfileChromeOS::OnRegisterProfile(
235 const ProfileCallback& callback) {
236 VLOG(1) << object_path_.value() << ": Profile registered";
237 callback.Run(this);
240 void BluetoothProfileChromeOS::OnRegisterProfileError(
241 const ProfileCallback& callback,
242 const std::string& error_name,
243 const std::string& error_message) {
244 // It's okay if the profile already exists, it means we registered it when
245 // we first saw the adapter.
246 if (error_name == bluetooth_profile_manager::kErrorAlreadyExists)
247 return;
249 LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
250 << error_name << ": " << error_message;
251 callback.Run(NULL);
254 void BluetoothProfileChromeOS::OnUnregisterProfile() {
255 VLOG(1) << object_path_.value() << ": Profile unregistered";
256 object_path_ = dbus::ObjectPath("");
257 delete this;
260 void BluetoothProfileChromeOS::OnUnregisterProfileError(
261 const std::string& error_name,
262 const std::string& error_message) {
263 // It's okay if the profile didn't exist, it means we never saw an adapter.
264 if (error_name == bluetooth_profile_manager::kErrorDoesNotExist)
265 return;
267 LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: "
268 << error_name << ": " << error_message;
269 object_path_ = dbus::ObjectPath("");
270 delete this;
273 void BluetoothProfileChromeOS::OnCheckValidity(
274 const dbus::ObjectPath& device_path,
275 const BluetoothProfileServiceProvider::Delegate::Options& options,
276 const ConfirmationCallback& callback,
277 scoped_ptr<dbus::FileDescriptor> fd) {
278 VLOG(1) << object_path_.value() << ": Validity check complete";
279 if (!fd->is_valid()) {
280 callback.Run(REJECTED);
281 return;
284 callback.Run(SUCCESS);
286 BluetoothDeviceChromeOS* device =
287 static_cast<BluetoothAdapterChromeOS*>(adapter_.get())->
288 GetDeviceWithPath(device_path);
289 DCHECK(device);
291 scoped_refptr<BluetoothSocket> socket((
292 BluetoothSocketChromeOS::Create(fd.get())));
293 connection_callback_.Run(device, socket);
296 } // namespace chromeos