1// Copyright 2014 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 "extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h" 6 7#include <stdint.h> 8 9#include "content/public/browser/browser_context.h" 10#include "content/public/browser/browser_thread.h" 11#include "device/bluetooth/bluetooth_adapter.h" 12#include "device/bluetooth/bluetooth_adapter_factory.h" 13#include "device/bluetooth/bluetooth_device.h" 14#include "device/bluetooth/bluetooth_socket.h" 15#include "extensions/browser/api/bluetooth_socket/bluetooth_api_socket.h" 16#include "extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h" 17#include "extensions/common/api/bluetooth/bluetooth_manifest_data.h" 18#include "extensions/common/permissions/permissions_data.h" 19#include "net/base/io_buffer.h" 20 21using content::BrowserThread; 22using extensions::BluetoothApiSocket; 23using extensions::core_api::bluetooth_socket::ListenOptions; 24using extensions::core_api::bluetooth_socket::SocketInfo; 25using extensions::core_api::bluetooth_socket::SocketProperties; 26 27namespace extensions { 28namespace core_api { 29 30namespace { 31 32const char kDeviceNotFoundError[] = "Device not found"; 33const char kInvalidPsmError[] = "Invalid PSM"; 34const char kInvalidUuidError[] = "Invalid UUID"; 35const char kPermissionDeniedError[] = "Permission denied"; 36const char kSocketNotFoundError[] = "Socket not found"; 37 38linked_ptr<SocketInfo> CreateSocketInfo(int socket_id, 39 BluetoothApiSocket* socket) { 40 DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId)); 41 linked_ptr<SocketInfo> socket_info(new SocketInfo()); 42 // This represents what we know about the socket, and does not call through 43 // to the system. 44 socket_info->socket_id = socket_id; 45 if (socket->name()) { 46 socket_info->name.reset(new std::string(*socket->name())); 47 } 48 socket_info->persistent = socket->persistent(); 49 if (socket->buffer_size() > 0) { 50 socket_info->buffer_size.reset(new int(socket->buffer_size())); 51 } 52 socket_info->paused = socket->paused(); 53 socket_info->connected = socket->IsConnected(); 54 55 if (socket->IsConnected()) 56 socket_info->address.reset(new std::string(socket->device_address())); 57 socket_info->uuid.reset(new std::string(socket->uuid().canonical_value())); 58 59 return socket_info; 60} 61 62void SetSocketProperties(BluetoothApiSocket* socket, 63 SocketProperties* properties) { 64 if (properties->name.get()) { 65 socket->set_name(*properties->name.get()); 66 } 67 if (properties->persistent.get()) { 68 socket->set_persistent(*properties->persistent.get()); 69 } 70 if (properties->buffer_size.get()) { 71 // buffer size is validated when issuing the actual Recv operation 72 // on the socket. 73 socket->set_buffer_size(*properties->buffer_size.get()); 74 } 75} 76 77BluetoothSocketEventDispatcher* GetSocketEventDispatcher( 78 content::BrowserContext* browser_context) { 79 BluetoothSocketEventDispatcher* socket_event_dispatcher = 80 BluetoothSocketEventDispatcher::Get(browser_context); 81 DCHECK(socket_event_dispatcher) 82 << "There is no socket event dispatcher. " 83 "If this assertion is failing during a test, then it is likely that " 84 "TestExtensionSystem is failing to provide an instance of " 85 "BluetoothSocketEventDispatcher."; 86 return socket_event_dispatcher; 87} 88 89// Returns |true| if |psm| is a valid PSM. 90// Per the Bluetooth specification, the PSM field must be at least two octets in 91// length, with least significant bit of the least significant octet equal to 92// '1' and the least significant bit of the most significant octet equal to '0'. 93bool IsValidPsm(int psm) { 94 if (psm <= 0) 95 return false; 96 97 std::vector<int16_t> octets; 98 while (psm > 0) { 99 octets.push_back(psm & 0xFF); 100 psm = psm >> 8; 101 } 102 103 if (octets.size() < 2U) 104 return false; 105 106 // The least significant bit of the least significant octet must be '1'. 107 if ((octets.front() & 0x01) != 1) 108 return false; 109 110 // The least significant bit of the most significant octet must be '0'. 111 if ((octets.back() & 0x01) != 0) 112 return false; 113 114 return true; 115} 116 117} // namespace 118 119BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {} 120 121BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {} 122 123bool BluetoothSocketAsyncApiFunction::RunAsync() { 124 if (!PrePrepare() || !Prepare()) { 125 return false; 126 } 127 AsyncWorkStart(); 128 return true; 129} 130 131bool BluetoothSocketAsyncApiFunction::PrePrepare() { 132 if (!BluetoothManifestData::CheckSocketPermitted(extension())) { 133 error_ = kPermissionDeniedError; 134 return false; 135 } 136 137 manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context()); 138 DCHECK(manager_) 139 << "There is no socket manager. " 140 "If this assertion is failing during a test, then it is likely that " 141 "TestExtensionSystem is failing to provide an instance of " 142 "ApiResourceManager<BluetoothApiSocket>."; 143 return manager_ != NULL; 144} 145 146bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); } 147 148void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() { 149 SendResponse(Respond()); 150} 151 152void BluetoothSocketAsyncApiFunction::Work() {} 153 154void BluetoothSocketAsyncApiFunction::AsyncWorkStart() { 155 Work(); 156 AsyncWorkCompleted(); 157} 158 159int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) { 160 return manager_->Add(socket); 161} 162 163content::BrowserThread::ID 164BluetoothSocketAsyncApiFunction::work_thread_id() const { 165 return BluetoothApiSocket::kThreadId; 166} 167 168BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket( 169 int api_resource_id) { 170 return manager_->Get(extension_id(), api_resource_id); 171} 172 173void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) { 174 manager_->Remove(extension_id(), api_resource_id); 175} 176 177base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() { 178 return manager_->GetResourceIds(extension_id()); 179} 180 181BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {} 182 183BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {} 184 185bool BluetoothSocketCreateFunction::Prepare() { 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 187 188 params_ = bluetooth_socket::Create::Params::Create(*args_); 189 EXTENSION_FUNCTION_VALIDATE(params_.get()); 190 return true; 191} 192 193void BluetoothSocketCreateFunction::Work() { 194 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 195 196 BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id()); 197 198 bluetooth_socket::SocketProperties* properties = 199 params_.get()->properties.get(); 200 if (properties) { 201 SetSocketProperties(socket, properties); 202 } 203 204 bluetooth_socket::CreateInfo create_info; 205 create_info.socket_id = AddSocket(socket); 206 results_ = bluetooth_socket::Create::Results::Create(create_info); 207 AsyncWorkCompleted(); 208} 209 210BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {} 211 212BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {} 213 214bool BluetoothSocketUpdateFunction::Prepare() { 215 params_ = bluetooth_socket::Update::Params::Create(*args_); 216 EXTENSION_FUNCTION_VALIDATE(params_.get()); 217 return true; 218} 219 220void BluetoothSocketUpdateFunction::Work() { 221 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 222 if (!socket) { 223 error_ = kSocketNotFoundError; 224 return; 225 } 226 227 SetSocketProperties(socket, ¶ms_.get()->properties); 228 results_ = bluetooth_socket::Update::Results::Create(); 229} 230 231BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction() 232 : socket_event_dispatcher_(NULL) {} 233 234BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {} 235 236bool BluetoothSocketSetPausedFunction::Prepare() { 237 params_ = bluetooth_socket::SetPaused::Params::Create(*args_); 238 EXTENSION_FUNCTION_VALIDATE(params_.get()); 239 240 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context()); 241 return socket_event_dispatcher_ != NULL; 242} 243 244void BluetoothSocketSetPausedFunction::Work() { 245 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 246 if (!socket) { 247 error_ = kSocketNotFoundError; 248 return; 249 } 250 251 if (socket->paused() != params_->paused) { 252 socket->set_paused(params_->paused); 253 if (!params_->paused) { 254 socket_event_dispatcher_->OnSocketResume(extension_id(), 255 params_->socket_id); 256 } 257 } 258 259 results_ = bluetooth_socket::SetPaused::Results::Create(); 260} 261 262BluetoothSocketListenFunction::BluetoothSocketListenFunction() {} 263 264BluetoothSocketListenFunction::~BluetoothSocketListenFunction() {} 265 266bool BluetoothSocketListenFunction::Prepare() { 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 268 if (!CreateParams()) 269 return false; 270 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context()); 271 return socket_event_dispatcher_ != NULL; 272} 273 274void BluetoothSocketListenFunction::AsyncWorkStart() { 275 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 276 device::BluetoothAdapterFactory::GetAdapter( 277 base::Bind(&BluetoothSocketListenFunction::OnGetAdapter, this)); 278} 279 280void BluetoothSocketListenFunction::OnGetAdapter( 281 scoped_refptr<device::BluetoothAdapter> adapter) { 282 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 283 BluetoothApiSocket* socket = GetSocket(socket_id()); 284 if (!socket) { 285 error_ = kSocketNotFoundError; 286 AsyncWorkCompleted(); 287 return; 288 } 289 290 device::BluetoothUUID bluetooth_uuid(uuid()); 291 if (!bluetooth_uuid.IsValid()) { 292 error_ = kInvalidUuidError; 293 AsyncWorkCompleted(); 294 return; 295 } 296 297 BluetoothPermissionRequest param(uuid()); 298 if (!BluetoothManifestData::CheckRequest(extension(), param)) { 299 error_ = kPermissionDeniedError; 300 AsyncWorkCompleted(); 301 return; 302 } 303 304 scoped_ptr<std::string> name; 305 if (socket->name()) 306 name.reset(new std::string(*socket->name())); 307 308 CreateService( 309 adapter, 310 bluetooth_uuid, 311 name.Pass(), 312 base::Bind(&BluetoothSocketListenFunction::OnCreateService, this), 313 base::Bind(&BluetoothSocketListenFunction::OnCreateServiceError, this)); 314} 315 316 317void BluetoothSocketListenFunction::OnCreateService( 318 scoped_refptr<device::BluetoothSocket> socket) { 319 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 320 321 // Fetch the socket again since this is not a reference-counted object, and 322 // it may have gone away in the meantime (we check earlier to avoid making 323 // a connection in the case of an obvious programming error). 324 BluetoothApiSocket* api_socket = GetSocket(socket_id()); 325 if (!api_socket) { 326 error_ = kSocketNotFoundError; 327 AsyncWorkCompleted(); 328 return; 329 } 330 331 api_socket->AdoptListeningSocket(socket, 332 device::BluetoothUUID(uuid())); 333 socket_event_dispatcher_->OnSocketListen(extension_id(), socket_id()); 334 335 CreateResults(); 336 AsyncWorkCompleted(); 337} 338 339void BluetoothSocketListenFunction::OnCreateServiceError( 340 const std::string& message) { 341 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 342 error_ = message; 343 AsyncWorkCompleted(); 344} 345 346BluetoothSocketListenUsingRfcommFunction:: 347 BluetoothSocketListenUsingRfcommFunction() {} 348 349BluetoothSocketListenUsingRfcommFunction:: 350 ~BluetoothSocketListenUsingRfcommFunction() {} 351 352int BluetoothSocketListenUsingRfcommFunction::socket_id() const { 353 return params_->socket_id; 354} 355 356const std::string& BluetoothSocketListenUsingRfcommFunction::uuid() const { 357 return params_->uuid; 358} 359 360bool BluetoothSocketListenUsingRfcommFunction::CreateParams() { 361 params_ = bluetooth_socket::ListenUsingRfcomm::Params::Create(*args_); 362 EXTENSION_FUNCTION_VALIDATE(params_.get()); 363 return true; 364} 365 366void BluetoothSocketListenUsingRfcommFunction::CreateService( 367 scoped_refptr<device::BluetoothAdapter> adapter, 368 const device::BluetoothUUID& uuid, 369 scoped_ptr<std::string> name, 370 const device::BluetoothAdapter::CreateServiceCallback& callback, 371 const device::BluetoothAdapter::CreateServiceErrorCallback& 372 error_callback) { 373 device::BluetoothAdapter::ServiceOptions service_options; 374 service_options.name = name.Pass(); 375 376 ListenOptions* options = params_->options.get(); 377 if (options) { 378 if (options->channel.get()) 379 service_options.channel.reset(new int(*(options->channel))); 380 } 381 382 adapter->CreateRfcommService(uuid, service_options, callback, error_callback); 383} 384 385void BluetoothSocketListenUsingRfcommFunction::CreateResults() { 386 results_ = bluetooth_socket::ListenUsingRfcomm::Results::Create(); 387} 388 389BluetoothSocketListenUsingL2capFunction:: 390 BluetoothSocketListenUsingL2capFunction() {} 391 392BluetoothSocketListenUsingL2capFunction:: 393 ~BluetoothSocketListenUsingL2capFunction() {} 394 395int BluetoothSocketListenUsingL2capFunction::socket_id() const { 396 return params_->socket_id; 397} 398 399const std::string& BluetoothSocketListenUsingL2capFunction::uuid() const { 400 return params_->uuid; 401} 402 403bool BluetoothSocketListenUsingL2capFunction::CreateParams() { 404 params_ = bluetooth_socket::ListenUsingL2cap::Params::Create(*args_); 405 EXTENSION_FUNCTION_VALIDATE(params_.get()); 406 return true; 407} 408 409void BluetoothSocketListenUsingL2capFunction::CreateService( 410 scoped_refptr<device::BluetoothAdapter> adapter, 411 const device::BluetoothUUID& uuid, 412 scoped_ptr<std::string> name, 413 const device::BluetoothAdapter::CreateServiceCallback& callback, 414 const device::BluetoothAdapter::CreateServiceErrorCallback& 415 error_callback) { 416 device::BluetoothAdapter::ServiceOptions service_options; 417 service_options.name = name.Pass(); 418 419 ListenOptions* options = params_->options.get(); 420 if (options) { 421 if (options->psm) { 422 int psm = *options->psm; 423 if (!IsValidPsm(psm)) { 424 error_callback.Run(kInvalidPsmError); 425 return; 426 } 427 428 service_options.psm.reset(new int(psm)); 429 } 430 } 431 432 adapter->CreateL2capService(uuid, service_options, callback, error_callback); 433} 434 435void BluetoothSocketListenUsingL2capFunction::CreateResults() { 436 results_ = bluetooth_socket::ListenUsingL2cap::Results::Create(); 437} 438 439BluetoothSocketAbstractConnectFunction:: 440 BluetoothSocketAbstractConnectFunction() {} 441 442BluetoothSocketAbstractConnectFunction:: 443 ~BluetoothSocketAbstractConnectFunction() {} 444 445bool BluetoothSocketAbstractConnectFunction::Prepare() { 446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 447 params_ = bluetooth_socket::Connect::Params::Create(*args_); 448 EXTENSION_FUNCTION_VALIDATE(params_.get()); 449 450 socket_event_dispatcher_ = GetSocketEventDispatcher(browser_context()); 451 return socket_event_dispatcher_ != NULL; 452} 453 454void BluetoothSocketAbstractConnectFunction::AsyncWorkStart() { 455 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 456 device::BluetoothAdapterFactory::GetAdapter( 457 base::Bind(&BluetoothSocketAbstractConnectFunction::OnGetAdapter, this)); 458} 459 460void BluetoothSocketAbstractConnectFunction::OnGetAdapter( 461 scoped_refptr<device::BluetoothAdapter> adapter) { 462 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 463 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 464 if (!socket) { 465 error_ = kSocketNotFoundError; 466 AsyncWorkCompleted(); 467 return; 468 } 469 470 device::BluetoothDevice* device = adapter->GetDevice(params_->address); 471 if (!device) { 472 error_ = kDeviceNotFoundError; 473 AsyncWorkCompleted(); 474 return; 475 } 476 477 device::BluetoothUUID uuid(params_->uuid); 478 if (!uuid.IsValid()) { 479 error_ = kInvalidUuidError; 480 AsyncWorkCompleted(); 481 return; 482 } 483 484 BluetoothPermissionRequest param(params_->uuid); 485 if (!BluetoothManifestData::CheckRequest(extension(), param)) { 486 error_ = kPermissionDeniedError; 487 AsyncWorkCompleted(); 488 return; 489 } 490 491 ConnectToService(device, uuid); 492} 493 494void BluetoothSocketAbstractConnectFunction::OnConnect( 495 scoped_refptr<device::BluetoothSocket> socket) { 496 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 497 498 // Fetch the socket again since this is not a reference-counted object, and 499 // it may have gone away in the meantime (we check earlier to avoid making 500 // a connection in the case of an obvious programming error). 501 BluetoothApiSocket* api_socket = GetSocket(params_->socket_id); 502 if (!api_socket) { 503 error_ = kSocketNotFoundError; 504 AsyncWorkCompleted(); 505 return; 506 } 507 508 api_socket->AdoptConnectedSocket(socket, 509 params_->address, 510 device::BluetoothUUID(params_->uuid)); 511 socket_event_dispatcher_->OnSocketConnect(extension_id(), 512 params_->socket_id); 513 514 results_ = bluetooth_socket::Connect::Results::Create(); 515 AsyncWorkCompleted(); 516} 517 518void BluetoothSocketAbstractConnectFunction::OnConnectError( 519 const std::string& message) { 520 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 521 error_ = message; 522 AsyncWorkCompleted(); 523} 524 525BluetoothSocketConnectFunction::BluetoothSocketConnectFunction() {} 526 527BluetoothSocketConnectFunction::~BluetoothSocketConnectFunction() {} 528 529void BluetoothSocketConnectFunction::ConnectToService( 530 device::BluetoothDevice* device, 531 const device::BluetoothUUID& uuid) { 532 device->ConnectToService( 533 uuid, 534 base::Bind(&BluetoothSocketConnectFunction::OnConnect, this), 535 base::Bind(&BluetoothSocketConnectFunction::OnConnectError, this)); 536} 537 538BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {} 539 540BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {} 541 542bool BluetoothSocketDisconnectFunction::Prepare() { 543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 544 params_ = bluetooth_socket::Disconnect::Params::Create(*args_); 545 EXTENSION_FUNCTION_VALIDATE(params_.get()); 546 return true; 547} 548 549void BluetoothSocketDisconnectFunction::AsyncWorkStart() { 550 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 551 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 552 if (!socket) { 553 error_ = kSocketNotFoundError; 554 AsyncWorkCompleted(); 555 return; 556 } 557 558 socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess, 559 this)); 560} 561 562void BluetoothSocketDisconnectFunction::OnSuccess() { 563 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 564 results_ = bluetooth_socket::Disconnect::Results::Create(); 565 AsyncWorkCompleted(); 566} 567 568BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {} 569 570BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {} 571 572bool BluetoothSocketCloseFunction::Prepare() { 573 params_ = bluetooth_socket::Close::Params::Create(*args_); 574 EXTENSION_FUNCTION_VALIDATE(params_.get()); 575 return true; 576} 577 578void BluetoothSocketCloseFunction::Work() { 579 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 580 if (!socket) { 581 error_ = kSocketNotFoundError; 582 return; 583 } 584 585 RemoveSocket(params_->socket_id); 586 results_ = bluetooth_socket::Close::Results::Create(); 587} 588 589BluetoothSocketSendFunction::BluetoothSocketSendFunction() 590 : io_buffer_size_(0) {} 591 592BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {} 593 594bool BluetoothSocketSendFunction::Prepare() { 595 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 596 params_ = bluetooth_socket::Send::Params::Create(*args_); 597 EXTENSION_FUNCTION_VALIDATE(params_.get()); 598 599 io_buffer_size_ = params_->data.size(); 600 io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); 601 return true; 602} 603 604void BluetoothSocketSendFunction::AsyncWorkStart() { 605 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 606 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 607 if (!socket) { 608 error_ = kSocketNotFoundError; 609 return; 610 } 611 612 socket->Send(io_buffer_, 613 io_buffer_size_, 614 base::Bind(&BluetoothSocketSendFunction::OnSuccess, this), 615 base::Bind(&BluetoothSocketSendFunction::OnError, this)); 616} 617 618void BluetoothSocketSendFunction::OnSuccess(int bytes_sent) { 619 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 620 results_ = bluetooth_socket::Send::Results::Create(bytes_sent); 621 AsyncWorkCompleted(); 622} 623 624void BluetoothSocketSendFunction::OnError( 625 BluetoothApiSocket::ErrorReason reason, 626 const std::string& message) { 627 DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); 628 error_ = message; 629 AsyncWorkCompleted(); 630} 631 632BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {} 633 634BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {} 635 636bool BluetoothSocketGetInfoFunction::Prepare() { 637 params_ = bluetooth_socket::GetInfo::Params::Create(*args_); 638 EXTENSION_FUNCTION_VALIDATE(params_.get()); 639 return true; 640} 641 642void BluetoothSocketGetInfoFunction::Work() { 643 BluetoothApiSocket* socket = GetSocket(params_->socket_id); 644 if (!socket) { 645 error_ = kSocketNotFoundError; 646 return; 647 } 648 649 linked_ptr<bluetooth_socket::SocketInfo> socket_info = 650 CreateSocketInfo(params_->socket_id, socket); 651 results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info); 652} 653 654BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {} 655 656BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {} 657 658bool BluetoothSocketGetSocketsFunction::Prepare() { return true; } 659 660void BluetoothSocketGetSocketsFunction::Work() { 661 std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos; 662 base::hash_set<int>* resource_ids = GetSocketIds(); 663 if (resource_ids != NULL) { 664 for (base::hash_set<int>::iterator it = resource_ids->begin(); 665 it != resource_ids->end(); 666 ++it) { 667 int socket_id = *it; 668 BluetoothApiSocket* socket = GetSocket(socket_id); 669 if (socket) { 670 socket_infos.push_back(CreateSocketInfo(socket_id, socket)); 671 } 672 } 673 } 674 results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos); 675} 676 677} // namespace core_api 678} // namespace extensions 679