OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/bluetooth/bluetooth_socket_chromeos.h" | 5 #include "device/bluetooth/bluetooth_socket_chromeos.h" |
6 | 6 |
7 #include <queue> | |
7 #include <string> | 8 #include <string> |
8 | 9 |
10 #include "base/basictypes.h" | |
11 #include "base/bind.h" | |
12 #include "base/callback.h" | |
9 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/linked_ptr.h" | |
10 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/memory/scoped_ptr.h" | |
11 #include "base/sequenced_task_runner.h" | 17 #include "base/sequenced_task_runner.h" |
18 #include "base/strings/string_util.h" | |
19 #include "base/task_runner_util.h" | |
12 #include "base/threading/thread_restrictions.h" | 20 #include "base/threading/thread_restrictions.h" |
21 #include "base/threading/worker_pool.h" | |
22 #include "chromeos/dbus/bluetooth_device_client.h" | |
23 #include "chromeos/dbus/bluetooth_profile_manager_client.h" | |
24 #include "chromeos/dbus/bluetooth_profile_service_provider.h" | |
25 #include "chromeos/dbus/dbus_thread_manager.h" | |
26 #include "dbus/bus.h" | |
13 #include "dbus/file_descriptor.h" | 27 #include "dbus/file_descriptor.h" |
28 #include "dbus/object_path.h" | |
29 #include "device/bluetooth/bluetooth_adapter.h" | |
30 #include "device/bluetooth/bluetooth_adapter_chromeos.h" | |
31 #include "device/bluetooth/bluetooth_device.h" | |
32 #include "device/bluetooth/bluetooth_device_chromeos.h" | |
14 #include "device/bluetooth/bluetooth_socket.h" | 33 #include "device/bluetooth/bluetooth_socket.h" |
15 #include "device/bluetooth/bluetooth_socket_net.h" | 34 #include "device/bluetooth/bluetooth_socket_net.h" |
16 #include "device/bluetooth/bluetooth_socket_thread.h" | 35 #include "device/bluetooth/bluetooth_socket_thread.h" |
17 #include "net/base/ip_endpoint.h" | 36 #include "net/base/ip_endpoint.h" |
18 #include "net/base/net_errors.h" | 37 #include "net/base/net_errors.h" |
38 #include "third_party/cros_system_api/dbus/service_constants.h" | |
39 | |
40 using device::BluetoothAdapter; | |
41 using device::BluetoothDevice; | |
42 using device::BluetoothSocketThread; | |
43 using device::BluetoothUUID; | |
19 | 44 |
20 namespace { | 45 namespace { |
21 | 46 |
22 const char kSocketAlreadyConnected[] = "Socket is already connected."; | 47 const char kAcceptFailed[] = "Failed to accept connection."; |
48 const char kInvalidUUID[] = "Invalid UUID"; | |
49 const char kSocketNotListening[] = "Socket is not listening."; | |
23 | 50 |
24 } // namespace | 51 } // namespace |
25 | 52 |
26 namespace chromeos { | 53 namespace chromeos { |
27 | 54 |
28 // static | 55 // static |
29 scoped_refptr<BluetoothSocketChromeOS> | 56 scoped_refptr<BluetoothSocketChromeOS> |
30 BluetoothSocketChromeOS::CreateBluetoothSocket( | 57 BluetoothSocketChromeOS::CreateBluetoothSocket( |
31 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 58 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
32 scoped_refptr<device::BluetoothSocketThread> socket_thread, | 59 scoped_refptr<BluetoothSocketThread> socket_thread, |
33 net::NetLog* net_log, | 60 net::NetLog* net_log, |
34 const net::NetLog::Source& source) { | 61 const net::NetLog::Source& source) { |
35 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); | 62 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); |
36 | 63 |
37 return make_scoped_refptr( | 64 return make_scoped_refptr( |
38 new BluetoothSocketChromeOS( | 65 new BluetoothSocketChromeOS( |
39 ui_task_runner, socket_thread, net_log, source)); | 66 ui_task_runner, socket_thread, net_log, source)); |
40 } | 67 } |
41 | 68 |
69 BluetoothSocketChromeOS::AcceptRequest::AcceptRequest() {} | |
70 | |
71 BluetoothSocketChromeOS::AcceptRequest::~AcceptRequest() {} | |
72 | |
73 BluetoothSocketChromeOS::ConnectionRequest::ConnectionRequest() | |
74 : accepting(false), | |
75 cancelled(false) {} | |
76 | |
77 BluetoothSocketChromeOS::ConnectionRequest::~ConnectionRequest() {} | |
78 | |
42 BluetoothSocketChromeOS::BluetoothSocketChromeOS( | 79 BluetoothSocketChromeOS::BluetoothSocketChromeOS( |
43 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 80 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
44 scoped_refptr<device::BluetoothSocketThread> socket_thread, | 81 scoped_refptr<BluetoothSocketThread> socket_thread, |
45 net::NetLog* net_log, | 82 net::NetLog* net_log, |
46 const net::NetLog::Source& source) | 83 const net::NetLog::Source& source) |
47 : BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source) { | 84 : BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source) { |
48 } | 85 } |
49 | 86 |
50 BluetoothSocketChromeOS::~BluetoothSocketChromeOS() { | 87 BluetoothSocketChromeOS::~BluetoothSocketChromeOS() { |
88 DCHECK(object_path_.value().empty()); | |
89 DCHECK(profile_.get() == NULL); | |
90 | |
91 if (adapter_.get()) { | |
92 adapter_->RemoveObserver(this); | |
93 adapter_ = NULL; | |
94 } | |
51 } | 95 } |
52 | 96 |
53 void BluetoothSocketChromeOS::Connect( | 97 void BluetoothSocketChromeOS::Connect( |
54 scoped_ptr<dbus::FileDescriptor> fd, | 98 const BluetoothDeviceChromeOS* device, |
99 const BluetoothUUID& uuid, | |
55 const base::Closure& success_callback, | 100 const base::Closure& success_callback, |
56 const ErrorCompletionCallback& error_callback) { | 101 const ErrorCompletionCallback& error_callback) { |
57 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | 102 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
103 DCHECK (object_path_.value().empty()); | |
104 DCHECK (!profile_.get()); | |
105 | |
106 if (!uuid.IsValid()) { | |
107 error_callback.Run(kInvalidUUID); | |
108 return; | |
109 } | |
110 | |
111 device_address_ = device->GetAddress(); | |
112 device_path_ = device->object_path(); | |
113 uuid_ = uuid; | |
114 options_.reset(new BluetoothProfileManagerClient::Options()); | |
115 | |
116 RegisterProfile(success_callback, error_callback); | |
117 } | |
118 | |
119 void BluetoothSocketChromeOS::Listen( | |
120 scoped_refptr<BluetoothAdapter> adapter, | |
121 SocketType socket_type, | |
122 const BluetoothUUID& uuid, | |
123 int psm_or_channel, | |
124 bool insecure, | |
125 const base::Closure& success_callback, | |
126 const ErrorCompletionCallback& error_callback) { | |
127 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
128 DCHECK (object_path_.value().empty()); | |
129 DCHECK (!profile_.get()); | |
armansito
2014/05/13 19:44:59
nit: no space after DCHECK
keybuk
2014/05/13 20:14:53
Done.
| |
130 | |
131 if (!uuid.IsValid()) { | |
132 error_callback.Run(kInvalidUUID); | |
133 return; | |
134 } | |
135 | |
136 adapter_ = adapter; | |
137 adapter_->AddObserver(this); | |
138 | |
139 uuid_ = uuid; | |
140 options_.reset(new BluetoothProfileManagerClient::Options()); | |
141 | |
142 switch (socket_type) { | |
143 case kRfcomm: | |
144 options_->channel.reset(new uint16( | |
145 psm_or_channel == BluetoothAdapter::kChannelAuto | |
146 ? 0 : psm_or_channel)); | |
147 break; | |
148 case kL2cap: | |
149 options_->psm.reset(new uint16( | |
150 psm_or_channel == BluetoothAdapter::kPsmAuto | |
151 ? 0 : psm_or_channel)); | |
152 break; | |
153 default: | |
154 NOTREACHED(); | |
155 } | |
156 | |
157 if (insecure) | |
158 options_->require_authentication.reset(new bool(false)); | |
159 | |
160 RegisterProfile(success_callback, error_callback); | |
161 } | |
162 | |
163 void BluetoothSocketChromeOS::Close() { | |
164 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
165 | |
166 if (profile_) | |
167 UnregisterProfile(); | |
168 | |
169 if (!device_path_.value().empty()) { | |
170 BluetoothSocketNet::Close(); | |
171 } else { | |
172 DoCloseListening(); | |
173 } | |
174 } | |
175 | |
176 void BluetoothSocketChromeOS::Disconnect(const base::Closure& callback) { | |
177 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
178 | |
179 if (profile_) | |
180 UnregisterProfile(); | |
181 | |
182 if (!device_path_.value().empty()) { | |
183 BluetoothSocketNet::Disconnect(callback); | |
184 } else { | |
185 DoCloseListening(); | |
186 callback.Run(); | |
187 } | |
188 } | |
189 | |
190 void BluetoothSocketChromeOS::Accept( | |
191 const AcceptCompletionCallback& success_callback, | |
192 const ErrorCompletionCallback& error_callback) { | |
193 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
194 | |
195 if (!device_path_.value().empty()) { | |
196 error_callback.Run(kSocketNotListening); | |
197 return; | |
198 } | |
199 | |
200 // Only one pending accept at a time | |
201 if (accept_request_.get()) { | |
202 error_callback.Run(net::ErrorToString(net::ERR_IO_PENDING)); | |
203 return; | |
204 } | |
205 | |
206 accept_request_.reset(new AcceptRequest); | |
207 accept_request_->success_callback = success_callback; | |
208 accept_request_->error_callback = error_callback; | |
209 | |
210 if (connection_request_queue_.size() >= 1) { | |
211 AcceptConnectionRequest(); | |
212 } | |
213 } | |
214 | |
215 void BluetoothSocketChromeOS::RegisterProfile( | |
216 const base::Closure& success_callback, | |
217 const ErrorCompletionCallback& error_callback) { | |
218 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
219 DCHECK(object_path_.value().empty()); | |
220 DCHECK(!profile_.get()); | |
221 | |
222 // The object path is relatively meaningless, but has to be unique, so for | |
223 // connecting profiles use a combination of the device address and profile | |
224 // UUID. | |
225 std::string device_address_path, uuid_path; | |
226 base::ReplaceChars(device_address_, ":-", "_", &device_address_path); | |
227 base::ReplaceChars(uuid_.canonical_value(), ":-", "_", &uuid_path); | |
228 if (!device_address_path.empty()) { | |
229 object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" + | |
230 device_address_path + "/" + uuid_path); | |
231 } else { | |
232 object_path_ = dbus::ObjectPath("/org/chromium/bluetooth_profile/" + | |
233 uuid_path); | |
234 } | |
235 | |
236 // Create the service provider for the profile object. | |
237 dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); | |
238 profile_.reset(BluetoothProfileServiceProvider::Create( | |
239 system_bus, object_path_, this)); | |
240 DCHECK(profile_.get()); | |
241 | |
242 // Before reaching out to the Bluetooth Daemon to register a listening socket, | |
243 // make sure it's actually running. If not, report success and carry on; | |
244 // the profile will be registered when the daemon becomes available. | |
245 if (adapter_ && !adapter_->IsPresent()) { | |
246 VLOG(1) << object_path_.value() << ": Delaying profile registration."; | |
247 success_callback.Run(); | |
248 return; | |
249 } | |
250 | |
251 VLOG(1) << object_path_.value() << ": Registering profile."; | |
252 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> | |
253 RegisterProfile( | |
254 object_path_, | |
255 uuid_.canonical_value(), | |
256 *options_, | |
257 base::Bind(&BluetoothSocketChromeOS::OnRegisterProfile, | |
258 this, | |
259 success_callback, | |
260 error_callback), | |
261 base::Bind(&BluetoothSocketChromeOS::OnRegisterProfileError, | |
262 this, | |
263 error_callback)); | |
264 } | |
265 | |
266 void BluetoothSocketChromeOS::OnRegisterProfile( | |
267 const base::Closure& success_callback, | |
268 const ErrorCompletionCallback& error_callback) { | |
269 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
270 if (!device_path_.value().empty()) { | |
271 VLOG(1) << object_path_.value() << ": Profile registered, connecting to " | |
272 << device_path_.value(); | |
273 | |
274 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> | |
275 ConnectProfile( | |
276 device_path_, | |
277 uuid_.canonical_value(), | |
278 base::Bind( | |
279 &BluetoothSocketChromeOS::OnConnectProfile, | |
280 this, | |
281 success_callback), | |
282 base::Bind( | |
283 &BluetoothSocketChromeOS::OnConnectProfileError, | |
284 this, | |
285 error_callback)); | |
286 } else { | |
287 VLOG(1) << object_path_.value() << ": Profile registered."; | |
288 success_callback.Run(); | |
289 } | |
290 } | |
291 | |
292 void BluetoothSocketChromeOS::OnRegisterProfileError( | |
293 const ErrorCompletionCallback& error_callback, | |
294 const std::string& error_name, | |
295 const std::string& error_message) { | |
296 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
297 LOG(WARNING) << object_path_.value() << ": Failed to register profile: " | |
298 << error_name << ": " << error_message; | |
299 error_callback.Run(error_message); | |
300 } | |
301 | |
302 void BluetoothSocketChromeOS::OnConnectProfile( | |
303 const base::Closure& success_callback) { | |
304 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
305 VLOG(1) << object_path_.value() << ": Profile connected."; | |
306 UnregisterProfile(); | |
armansito
2014/05/13 19:44:59
Is the call to UnregisterProfile here intended?
keybuk
2014/05/13 20:03:53
Yes, the connection has been accepted, there is no
| |
307 success_callback.Run(); | |
308 } | |
309 | |
310 void BluetoothSocketChromeOS::OnConnectProfileError( | |
311 const ErrorCompletionCallback& error_callback, | |
312 const std::string& error_name, | |
313 const std::string& error_message) { | |
314 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
315 LOG(WARNING) << object_path_.value() << ": Failed to connect profile: " | |
316 << error_name << ": " << error_message; | |
317 UnregisterProfile(); | |
318 error_callback.Run(error_message); | |
319 } | |
320 | |
321 void BluetoothSocketChromeOS::AdapterPresentChanged(BluetoothAdapter* adapter, | |
322 bool present) { | |
323 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
324 DCHECK(!object_path_.value().empty()); | |
325 DCHECK(profile_.get()); | |
326 | |
327 if (!present) | |
328 return; | |
329 | |
330 VLOG(1) << object_path_.value() << ": Re-register profile."; | |
331 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> | |
332 RegisterProfile( | |
333 object_path_, | |
334 uuid_.canonical_value(), | |
335 *options_, | |
336 base::Bind(&BluetoothSocketChromeOS::OnInternalRegisterProfile, | |
337 this), | |
338 base::Bind(&BluetoothSocketChromeOS::OnInternalRegisterProfileError, | |
339 this)); | |
340 } | |
341 | |
342 void BluetoothSocketChromeOS::OnInternalRegisterProfile() { | |
343 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
344 | |
345 VLOG(1) << object_path_.value() << ": Profile re-registered"; | |
346 } | |
347 | |
348 void BluetoothSocketChromeOS::OnInternalRegisterProfileError( | |
349 const std::string& error_name, | |
350 const std::string& error_message) { | |
351 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
352 | |
353 // It's okay if the profile already exists, it means we registered it on | |
354 // initialization. | |
355 if (error_name == bluetooth_profile_manager::kErrorAlreadyExists) | |
356 return; | |
357 | |
358 LOG(WARNING) << object_path_.value() << ": Failed to re-register profile: " | |
359 << error_name << ": " << error_message; | |
360 } | |
361 | |
362 void BluetoothSocketChromeOS::Released() { | |
363 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
364 VLOG(1) << object_path_.value() << ": Release"; | |
365 } | |
366 | |
367 void BluetoothSocketChromeOS::NewConnection( | |
368 const dbus::ObjectPath& device_path, | |
369 scoped_ptr<dbus::FileDescriptor> fd, | |
370 const BluetoothProfileServiceProvider::Delegate::Options& options, | |
371 const ConfirmationCallback& callback) { | |
372 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
373 VLOG(1) << object_path_.value() << ": New connection from device: " | |
374 << device_path.value(); | |
375 | |
376 if (!device_path_.value().empty()) { | |
377 DCHECK(device_path_ == device_path); | |
378 | |
379 socket_thread()->task_runner()->PostTask( | |
380 FROM_HERE, | |
381 base::Bind( | |
382 &BluetoothSocketChromeOS::DoNewConnection, | |
383 this, | |
384 device_path_, | |
385 base::Passed(&fd), | |
386 options, | |
387 callback)); | |
388 } else { | |
389 linked_ptr<ConnectionRequest> request(new ConnectionRequest()); | |
390 request->device_path = device_path; | |
391 request->fd = fd.Pass(); | |
392 request->options = options; | |
393 request->callback = callback; | |
394 | |
395 connection_request_queue_.push(request); | |
396 VLOG(1) << object_path_.value() << ": Connection is now pending."; | |
397 if (accept_request_) { | |
398 AcceptConnectionRequest(); | |
399 } | |
400 } | |
401 } | |
402 | |
403 void BluetoothSocketChromeOS::RequestDisconnection( | |
404 const dbus::ObjectPath& device_path, | |
405 const ConfirmationCallback& callback) { | |
406 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
407 VLOG(1) << object_path_.value() << ": Request disconnection"; | |
408 callback.Run(SUCCESS); | |
409 } | |
410 | |
411 void BluetoothSocketChromeOS::Cancel() { | |
412 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
413 VLOG(1) << object_path_.value() << ": Cancel"; | |
414 | |
415 if (!connection_request_queue_.size()) | |
416 return; | |
417 | |
418 // If the front request is being accepted mark it as cancelled, otherwise | |
419 // just pop it from the queue. | |
420 linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); | |
421 if (!request->accepting) { | |
422 request->cancelled = true; | |
423 } else { | |
424 connection_request_queue_.pop(); | |
425 } | |
426 } | |
427 | |
428 void BluetoothSocketChromeOS::AcceptConnectionRequest() { | |
429 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
430 DCHECK(accept_request_.get()); | |
431 DCHECK(connection_request_queue_.size() >= 1); | |
432 | |
433 VLOG(1) << object_path_.value() << ": Accepting pending connection."; | |
434 | |
435 linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); | |
436 request->accepting = true; | |
437 | |
438 BluetoothDeviceChromeOS* device = | |
439 static_cast<BluetoothAdapterChromeOS*>(adapter_.get())-> | |
440 GetDeviceWithPath(request->device_path); | |
441 DCHECK(device); | |
442 | |
443 scoped_refptr<BluetoothSocketChromeOS> client_socket = | |
444 BluetoothSocketChromeOS::CreateBluetoothSocket( | |
445 ui_task_runner(), | |
446 socket_thread(), | |
447 net_log(), | |
448 source()); | |
449 | |
450 client_socket->device_address_ = device->GetAddress(); | |
451 client_socket->device_path_ = request->device_path; | |
452 client_socket->uuid_ = uuid_; | |
58 | 453 |
59 socket_thread()->task_runner()->PostTask( | 454 socket_thread()->task_runner()->PostTask( |
60 FROM_HERE, | 455 FROM_HERE, |
61 base::Bind( | 456 base::Bind( |
62 &BluetoothSocketChromeOS::DoConnect, | 457 &BluetoothSocketChromeOS::DoNewConnection, |
63 this, | 458 client_socket, |
64 base::Passed(&fd), | 459 request->device_path, |
65 base::Bind(&BluetoothSocketChromeOS::PostSuccess, | 460 base::Passed(&request->fd), |
461 request->options, | |
462 base::Bind(&BluetoothSocketChromeOS::OnNewConnection, | |
66 this, | 463 this, |
67 success_callback), | 464 client_socket, |
68 base::Bind(&BluetoothSocketChromeOS::PostErrorCompletion, | 465 request->callback))); |
69 this, | 466 } |
70 error_callback))); | 467 |
71 } | 468 void BluetoothSocketChromeOS::DoNewConnection( |
72 | 469 const dbus::ObjectPath& device_path, |
73 void BluetoothSocketChromeOS::Accept( | |
74 const AcceptCompletionCallback& success_callback, | |
75 const ErrorCompletionCallback& error_callback) { | |
76 NOTIMPLEMENTED(); | |
77 } | |
78 | |
79 void BluetoothSocketChromeOS::DoConnect( | |
80 scoped_ptr<dbus::FileDescriptor> fd, | 470 scoped_ptr<dbus::FileDescriptor> fd, |
81 const base::Closure& success_callback, | 471 const BluetoothProfileServiceProvider::Delegate::Options& options, |
82 const ErrorCompletionCallback& error_callback) { | 472 const ConfirmationCallback& callback) { |
83 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); | 473 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
84 base::ThreadRestrictions::AssertIOAllowed(); | 474 base::ThreadRestrictions::AssertIOAllowed(); |
85 DCHECK(fd->is_valid()); | 475 fd->CheckValidity(); |
476 | |
477 VLOG(1) << object_path_.value() << ": Validity check complete."; | |
478 if (!fd->is_valid()) { | |
479 ui_task_runner()->PostTask(FROM_HERE, | |
480 base::Bind(callback, REJECTED));; | |
481 return; | |
482 } | |
86 | 483 |
87 if (tcp_socket()) { | 484 if (tcp_socket()) { |
88 error_callback.Run(kSocketAlreadyConnected); | 485 LOG(WARNING) << object_path_.value() << ": Already connected"; |
89 return; | 486 ui_task_runner()->PostTask(FROM_HERE, |
90 } | 487 base::Bind(callback, REJECTED));; |
91 | 488 return; |
489 } | |
490 | |
92 ResetTCPSocket(); | 491 ResetTCPSocket(); |
93 | 492 |
94 // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the | 493 // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the |
95 // TCPSocket implementation does not actually require one. | 494 // TCPSocket implementation does not actually require one. |
96 int net_result = tcp_socket()->AdoptConnectedSocket(fd->value(), | 495 int net_result = tcp_socket()->AdoptConnectedSocket(fd->value(), |
97 net::IPEndPoint()); | 496 net::IPEndPoint()); |
98 if (net_result != net::OK) { | 497 if (net_result != net::OK) { |
99 error_callback.Run("Error connecting to socket: " + | 498 LOG(WARNING) << object_path_.value() << ": Error adopting socket: " |
100 std::string(net::ErrorToString(net_result))); | 499 << std::string(net::ErrorToString(net_result)); |
500 ui_task_runner()->PostTask(FROM_HERE, | |
501 base::Bind(callback, REJECTED));; | |
101 return; | 502 return; |
102 } | 503 } |
103 | 504 |
104 fd->TakeValue(); | 505 fd->TakeValue(); |
105 success_callback.Run(); | 506 ui_task_runner()->PostTask(FROM_HERE, |
507 base::Bind(callback, SUCCESS));; | |
508 } | |
509 | |
510 void BluetoothSocketChromeOS::OnNewConnection( | |
511 scoped_refptr<BluetoothSocket> socket, | |
512 const ConfirmationCallback& callback, | |
513 Status status) { | |
514 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
515 DCHECK(accept_request_.get()); | |
516 DCHECK(connection_request_queue_.size() >= 1); | |
517 | |
518 linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); | |
519 if (status == SUCCESS && !request->cancelled) { | |
520 BluetoothDeviceChromeOS* device = | |
521 static_cast<BluetoothAdapterChromeOS*>(adapter_.get())-> | |
522 GetDeviceWithPath(request->device_path); | |
523 DCHECK(device); | |
524 | |
525 accept_request_->success_callback.Run(device, socket); | |
526 } else { | |
527 accept_request_->error_callback.Run(kAcceptFailed); | |
528 } | |
529 | |
530 accept_request_.reset(NULL); | |
531 connection_request_queue_.pop(); | |
532 | |
533 callback.Run(status); | |
534 } | |
535 | |
536 void BluetoothSocketChromeOS::DoCloseListening() { | |
537 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
538 | |
539 if (accept_request_) { | |
540 accept_request_->error_callback.Run( | |
541 net::ErrorToString(net::ERR_CONNECTION_CLOSED)); | |
542 accept_request_.reset(NULL); | |
543 } | |
544 | |
545 while (connection_request_queue_.size() > 0) { | |
546 linked_ptr<ConnectionRequest> request = connection_request_queue_.front(); | |
547 request->callback.Run(REJECTED); | |
548 connection_request_queue_.pop(); | |
549 } | |
550 } | |
551 | |
552 void BluetoothSocketChromeOS::UnregisterProfile() { | |
553 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); | |
554 DCHECK(!object_path_.value().empty()); | |
555 DCHECK(profile_.get()); | |
556 | |
557 VLOG(1) << object_path_.value() << ": Unregister profile"; | |
558 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()-> | |
559 UnregisterProfile( | |
560 object_path_, | |
561 base::Bind(&BluetoothSocketChromeOS::OnUnregisterProfile, | |
562 this, | |
563 object_path_), | |
564 base::Bind(&BluetoothSocketChromeOS::OnUnregisterProfileError, | |
565 this, | |
566 object_path_)); | |
567 | |
568 profile_.reset(); | |
569 object_path_ = dbus::ObjectPath(""); | |
570 } | |
571 | |
572 void BluetoothSocketChromeOS::OnUnregisterProfile( | |
573 const dbus::ObjectPath& object_path) { | |
574 VLOG(1) << object_path.value() << ": Profile unregistered"; | |
575 } | |
576 | |
577 void BluetoothSocketChromeOS::OnUnregisterProfileError( | |
578 const dbus::ObjectPath& object_path, | |
579 const std::string& error_name, | |
580 const std::string& error_message) { | |
581 // It's okay if the profile doesn't exist, it means we haven't registered it | |
582 // yet. | |
583 if (error_name == bluetooth_profile_manager::kErrorDoesNotExist) | |
584 return; | |
585 | |
586 LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: " | |
587 << error_name << ": " << error_message; | |
106 } | 588 } |
107 | 589 |
108 } // namespace chromeos | 590 } // namespace chromeos |
OLD | NEW |