OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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_experimental_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.h" | |
16 #include "base/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/dbus_thread_manager.h" | |
21 #include "chromeos/dbus/experimental_bluetooth_profile_manager_client.h" | |
22 #include "chromeos/dbus/experimental_bluetooth_profile_service_provider.h" | |
23 #include "dbus/bus.h" | |
24 #include "dbus/file_descriptor.h" | |
25 #include "dbus/object_path.h" | |
26 #include "device/bluetooth/bluetooth_adapter_experimental_chromeos.h" | |
27 #include "device/bluetooth/bluetooth_adapter_factory.h" | |
28 #include "device/bluetooth/bluetooth_device.h" | |
29 #include "device/bluetooth/bluetooth_device_experimental_chromeos.h" | |
30 #include "device/bluetooth/bluetooth_profile.h" | |
31 #include "device/bluetooth/bluetooth_socket.h" | |
32 #include "device/bluetooth/bluetooth_socket_experimental_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 recieved from D-Bus. Must be run | |
youngki
2013/05/02 22:02:55
s/recieved/received/
| |
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 BluetoothProfileExperimentalChromeOS::BluetoothProfileExperimentalChromeOS() | |
57 : weak_ptr_factory_(this) { | |
58 } | |
59 | |
60 BluetoothProfileExperimentalChromeOS::~BluetoothProfileExperimentalChromeOS() { | |
61 DCHECK(object_path_.value().empty()); | |
62 DCHECK(profile_.get() == NULL); | |
63 } | |
64 | |
65 void BluetoothProfileExperimentalChromeOS::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 ExperimentalBluetoothProfileManagerClient::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 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(ExperimentalBluetoothProfileServiceProvider::Create( | |
100 system_bus, object_path_, this)); | |
101 DCHECK(profile_.get()); | |
102 | |
103 VLOG(1) << object_path_.value() << ": Register profile"; | |
104 DBusThreadManager::Get()->GetExperimentalBluetoothProfileManagerClient()-> | |
105 RegisterProfile( | |
106 object_path_, | |
107 uuid, | |
108 bluetooth_options, | |
109 base::Bind( | |
110 &BluetoothProfileExperimentalChromeOS::OnRegisterProfile, | |
111 weak_ptr_factory_.GetWeakPtr(), | |
112 callback), | |
113 base::Bind( | |
114 &BluetoothProfileExperimentalChromeOS::OnRegisterProfileError, | |
115 weak_ptr_factory_.GetWeakPtr(), | |
116 callback)); | |
117 } | |
118 | |
119 void BluetoothProfileExperimentalChromeOS::Unregister() { | |
120 DCHECK(!object_path_.value().empty()); | |
121 DCHECK(profile_.get()); | |
122 | |
123 profile_.reset(); | |
124 | |
125 VLOG(1) << object_path_.value() << ": Unregister profile"; | |
126 DBusThreadManager::Get()->GetExperimentalBluetoothProfileManagerClient()-> | |
127 UnregisterProfile( | |
128 object_path_, | |
129 base::Bind( | |
130 &BluetoothProfileExperimentalChromeOS::OnUnregisterProfile, | |
131 weak_ptr_factory_.GetWeakPtr()), | |
132 base::Bind( | |
133 &BluetoothProfileExperimentalChromeOS::OnUnregisterProfileError, | |
134 weak_ptr_factory_.GetWeakPtr())); | |
135 } | |
136 | |
137 void BluetoothProfileExperimentalChromeOS::SetConnectionCallback( | |
138 const ConnectionCallback& callback) { | |
139 connection_callback_ = callback; | |
140 } | |
141 | |
142 void BluetoothProfileExperimentalChromeOS::Release() { | |
143 VLOG(1) << object_path_.value() << ": Release"; | |
144 } | |
145 | |
146 void BluetoothProfileExperimentalChromeOS::NewConnection( | |
147 const dbus::ObjectPath& device_path, | |
148 scoped_ptr<dbus::FileDescriptor> fd, | |
149 const ExperimentalBluetoothProfileServiceProvider::Delegate::Options& | |
150 options, | |
151 const ConfirmationCallback& callback) { | |
152 VLOG(1) << object_path_.value() << ": New connection from device: " | |
153 << device_path.value();; | |
154 if (connection_callback_.is_null()) { | |
155 callback.Run(REJECTED); | |
156 return; | |
157 } | |
158 | |
159 // Punt descriptor validity check to a worker thread where i/o is permitted; | |
160 // on return we'll fetch the adapter and then call the connection callback. | |
161 // | |
162 // base::Passed is used to take ownership of the file descriptor during the | |
163 // CheckValidity() call and pass that ownership to the GetAdapter() call. | |
164 base::PostTaskAndReplyWithResult( | |
165 base::WorkerPool::GetTaskRunner(false), | |
166 FROM_HERE, | |
167 base::Bind(&CheckValidity, base::Passed(&fd)), | |
168 base::Bind(&BluetoothProfileExperimentalChromeOS::GetAdapter, | |
169 weak_ptr_factory_.GetWeakPtr(), | |
170 device_path, | |
171 options, | |
172 callback)); | |
173 } | |
174 | |
175 void BluetoothProfileExperimentalChromeOS::RequestDisconnection( | |
176 const dbus::ObjectPath& device_path, | |
177 const ConfirmationCallback& callback) { | |
178 VLOG(1) << object_path_.value() << ": Request disconnection"; | |
179 callback.Run(SUCCESS); | |
180 } | |
181 | |
182 void BluetoothProfileExperimentalChromeOS::Cancel() { | |
183 VLOG(1) << object_path_.value() << ": Cancel"; | |
184 } | |
185 | |
186 void BluetoothProfileExperimentalChromeOS::OnRegisterProfile( | |
187 const ProfileCallback& callback) { | |
188 VLOG(1) << object_path_.value() << ": Profile registered"; | |
189 callback.Run(this); | |
190 } | |
191 | |
192 void BluetoothProfileExperimentalChromeOS::OnRegisterProfileError( | |
193 const ProfileCallback& callback, | |
194 const std::string& error_name, | |
195 const std::string& error_message) { | |
196 LOG(WARNING) << object_path_.value() << ": Failed to register profile: " | |
197 << error_name << ": " << error_message; | |
198 callback.Run(NULL); | |
199 | |
200 Unregister(); | |
201 } | |
202 | |
203 void BluetoothProfileExperimentalChromeOS::OnUnregisterProfile() { | |
204 VLOG(1) << object_path_.value() << ": Profile unregistered"; | |
205 object_path_ = dbus::ObjectPath(""); | |
206 delete this; | |
207 } | |
208 | |
209 void BluetoothProfileExperimentalChromeOS::OnUnregisterProfileError( | |
210 const std::string& error_name, | |
211 const std::string& error_message) { | |
212 LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: " | |
213 << error_name << ": " << error_message; | |
214 object_path_ = dbus::ObjectPath(""); | |
215 delete this; | |
216 } | |
217 | |
218 void BluetoothProfileExperimentalChromeOS::GetAdapter( | |
219 const dbus::ObjectPath& device_path, | |
220 const ExperimentalBluetoothProfileServiceProvider::Delegate::Options& | |
221 options, | |
222 const ConfirmationCallback& callback, | |
223 scoped_ptr<dbus::FileDescriptor> fd) { | |
224 VLOG(1) << object_path_.value() << ": Validity check complete"; | |
225 if (!fd->is_valid()) { | |
226 callback.Run(REJECTED); | |
227 return; | |
228 } | |
229 | |
230 BluetoothAdapterFactory::GetAdapter( | |
231 base::Bind(&BluetoothProfileExperimentalChromeOS::OnGetAdapter, | |
232 weak_ptr_factory_.GetWeakPtr(), | |
233 device_path, | |
234 options, | |
235 callback, | |
236 base::Passed(&fd))); | |
237 } | |
238 | |
239 void BluetoothProfileExperimentalChromeOS::OnGetAdapter( | |
240 const dbus::ObjectPath& device_path, | |
241 const ExperimentalBluetoothProfileServiceProvider::Delegate::Options& | |
242 options, | |
243 const ConfirmationCallback& callback, | |
244 scoped_ptr<dbus::FileDescriptor> fd, | |
245 scoped_refptr<BluetoothAdapter> adapter) { | |
246 VLOG(1) << object_path_.value() << ": Obtained adapter reference"; | |
247 callback.Run(SUCCESS); | |
248 | |
249 BluetoothDeviceExperimentalChromeOS* device = | |
250 static_cast<BluetoothAdapterExperimentalChromeOS*>(adapter.get())-> | |
251 GetDeviceWithPath(device_path); | |
252 DCHECK(device); | |
253 | |
254 scoped_refptr<BluetoothSocket> socket(( | |
255 BluetoothSocketExperimentalChromeOS::Create(fd.get()))); | |
256 connection_callback_.Run(device, socket); | |
257 } | |
258 | |
259 } // namespace chromeos | |
OLD | NEW |