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/extension_system.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/common/extensions/api/bluetooth.h" 17 #include "chrome/common/extensions/permissions/bluetooth_permission.h" 18 #include "content/public/browser/browser_thread.h" 19 #include "device/bluetooth/bluetooth_adapter.h" 20 #include "device/bluetooth/bluetooth_device.h" 21 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h" 22 #include "device/bluetooth/bluetooth_profile.h" 23 #include "device/bluetooth/bluetooth_service_record.h" 24 #include "device/bluetooth/bluetooth_socket.h" 25 #include "device/bluetooth/bluetooth_utils.h" 26 #include "extensions/browser/event_router.h" 27 #include "extensions/common/permissions/permissions_data.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 kProfileAlreadyRegistered[] = 55 "This profile has already been registered"; 56 const char kProfileNotFound[] = "Profile not found: invalid uuid"; 57 const char kProfileRegistrationFailed[] = "Profile registration failed"; 58 const char kServiceDiscoveryFailed[] = "Service discovery failed"; 59 const char kSocketNotFoundError[] = "Socket not found: invalid socket id"; 60 const char kStartDiscoveryFailed[] = "Starting discovery failed"; 61 const char kStopDiscoveryFailed[] = "Failed to stop discovery"; 62 63 } // namespace 64 65 namespace AddProfile = extensions::api::bluetooth::AddProfile; 66 namespace bluetooth = extensions::api::bluetooth; 67 namespace Connect = extensions::api::bluetooth::Connect; 68 namespace Disconnect = extensions::api::bluetooth::Disconnect; 69 namespace GetDevices = extensions::api::bluetooth::GetDevices; 70 namespace GetProfiles = extensions::api::bluetooth::GetProfiles; 71 namespace GetServices = extensions::api::bluetooth::GetServices; 72 namespace Read = extensions::api::bluetooth::Read; 73 namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile; 74 namespace SetOutOfBandPairingData = 75 extensions::api::bluetooth::SetOutOfBandPairingData; 76 namespace Write = extensions::api::bluetooth::Write; 77 78 namespace extensions { 79 80 // static 81 BluetoothAPI* BluetoothAPI::Get(Profile* profile) { 82 return BluetoothAPIFactory::GetForProfile(profile); 83 } 84 85 BluetoothAPI::BluetoothAPI(Profile* profile) : profile_(profile) { 86 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 87 this, bluetooth::OnAdapterStateChanged::kEventName); 88 } 89 90 BluetoothAPI::~BluetoothAPI() { 91 } 92 93 ExtensionBluetoothEventRouter* BluetoothAPI::bluetooth_event_router() { 94 if (!bluetooth_event_router_) 95 bluetooth_event_router_.reset(new ExtensionBluetoothEventRouter(profile_)); 96 97 return bluetooth_event_router_.get(); 98 } 99 100 void BluetoothAPI::Shutdown() { 101 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 102 } 103 104 void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) { 105 if (bluetooth_event_router()->IsBluetoothSupported()) 106 bluetooth_event_router()->OnListenerAdded(); 107 } 108 109 void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) { 110 if (bluetooth_event_router()->IsBluetoothSupported()) 111 bluetooth_event_router()->OnListenerRemoved(); 112 } 113 114 namespace api { 115 116 BluetoothAddProfileFunction::BluetoothAddProfileFunction() { 117 } 118 119 bool BluetoothAddProfileFunction::RunImpl() { 120 scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_)); 121 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 122 123 if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) { 124 SetError(kInvalidUuid); 125 return false; 126 } 127 128 BluetoothPermission::CheckParam param(params->profile.uuid); 129 if (!PermissionsData::CheckAPIPermissionWithParam( 130 GetExtension(), APIPermission::kBluetooth, ¶m)) { 131 SetError(kPermissionDenied); 132 return false; 133 } 134 135 uuid_ = device::bluetooth_utils::CanonicalUuid(params->profile.uuid); 136 137 if (GetEventRouter(GetProfile())->HasProfile(uuid_)) { 138 SetError(kProfileAlreadyRegistered); 139 return false; 140 } 141 142 BluetoothProfile::Options options; 143 if (params->profile.name.get()) 144 options.name = *params->profile.name.get(); 145 if (params->profile.channel.get()) 146 options.channel = *params->profile.channel.get(); 147 if (params->profile.psm.get()) 148 options.psm = *params->profile.psm.get(); 149 if (params->profile.require_authentication.get()) { 150 options.require_authentication = 151 *params->profile.require_authentication.get(); 152 } 153 if (params->profile.require_authorization.get()) { 154 options.require_authorization = 155 *params->profile.require_authorization.get(); 156 } 157 if (params->profile.auto_connect.get()) 158 options.auto_connect = *params->profile.auto_connect.get(); 159 if (params->profile.version.get()) 160 options.version = *params->profile.version.get(); 161 if (params->profile.features.get()) 162 options.features = *params->profile.features.get(); 163 164 RegisterProfile( 165 options, 166 base::Bind(&BluetoothAddProfileFunction::OnProfileRegistered, this)); 167 168 return true; 169 } 170 171 void BluetoothAddProfileFunction::RegisterProfile( 172 const BluetoothProfile::Options& options, 173 const BluetoothProfile::ProfileCallback& callback) { 174 BluetoothProfile::Register(uuid_, options, callback); 175 } 176 177 void BluetoothAddProfileFunction::OnProfileRegistered( 178 BluetoothProfile* bluetooth_profile) { 179 if (!bluetooth_profile) { 180 SetError(kProfileRegistrationFailed); 181 SendResponse(false); 182 return; 183 } 184 185 if (GetEventRouter(GetProfile())->HasProfile(uuid_)) { 186 bluetooth_profile->Unregister(); 187 SetError(kProfileAlreadyRegistered); 188 SendResponse(false); 189 return; 190 } 191 192 bluetooth_profile->SetConnectionCallback( 193 base::Bind(&ExtensionBluetoothEventRouter::DispatchConnectionEvent, 194 base::Unretained(GetEventRouter(GetProfile())), 195 extension_id(), 196 uuid_)); 197 GetEventRouter(GetProfile())->AddProfile(uuid_, bluetooth_profile); 198 SendResponse(true); 199 } 200 201 bool BluetoothRemoveProfileFunction::RunImpl() { 202 scoped_ptr<RemoveProfile::Params> params( 203 RemoveProfile::Params::Create(*args_)); 204 205 if (!BluetoothDevice::IsUUIDValid(params->profile.uuid)) { 206 SetError(kInvalidUuid); 207 return false; 208 } 209 210 std::string uuid = 211 device::bluetooth_utils::CanonicalUuid(params->profile.uuid); 212 213 if (!GetEventRouter(GetProfile())->HasProfile(uuid)) { 214 SetError(kProfileNotFound); 215 return false; 216 } 217 218 GetEventRouter(GetProfile())->RemoveProfile(uuid); 219 return true; 220 } 221 222 // TODO(youngki): Implement. 223 bool BluetoothGetProfilesFunction::DoWork( 224 scoped_refptr<device::BluetoothAdapter> adapter) { 225 scoped_ptr<GetProfiles::Params> params(GetProfiles::Params::Create(*args_)); 226 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 227 const bluetooth::GetProfilesOptions& options = params->options; 228 229 BluetoothDevice* device = adapter->GetDevice(options.device.address); 230 if (!device) { 231 SetError(kInvalidDevice); 232 SendResponse(false); 233 return false; 234 } 235 236 BluetoothDevice::ServiceList service_list = device->GetServices(); 237 238 base::ListValue* profiles = new base::ListValue; 239 for (BluetoothDevice::ServiceList::const_iterator iter = service_list.begin(); 240 iter != service_list.end(); 241 ++iter) { 242 bluetooth::Profile api_profile; 243 api_profile.uuid = *iter; 244 profiles->Append(api_profile.ToValue().release()); 245 } 246 247 SetResult(profiles); 248 SendResponse(true); 249 250 return true; 251 } 252 253 bool BluetoothGetAdapterStateFunction::DoWork( 254 scoped_refptr<BluetoothAdapter> adapter) { 255 bluetooth::AdapterState state; 256 PopulateAdapterState(*adapter.get(), &state); 257 SetResult(state.ToValue().release()); 258 SendResponse(true); 259 return true; 260 } 261 262 BluetoothGetDevicesFunction::BluetoothGetDevicesFunction() 263 : device_events_sent_(0) {} 264 265 void BluetoothGetDevicesFunction::DispatchDeviceSearchResult( 266 const BluetoothDevice& device) { 267 bluetooth::Device extension_device; 268 bluetooth::BluetoothDeviceToApiDevice(device, &extension_device); 269 GetEventRouter(GetProfile())->DispatchDeviceEvent( 270 extensions::event_names::kBluetoothOnDeviceSearchResult, 271 extension_device); 272 273 device_events_sent_++; 274 } 275 276 void BluetoothGetDevicesFunction::FinishDeviceSearch() { 277 scoped_ptr<base::ListValue> args(new base::ListValue()); 278 scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue()); 279 info->SetInteger("expectedEventCount", device_events_sent_); 280 args->Append(info.release()); 281 282 scoped_ptr<extensions::Event> event(new extensions::Event( 283 extensions::event_names::kBluetoothOnDeviceSearchFinished, args.Pass())); 284 extensions::ExtensionSystem::Get(GetProfile()) 285 ->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(GetProfile())->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(GetProfile())->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(GetProfile())->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(GetProfile())->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(new base::FundamentalValue( 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(GetProfile())->SetResponsibleForDiscovery(false); 627 SendResponse(false); 628 GetEventRouter(GetProfile())->OnListenerRemoved(); 629 } 630 631 bool BluetoothStartDiscoveryFunction::DoWork( 632 scoped_refptr<BluetoothAdapter> adapter) { 633 GetEventRouter(GetProfile())->SetSendDiscoveryEvents(true); 634 635 // If this profile is already discovering devices, there should be nothing 636 // else to do. 637 if (!GetEventRouter(GetProfile())->IsResponsibleForDiscovery()) { 638 GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true); 639 GetEventRouter(GetProfile())->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(GetProfile())->OnListenerRemoved(); 651 } 652 653 void BluetoothStopDiscoveryFunction::OnErrorCallback() { 654 SetError(kStopDiscoveryFailed); 655 GetEventRouter(GetProfile())->SetResponsibleForDiscovery(true); 656 SendResponse(false); 657 GetEventRouter(GetProfile())->OnListenerRemoved(); 658 } 659 660 bool BluetoothStopDiscoveryFunction::DoWork( 661 scoped_refptr<BluetoothAdapter> adapter) { 662 GetEventRouter(GetProfile())->SetSendDiscoveryEvents(false); 663 if (GetEventRouter(GetProfile())->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