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