Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / device / bluetooth / bluetooth_profile_chromeos.cc
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.
4
5 #include "device/bluetooth/bluetooth_profile_chromeos.h"
6
7 #include <string>
8
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
34 using device::BluetoothAdapter;
35 using device::BluetoothAdapterFactory;
36 using device::BluetoothDevice;
37 using device::BluetoothProfile;
38 using device::BluetoothSocket;
39
40 namespace {
41
42 // Check the validity of a file descriptor received from D-Bus. Must be run
43 // on a thread where i/o is permitted.
44 scoped_ptr<dbus::FileDescriptor> CheckValidity(
45     scoped_ptr<dbus::FileDescriptor> fd) {
46   base::ThreadRestrictions::AssertIOAllowed();
47   fd->CheckValidity();
48   return fd.Pass();
49 }
50
51 }  // namespace
52
53
54 namespace chromeos {
55
56 BluetoothProfileChromeOS::BluetoothProfileChromeOS()
57     : weak_ptr_factory_(this) {
58 }
59
60 BluetoothProfileChromeOS::~BluetoothProfileChromeOS() {
61   DCHECK(object_path_.value().empty());
62   DCHECK(profile_.get() == NULL);
63 }
64
65 void BluetoothProfileChromeOS::Init(
66     const std::string& uuid,
67     const device::BluetoothProfile::Options& options,
68     const ProfileCallback& callback) {
69   DCHECK(object_path_.value().empty());
70   DCHECK(profile_.get() == NULL);
71
72   if (!BluetoothDevice::IsUUIDValid(uuid)) {
73     callback.Run(NULL);
74     return;
75   }
76
77   uuid_ = uuid;
78
79   BluetoothProfileManagerClient::Options bluetooth_options;
80   bluetooth_options.name = options.name;
81   bluetooth_options.service = uuid;
82   bluetooth_options.channel = options.channel;
83   bluetooth_options.psm = options.psm;
84   bluetooth_options.require_authentication = options.require_authentication;
85   bluetooth_options.require_authorization = options.require_authorization;
86   bluetooth_options.auto_connect = options.auto_connect;
87   bluetooth_options.version = options.version;
88   bluetooth_options.features = options.features;
89
90   // The object path is relatively meaningless, but has to be unique, so we
91   // use the UUID of the profile.
92   std::string uuid_path;
93   base::ReplaceChars(uuid, ":-", "_", &uuid_path);
94
95   object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" +
96                                   uuid_path);
97
98   dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
99   profile_.reset(BluetoothProfileServiceProvider::Create(
100       system_bus, object_path_, this));
101   DCHECK(profile_.get());
102
103   VLOG(1) << object_path_.value() << ": Register profile";
104   DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
105       RegisterProfile(
106           object_path_,
107           uuid,
108           bluetooth_options,
109           base::Bind(&BluetoothProfileChromeOS::OnRegisterProfile,
110                      weak_ptr_factory_.GetWeakPtr(),
111                      callback),
112           base::Bind(&BluetoothProfileChromeOS::OnRegisterProfileError,
113                      weak_ptr_factory_.GetWeakPtr(),
114                      callback));
115 }
116
117 void BluetoothProfileChromeOS::Unregister() {
118   DCHECK(!object_path_.value().empty());
119   DCHECK(profile_.get());
120
121   profile_.reset();
122
123   VLOG(1) << object_path_.value() << ": Unregister profile";
124   DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
125       UnregisterProfile(
126           object_path_,
127           base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfile,
128                      weak_ptr_factory_.GetWeakPtr()),
129           base::Bind(&BluetoothProfileChromeOS::OnUnregisterProfileError,
130                      weak_ptr_factory_.GetWeakPtr()));
131 }
132
133 void BluetoothProfileChromeOS::SetConnectionCallback(
134     const ConnectionCallback& callback) {
135   connection_callback_ = callback;
136 }
137
138 void BluetoothProfileChromeOS::Release() {
139   VLOG(1) << object_path_.value() << ": Release";
140 }
141
142 void BluetoothProfileChromeOS::NewConnection(
143     const dbus::ObjectPath& device_path,
144     scoped_ptr<dbus::FileDescriptor> fd,
145     const BluetoothProfileServiceProvider::Delegate::Options& options,
146     const ConfirmationCallback& callback) {
147   VLOG(1) << object_path_.value() << ": New connection from device: "
148           << device_path.value();;
149   if (connection_callback_.is_null()) {
150     callback.Run(REJECTED);
151     return;
152   }
153
154   // Punt descriptor validity check to a worker thread where i/o is permitted;
155   // on return we'll fetch the adapter and then call the connection callback.
156   //
157   // base::Passed is used to take ownership of the file descriptor during the
158   // CheckValidity() call and pass that ownership to the GetAdapter() call.
159   base::PostTaskAndReplyWithResult(
160       base::WorkerPool::GetTaskRunner(false).get(),
161       FROM_HERE,
162       base::Bind(&CheckValidity, base::Passed(&fd)),
163       base::Bind(&BluetoothProfileChromeOS::GetAdapter,
164                  weak_ptr_factory_.GetWeakPtr(),
165                  device_path,
166                  options,
167                  callback));
168 }
169
170 void BluetoothProfileChromeOS::RequestDisconnection(
171     const dbus::ObjectPath& device_path,
172     const ConfirmationCallback& callback) {
173   VLOG(1) << object_path_.value() << ": Request disconnection";
174   callback.Run(SUCCESS);
175 }
176
177 void BluetoothProfileChromeOS::Cancel() {
178   VLOG(1) << object_path_.value() << ": Cancel";
179 }
180
181 void BluetoothProfileChromeOS::OnRegisterProfile(
182     const ProfileCallback& callback) {
183   VLOG(1) << object_path_.value() << ": Profile registered";
184   callback.Run(this);
185 }
186
187 void BluetoothProfileChromeOS::OnRegisterProfileError(
188     const ProfileCallback& callback,
189     const std::string& error_name,
190     const std::string& error_message) {
191   LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
192                << error_name << ": " << error_message;
193   callback.Run(NULL);
194
195   Unregister();
196 }
197
198 void BluetoothProfileChromeOS::OnUnregisterProfile() {
199   VLOG(1) << object_path_.value() << ": Profile unregistered";
200   object_path_ = dbus::ObjectPath("");
201   delete this;
202 }
203
204 void BluetoothProfileChromeOS::OnUnregisterProfileError(
205     const std::string& error_name,
206     const std::string& error_message) {
207   LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: "
208                << error_name << ": " << error_message;
209   object_path_ = dbus::ObjectPath("");
210   delete this;
211 }
212
213 void BluetoothProfileChromeOS::GetAdapter(
214       const dbus::ObjectPath& device_path,
215       const BluetoothProfileServiceProvider::Delegate::Options& options,
216       const ConfirmationCallback& callback,
217       scoped_ptr<dbus::FileDescriptor> fd) {
218   VLOG(1) << object_path_.value() << ": Validity check complete";
219   if (!fd->is_valid()) {
220     callback.Run(REJECTED);
221     return;
222   }
223
224   BluetoothAdapterFactory::GetAdapter(
225       base::Bind(&BluetoothProfileChromeOS::OnGetAdapter,
226                  weak_ptr_factory_.GetWeakPtr(),
227                  device_path,
228                  options,
229                  callback,
230                  base::Passed(&fd)));
231 }
232
233 void BluetoothProfileChromeOS::OnGetAdapter(
234     const dbus::ObjectPath& device_path,
235     const BluetoothProfileServiceProvider::Delegate::Options&
236         options,
237     const ConfirmationCallback& callback,
238     scoped_ptr<dbus::FileDescriptor> fd,
239     scoped_refptr<BluetoothAdapter> adapter) {
240   VLOG(1) << object_path_.value() << ": Obtained adapter reference";
241   callback.Run(SUCCESS);
242
243   BluetoothDeviceChromeOS* device =
244       static_cast<BluetoothAdapterChromeOS*>(adapter.get())->
245           GetDeviceWithPath(device_path);
246   DCHECK(device);
247
248   scoped_refptr<BluetoothSocket> socket((
249       BluetoothSocketChromeOS::Create(fd.get())));
250   connection_callback_.Run(device, socket);
251 }
252
253 }  // namespace chromeos