1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/bluetooth/bluetooth_api.h" 6 7 #include <string> 8 9 #include "base/memory/ref_counted.h" 10 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_factory.h" 11 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h" 12 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h" 13 #include "chrome/browser/extensions/event_names.h" 14 #include "chrome/browser/extensions/event_router.h" 15 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/common/extensions/api/bluetooth.h" 18 #include "chrome/common/extensions/permissions/bluetooth_permission.h" 19 #include "chrome/common/extensions/permissions/permissions_data.h" 20 #include "content/public/browser/browser_thread.h" 21 #include "device/bluetooth/bluetooth_adapter.h" 22 #include "device/bluetooth/bluetooth_device.h" 23 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h" 24 #include "device/bluetooth/bluetooth_profile.h" 25 #include "device/bluetooth/bluetooth_service_record.h" 26 #include "device/bluetooth/bluetooth_socket.h" 27 #include "device/bluetooth/bluetooth_utils.h" 28 #include "net/base/io_buffer.h" 29 30 using device::BluetoothAdapter; 31 using device::BluetoothDevice; 32 using device::BluetoothProfile; 33 using device::BluetoothServiceRecord; 34 using device::BluetoothSocket; 35 36 namespace { 37 38 extensions::ExtensionBluetoothEventRouter* GetEventRouter(Profile* profile) { 39 return extensions::BluetoothAPI::Get(profile)->bluetooth_event_router(); 40 } 41 42 } // namespace 43 44 namespace { 45 46 const char kCouldNotGetLocalOutOfBandPairingData[] = 47 "Could not get local Out Of Band Pairing Data"; 48 const char kCouldNotSetOutOfBandPairingData[] = 49 "Could not set Out Of Band Pairing Data"; 50 const char kFailedToConnect[] = "Connection failed"; 51 const char kInvalidDevice[] = "Invalid device"; 52 const char kInvalidUuid[] = "Invalid UUID"; 53 const char kPermissionDenied[] = "Permission to add profile denied."; 54 const char kPlatformNotSupported[] = 55 "This operation is not supported on your platform"; 56 const char kProfileAlreadyRegistered[] = 57 "This profile has already been registered"; 58 const char kProfileNotFound[] = "Profile not found: invalid uuid"; 59 const char kProfileRegistrationFailed[] = "Profile registration failed"; 60 const char kServiceDiscoveryFailed[] = "Service discovery failed"; 61 const char kSocketNotFoundError[] = "Socket not found: invalid socket id"; 62 const char kStartDiscoveryFailed[] = "Starting discovery failed"; 63 const char kStopDiscoveryFailed[] = "Failed to stop discovery"; 64 65 } // namespace 66 67 namespace AddProfile = extensions::api::bluetooth::AddProfile; 68 namespace Connect = extensions::api::bluetooth::Connect; 69 namespace Disconnect = extensions::api::bluetooth::Disconnect; 70 namespace GetDevices = extensions::api::bluetooth::GetDevices; 71 namespace GetProfiles = extensions::api::bluetooth::GetProfiles; 72 namespace GetServices = extensions::api::bluetooth::GetServices; 73 namespace Read = extensions::api::bluetooth::Read; 74 namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile; 75 namespace SetOutOfBandPairingData = 76 extensions::api::bluetooth::SetOutOfBandPairingData; 77 namespace Write = extensions::api::bluetooth::Write; 78 79 namespace extensions { 80 81 // static 82 BluetoothAPI* BluetoothAPI::Get(Profile* profile) { 83 return BluetoothAPIFactory::GetForProfile(profile); 84 } 85 86 BluetoothAPI::BluetoothAPI(Profile* profile) : profile_(profile) { 87 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 88 this, extensions::event_names::kBluetoothOnAdapterStateChanged); 89 } 90 91 BluetoothAPI::~BluetoothAPI() { 92 } 93 94 ExtensionBluetoothEventRouter* BluetoothAPI::bluetooth_event_router() { 95 if (!bluetooth_event_router_) 96 bluetooth_event_router_.reset(new ExtensionBluetoothEventRouter(profile_)); 97 98 return bluetooth_event_router_.get(); 99 } 100 101 void BluetoothAPI::Shutdown() { 102 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 103 } 104 105 void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) { 106 if (bluetooth_event_router()->IsBluetoothSupported()) 107 bluetooth_event_router()->OnListenerAdded(); 108 } 109 110 void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) { 111 if (bluetooth_event_router()->IsBluetoothSupported()) 112 bluetooth_event_router()->OnListenerRemoved(); 113 } 114 115 namespace api { 116 117 BluetoothAddProfileFunction::BluetoothAddProfileFunction() { 118 } 119 120 bool BluetoothAddProfileFunction::RunImpl() { 121 scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_)); 122 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 123 124 if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) { 125 SetError(kInvalidUuid); 126 return false; 127 } 128 129 BluetoothPermission::CheckParam param(params->profile.uuid); 130 if (!PermissionsData::CheckAPIPermissionWithParam( 131 GetExtension(), APIPermission::kBluetooth, ¶m)) { 132 SetError(kPermissionDenied); 133 return false; 134 } 135 136 uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid); 137 138 if (GetEventRouter(profile())->HasProfile(uuid_)) { 139 SetError(kProfileAlreadyRegistered); 140 return false; 141 } 142 143 BluetoothProfile::Options options; 144 if (params->profile.name.get()) 145 options.name = *params->profile.name.get(); 146 if (params->profile.channel.get()) 147 options.channel = *params->profile.channel.get(); 148 if (params->profile.psm.get()) 149 options.psm = *params->profile.psm.get(); 150 if (params->profile.require_authentication.get()) { 151 options.require_authentication = 152 *params->profile.require_authentication.get(); 153 } 154 if (params->profile.require_authorization.get()) { 155 options.require_authorization = 156 *params->profile.require_authorization.get(); 157 } 158 if (params->profile.auto_connect.get()) 159 options.auto_connect = *params->profile.auto_connect.get(); 160 if (params->profile.version.get()) 161 options.version = *params->profile.version.get(); 162 if (params->profile.features.get()) 163 options.features = *params->profile.features.get(); 164 165 RegisterProfile( 166 options, 167 base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this)); 168 169 return true; 170 } 171 172 void BluetoothAddProfileFunction::RegisterProfile( 173 const BluetoothProfile::Options& options, 174 const BluetoothProfile::ProfileCallback& callback) { 175 BluetoothProfile::Register(uuid_, options, callback); 176 } 177 178 void BluetoothAddProfileFunction::OnProfileRegistered( 179 BluetoothProfile* bluetooth_profile) { 180 if (!bluetooth_profile) { 181 SetError(kProfileRegistrationFailed); 182 SendResponse(false); 183 return; 184 } 185 186 if (GetEventRouter(profile())->HasProfile(uuid_)) { 187 bluetooth_profile->Unregister(); 188 SetError(kProfileAlreadyRegistered); 189 SendResponse(false); 190 return; 191 } 192 193 bluetooth_profile->SetConnectionCallback( 194 base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent, 195 base::Unretained(GetEventRouter(profile())), 196 extension_id(), 197 uuid_)); 198 GetEventRouter(profile())->AddProfile(uuid_, bluetooth_profile); 199 SendResponse(true); 200 } 201 202 bool BluetoothRemoveProfileFunction::RunImpl() { 203 scoped_ptr<RemoveProfile::Params> params( 204 RemoveProfile::Params::Create(*args_)); 205 206 if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) { 207 SetError(kInvalidUuid); 208 return false; 209 } 210 211 std::string uuid = 212 device::bluetooth_utils::CanonicalUuid(params->profile.uuid); 213 214 if (!GetEventRouter(profile())->HasProfile(uuid)) { 215 SetError(kProfileNotFound); 216 return false; 217 } 218 219 GetEventRouter(profile())->RemoveProfile(uuid); 220 return true; 221 } 222 223 // TODO(youngki): Implement. 224 bool BluetoothGetProfilesFunction::DoWork( 225 scoped_refptr<device::BluetoothAdapter> adapter) { 226 scoped_ptr<GetProfiles::Params> params(GetProfiles::Params::Create(*args_)); 227 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 228 const bluetooth::GetProfilesOptions& options = params->options; 229 230 BluetoothDevice* device = adapter->GetDevice(options.device.address); 231 if (!device) { 232 SetError(kInvalidDevice); 233 SendResponse(false); 234 return false; 235 } 236 237 BluetoothDevice::ServiceList service_list = device->GetServices(); 238 239 base::ListValue* profiles = new base::ListValue; 240 for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin(); 241 iter != service_list.end(); 242 ++iter) { 243 bluetooth::Profile api_profile; 244 api_profile.uuid = *iter; 245 profiles->Append(api_profile.ToValue().release()); 246 } 247 248 SetResult(profiles); 249 SendResponse(true); 250 251 return true; 252 } 253 254 bool BluetoothGetAdapterStateFunction::DoWork( 255 scoped_refptr<BluetoothAdapter> adapter) { 256 bluetooth::AdapterState state; 257 PopulateAdapterState(*adapter.get(), &state); 258 SetResult(state.ToValue().release()); 259 SendResponse(true); 260 return true; 261 } 262 263 BluetoothGetDevicesFunction::BluetoothGetDevicesFunction() 264 : device_events_sent_(0) {} 265 266 void BluetoothGetDevicesFunction::DispatchDeviceSearchResult( 267 const BluetoothDevice& device) { 268 bluetooth::Device extension_device; 269 bluetooth::BluetoothDeviceToApiDevice(device, &extension_device); 270 GetEventRouter(profile())->DispatchDeviceEvent( 271 extensions::event_names::kBluetoothOnDeviceSearchResult, 272 extension_device); 273 274 device_events_sent_++; 275 } 276 277 void BluetoothGetDevicesFunction::FinishDeviceSearch() { 278 scoped_ptr<base::ListValue> args(new base::ListValue()); 279 scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue()); 280 info->SetInteger("expectedEventCount", device_events_sent_); 281 args->Append(info.release()); 282 283 scoped_ptr<extensions::Event> event(new extensions::Event( 284 extensions::event_names::kBluetoothOnDeviceSearchFinished, args.Pass())); 285 extensions::ExtensionSystem::Get(profile())->event_router()-> 286 BroadcastEvent(event.Pass()); 287 288 SendResponse(true); 289 } 290 291 bool BluetoothGetDevicesFunction::DoWork( 292 scoped_refptr<BluetoothAdapter> adapter) { 293 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 294 295 scoped_ptr<GetDevices::Params> params(GetDevices::Params::Create(*args_)); 296 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 297 const bluetooth::GetDevicesOptions& options = params->options; 298 299 std::string uuid; 300 if (options.profile.get() != NULL) { 301 uuid = options.profile->uuid; 302 if (!BluetoothDevice::IsUUIDValid(uuid)) { 303 SetError(kInvalidUuid); 304 SendResponse(false); 305 return false; 306 } 307 } 308 309 BluetoothAdapter::DeviceList devices = adapter->GetDevices(); 310 for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin(); 311 iter != devices.end(); 312 ++iter) { 313 const BluetoothDevice* device = *iter; 314 DCHECK(device); 315 if (uuid.empty() || device->ProvidesServiceWithUUID(uuid)) 316 DispatchDeviceSearchResult(*device); 317 } 318 319 FinishDeviceSearch(); 320 321 return true; 322 } 323 324 void BluetoothGetServicesFunction::GetServiceRecordsCallback( 325 base::ListValue* services, 326 const BluetoothDevice::ServiceRecordList& records) { 327 for (BluetoothDevice::ServiceRecordList::const_iterator i = records.begin(); 328 i != records.end(); ++i) { 329 const BluetoothServiceRecord& record = **i; 330 bluetooth::ServiceRecord api_record; 331 api_record.name = record.name(); 332 if (!record.uuid().empty()) 333 api_record.uuid.reset(new std::string(record.uuid())); 334 services->Append(api_record.ToValue().release()); 335 } 336 337 SendResponse(true); 338 } 339 340 void BluetoothGetServicesFunction::OnErrorCallback() { 341 SetError(kServiceDiscoveryFailed); 342 SendResponse(false); 343 } 344 345 bool BluetoothGetServicesFunction::DoWork( 346 scoped_refptr<BluetoothAdapter> adapter) { 347 scoped_ptr<GetServices::Params> params(GetServices::Params::Create(*args_)); 348 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 349 const bluetooth::GetServicesOptions& options = params->options; 350 351 BluetoothDevice* device = adapter->GetDevice(options.device_address); 352 if (!device) { 353 SetError(kInvalidDevice); 354 SendResponse(false); 355 return false; 356 } 357 358 base::ListValue* services = new base::ListValue; 359 SetResult(services); 360 361 device->GetServiceRecords( 362 base::Bind(&BluetoothGetServicesFunction::GetServiceRecordsCallback, 363 this, 364 services), 365 base::Bind(&BluetoothGetServicesFunction::OnErrorCallback, 366 this)); 367 368 return true; 369 } 370 371 void BluetoothConnectFunction::OnSuccessCallback() { 372 SendResponse(true); 373 } 374 375 void BluetoothConnectFunction::OnErrorCallback() { 376 SetError(kFailedToConnect); 377 SendResponse(false); 378 } 379 380 bool BluetoothConnectFunction::DoWork(scoped_refptr<BluetoothAdapter> adapter) { 381 scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_)); 382 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 383 const bluetooth::ConnectOptions& options = params->options; 384 385 if (!BluetoothDevice::IsUUIDValid(options.profile.uuid)) { 386 SetError(kInvalidUuid); 387 SendResponse(false); 388 return false; 389 } 390 391 BluetoothDevice* device = adapter->GetDevice(options.device.address); 392 if (!device) { 393 SetError(kInvalidDevice); 394 SendResponse(false); 395 return false; 396 } 397 398 std::string uuid = device::bluetooth_utils::CanonicalUuid( 399 options.profile.uuid); 400 401 BluetoothProfile* bluetooth_profile = 402 GetEventRouter(profile())->GetProfile(uuid); 403 if (!bluetooth_profile) { 404 SetError(kProfileNotFound); 405 SendResponse(false); 406 return false; 407 } 408 409 device->ConnectToProfile( 410 bluetooth_profile, 411 base::Bind(&BluetoothConnectFunction::OnSuccessCallback, this), 412 base::Bind(&BluetoothConnectFunction::OnErrorCallback, this)); 413 414 return true; 415 } 416 417 bool BluetoothDisconnectFunction::RunImpl() { 418 scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_)); 419 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 420 const bluetooth::DisconnectOptions& options = params->options; 421 return GetEventRouter(profile())->ReleaseSocket(options.socket.id); 422 } 423 424 BluetoothReadFunction::BluetoothReadFunction() : success_(false) {} 425 BluetoothReadFunction::~BluetoothReadFunction() {} 426 427 bool BluetoothReadFunction::Prepare() { 428 scoped_ptr<Read::Params> params(Read::Params::Create(*args_)); 429 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 430 const bluetooth::ReadOptions& options = params->options; 431 432 socket_ = GetEventRouter(profile())->GetSocket(options.socket.id); 433 if (socket_.get() == NULL) { 434 SetError(kSocketNotFoundError); 435 return false; 436 } 437 438 success_ = false; 439 return true; 440 } 441 442 void BluetoothReadFunction::Work() { 443 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 444 445 if (!socket_.get()) 446 return; 447 448 scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer); 449 success_ = socket_->Receive(buffer.get()); 450 if (success_) 451 SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer->StartOfBuffer(), 452 buffer->offset())); 453 else 454 SetError(socket_->GetLastErrorMessage()); 455 } 456 457 bool BluetoothReadFunction::Respond() { 458 return success_; 459 } 460 461 BluetoothWriteFunction::BluetoothWriteFunction() 462 : success_(false), 463 data_to_write_(NULL) { 464 } 465 466 BluetoothWriteFunction::~BluetoothWriteFunction() {} 467 468 bool BluetoothWriteFunction::Prepare() { 469 // TODO(bryeung): update to new-style parameter passing when ArrayBuffer 470 // support is added 471 base::DictionaryValue* options; 472 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options)); 473 474 base::DictionaryValue* socket; 475 EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("socket", &socket)); 476 477 int socket_id; 478 EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id)); 479 480 socket_ = GetEventRouter(profile())->GetSocket(socket_id); 481 if (socket_.get() == NULL) { 482 SetError(kSocketNotFoundError); 483 return false; 484 } 485 486 base::BinaryValue* tmp_data; 487 EXTENSION_FUNCTION_VALIDATE(options->GetBinary("data", &tmp_data)); 488 data_to_write_ = tmp_data; 489 490 success_ = false; 491 return socket_.get() != NULL; 492 } 493 494 void BluetoothWriteFunction::Work() { 495 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 496 497 if (socket_.get() == NULL) 498 return; 499 500 scoped_refptr<net::WrappedIOBuffer> wrapped_io_buffer( 501 new net::WrappedIOBuffer(data_to_write_->GetBuffer())); 502 scoped_refptr<net::DrainableIOBuffer> drainable_io_buffer( 503 new net::DrainableIOBuffer(wrapped_io_buffer.get(), 504 data_to_write_->GetSize())); 505 success_ = socket_->Send(drainable_io_buffer.get()); 506 if (success_) { 507 if (drainable_io_buffer->BytesConsumed() > 0) 508 SetResult(base::Value::CreateIntegerValue( 509 drainable_io_buffer->BytesConsumed())); 510 else 511 results_.reset(); 512 } else { 513 SetError(socket_->GetLastErrorMessage()); 514 } 515 } 516 517 bool BluetoothWriteFunction::Respond() { 518 return success_; 519 } 520 521 void BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback() { 522 SendResponse(true); 523 } 524 525 void BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback() { 526 SetError(kCouldNotSetOutOfBandPairingData); 527 SendResponse(false); 528 } 529 530 bool BluetoothSetOutOfBandPairingDataFunction::DoWork( 531 scoped_refptr<BluetoothAdapter> adapter) { 532 // TODO(bryeung): update to new-style parameter passing when ArrayBuffer 533 // support is added 534 base::DictionaryValue* options; 535 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options)); 536 std::string address; 537 EXTENSION_FUNCTION_VALIDATE(options->GetString("deviceAddress", &address)); 538 539 BluetoothDevice* device = adapter->GetDevice(address); 540 if (!device) { 541 SetError(kInvalidDevice); 542 SendResponse(false); 543 return false; 544 } 545 546 if (options->HasKey("data")) { 547 base::DictionaryValue* data_in; 548 EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("data", &data_in)); 549 550 device::BluetoothOutOfBandPairingData data_out; 551 552 base::BinaryValue* tmp_data; 553 EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("hash", &tmp_data)); 554 EXTENSION_FUNCTION_VALIDATE( 555 tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize); 556 memcpy(data_out.hash, 557 reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()), 558 device::kBluetoothOutOfBandPairingDataSize); 559 560 EXTENSION_FUNCTION_VALIDATE(data_in->GetBinary("randomizer", &tmp_data)); 561 EXTENSION_FUNCTION_VALIDATE( 562 tmp_data->GetSize() == device::kBluetoothOutOfBandPairingDataSize); 563 memcpy(data_out.randomizer, 564 reinterpret_cast<uint8_t*>(tmp_data->GetBuffer()), 565 device::kBluetoothOutOfBandPairingDataSize); 566 567 device->SetOutOfBandPairingData( 568 data_out, 569 base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback, 570 this), 571 base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback, 572 this)); 573 } else { 574 device->ClearOutOfBandPairingData( 575 base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback, 576 this), 577 base::Bind(&BluetoothSetOutOfBandPairingDataFunction::OnErrorCallback, 578 this)); 579 } 580 581 return true; 582 } 583 584 void BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback( 585 const device::BluetoothOutOfBandPairingData& data) { 586 base::BinaryValue* hash = base::BinaryValue::CreateWithCopiedBuffer( 587 reinterpret_cast<const char*>(data.hash), 588 device::kBluetoothOutOfBandPairingDataSize); 589 base::BinaryValue* randomizer = base::BinaryValue::CreateWithCopiedBuffer( 590 reinterpret_cast<const char*>(data.randomizer), 591 device::kBluetoothOutOfBandPairingDataSize); 592 593 // TODO(bryeung): convert to bluetooth::OutOfBandPairingData 594 // when ArrayBuffer support within objects is completed. 595 base::DictionaryValue* result = new base::DictionaryValue(); 596 result->Set("hash", hash); 597 result->Set("randomizer", randomizer); 598 599 SetResult(result); 600 601 SendResponse(true); 602 } 603 604 void BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback() { 605 SetError(kCouldNotGetLocalOutOfBandPairingData); 606 SendResponse(false); 607 } 608 609 bool BluetoothGetLocalOutOfBandPairingDataFunction::DoWork( 610 scoped_refptr<BluetoothAdapter> adapter) { 611 adapter->ReadLocalOutOfBandPairingData( 612 base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ReadCallback, 613 this), 614 base::Bind(&BluetoothGetLocalOutOfBandPairingDataFunction::ErrorCallback, 615 this)); 616 617 return true; 618 } 619 620 void BluetoothStartDiscoveryFunction::OnSuccessCallback() { 621 SendResponse(true); 622 } 623 624 void BluetoothStartDiscoveryFunction::OnErrorCallback() { 625 SetError(kStartDiscoveryFailed); 626 GetEventRouter(profile())->SetResponsibleForDiscovery(false); 627 SendResponse(false); 628 GetEventRouter(profile())->OnListenerRemoved(); 629 } 630 631 bool BluetoothStartDiscoveryFunction::DoWork( 632 scoped_refptr<BluetoothAdapter> adapter) { 633 GetEventRouter(profile())->SetSendDiscoveryEvents(true); 634 635 // If this profile is already discovering devices, there should be nothing 636 // else to do. 637 if (!GetEventRouter(profile())->IsResponsibleForDiscovery()) { 638 GetEventRouter(profile())->SetResponsibleForDiscovery(true); 639 GetEventRouter(profile())->OnListenerAdded(); 640 adapter->StartDiscovering( 641 base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this), 642 base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this)); 643 } 644 645 return true; 646 } 647 648 void BluetoothStopDiscoveryFunction::OnSuccessCallback() { 649 SendResponse(true); 650 GetEventRouter(profile())->OnListenerRemoved(); 651 } 652 653 void BluetoothStopDiscoveryFunction::OnErrorCallback() { 654 SetError(kStopDiscoveryFailed); 655 GetEventRouter(profile())->SetResponsibleForDiscovery(true); 656 SendResponse(false); 657 GetEventRouter(profile())->OnListenerRemoved(); 658 } 659 660 bool BluetoothStopDiscoveryFunction::DoWork( 661 scoped_refptr<BluetoothAdapter> adapter) { 662 GetEventRouter(profile())->SetSendDiscoveryEvents(false); 663 if (GetEventRouter(profile())->IsResponsibleForDiscovery()) { 664 adapter->StopDiscovering( 665 base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this), 666 base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this)); 667 } 668 669 return true; 670 } 671 672 } // namespace api 673 } // namespace extensions 674