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()); |
| 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(); |
| 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 |