Upstream version 6.35.121.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 #include "third_party/cros_system_api/dbus/service_constants.h"
34
35 using device::BluetoothAdapter;
36 using device::BluetoothAdapterFactory;
37 using device::BluetoothDevice;
38 using device::BluetoothProfile;
39 using device::BluetoothSocket;
40
41 namespace {
42
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();
50 }
51
52 }  // namespace
53
54
55 namespace chromeos {
56
57 BluetoothProfileChromeOS::BluetoothProfileChromeOS()
58     : weak_ptr_factory_(this) {
59 }
60
61 BluetoothProfileChromeOS::~BluetoothProfileChromeOS() {
62   DCHECK(object_path_.value().empty());
63   DCHECK(profile_.get() == NULL);
64
65   if (adapter_.get()) {
66     adapter_->RemoveObserver(this);
67     adapter_ = NULL;
68   }
69 }
70
71 void BluetoothProfileChromeOS::Init(
72     const std::string& uuid,
73     const device::BluetoothProfile::Options& options,
74     const ProfileCallback& callback) {
75   DCHECK(object_path_.value().empty());
76   DCHECK(profile_.get() == NULL);
77
78   if (!BluetoothDevice::IsUUIDValid(uuid)) {
79     callback.Run(NULL);
80     return;
81   }
82
83   uuid_ = uuid;
84
85   options_.name = options.name;
86   options_.service = uuid;
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;
94
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, ":-", "_", &uuid_path);
99
100   object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" +
101                                   uuid_path);
102
103   dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
104   profile_.reset(BluetoothProfileServiceProvider::Create(
105       system_bus, object_path_, this));
106   DCHECK(profile_.get());
107
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));
114 }
115
116 void BluetoothProfileChromeOS::Unregister() {
117   DCHECK(!object_path_.value().empty());
118   DCHECK(profile_.get());
119
120   profile_.reset();
121
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()));
130 }
131
132 void BluetoothProfileChromeOS::SetConnectionCallback(
133     const ConnectionCallback& callback) {
134   connection_callback_ = callback;
135 }
136
137 void BluetoothProfileChromeOS::AdapterPresentChanged(BluetoothAdapter* adapter,
138                                                      bool present) {
139   if (!present)
140     return;
141
142   VLOG(1) << object_path_.value() << ": Register profile";
143   DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
144       RegisterProfile(
145           object_path_,
146           uuid_,
147           options_,
148           base::Bind(&BluetoothProfileChromeOS::OnInternalRegisterProfile,
149                      weak_ptr_factory_.GetWeakPtr()),
150           base::Bind(&BluetoothProfileChromeOS::OnInternalRegisterProfileError,
151                      weak_ptr_factory_.GetWeakPtr()));
152 }
153
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);
160
161   VLOG(1) << object_path_.value() << ": Register profile";
162   DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->
163       RegisterProfile(
164           object_path_,
165           uuid_,
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));
173 }
174
175 void BluetoothProfileChromeOS::Release() {
176   VLOG(1) << object_path_.value() << ": Release";
177 }
178
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;
189   }
190
191   // Punt descriptor validity check to a worker thread where i/o is permitted;
192   // on return we'll call the connection callback.
193   //
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));
205 }
206
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);
212 }
213
214 void BluetoothProfileChromeOS::Cancel() {
215   VLOG(1) << object_path_.value() << ": Cancel";
216 }
217
218 void BluetoothProfileChromeOS::OnInternalRegisterProfile() {
219   VLOG(1) << object_path_.value() << ": Profile registered";
220 }
221
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;
229
230   LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
231                << error_name << ": " << error_message;
232 }
233
234 void BluetoothProfileChromeOS::OnRegisterProfile(
235     const ProfileCallback& callback) {
236   VLOG(1) << object_path_.value() << ": Profile registered";
237   callback.Run(this);
238 }
239
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;
248
249   LOG(WARNING) << object_path_.value() << ": Failed to register profile: "
250                << error_name << ": " << error_message;
251   callback.Run(NULL);
252 }
253
254 void BluetoothProfileChromeOS::OnUnregisterProfile() {
255   VLOG(1) << object_path_.value() << ": Profile unregistered";
256   object_path_ = dbus::ObjectPath("");
257   delete this;
258 }
259
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;
266
267   LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: "
268                << error_name << ": " << error_message;
269   object_path_ = dbus::ObjectPath("");
270   delete this;
271 }
272
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;
282   }
283
284   callback.Run(SUCCESS);
285
286   BluetoothDeviceChromeOS* device =
287       static_cast<BluetoothAdapterChromeOS*>(adapter_.get())->
288           GetDeviceWithPath(device_path);
289   DCHECK(device);
290
291   scoped_refptr<BluetoothSocket> socket((
292       BluetoothSocketChromeOS::Create(fd.get())));
293   connection_callback_.Run(device, socket);
294 }
295
296 }  // namespace chromeos