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 "chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_api.h" 6 7 #include "base/bind.h" 8 #include "base/lazy_instance.h" 9 #include "base/strings/stringprintf.h" 10 #include "chrome/browser/extensions/api/bluetooth_low_energy/utils.h" 11 #include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h" 12 #include "chrome/common/extensions/api/bluetooth_low_energy.h" 13 #include "content/public/browser/browser_thread.h" 14 #include "extensions/browser/event_router.h" 15 #include "extensions/common/permissions/permissions_data.h" 16 17 using content::BrowserContext; 18 using content::BrowserThread; 19 20 namespace apibtle = extensions::api::bluetooth_low_energy; 21 22 namespace extensions { 23 24 namespace { 25 26 const char kErrorAdapterNotInitialized[] = 27 "Could not initialize Bluetooth adapter"; 28 const char kErrorAlreadyConnected[] = "Already connected"; 29 const char kErrorAlreadyNotifying[] = "Already notifying"; 30 const char kErrorInProgress[] = "In progress"; 31 const char kErrorNotConnected[] = "Not connected"; 32 const char kErrorNotNotifying[] = "Not notifying"; 33 const char kErrorNotFound[] = "Instance not found"; 34 const char kErrorOperationFailed[] = "Operation failed"; 35 const char kErrorPermissionDenied[] = "Permission denied"; 36 const char kErrorPlatformNotSupported[] = 37 "This operation is not supported on the current platform"; 38 39 // Returns the correct error string based on error status |status|. This is used 40 // to set the value of |chrome.runtime.lastError.message| and should not be 41 // passed |BluetoothLowEnergyEventRouter::kStatusSuccess|. 42 std::string StatusToString(BluetoothLowEnergyEventRouter::Status status) { 43 switch (status) { 44 case BluetoothLowEnergyEventRouter::kStatusErrorPermissionDenied: 45 return kErrorPermissionDenied; 46 case BluetoothLowEnergyEventRouter::kStatusErrorNotFound: 47 return kErrorNotFound; 48 case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyConnected: 49 return kErrorAlreadyConnected; 50 case BluetoothLowEnergyEventRouter::kStatusErrorAlreadyNotifying: 51 return kErrorAlreadyNotifying; 52 case BluetoothLowEnergyEventRouter::kStatusErrorNotConnected: 53 return kErrorNotConnected; 54 case BluetoothLowEnergyEventRouter::kStatusErrorNotNotifying: 55 return kErrorNotNotifying; 56 case BluetoothLowEnergyEventRouter::kStatusErrorInProgress: 57 return kErrorInProgress; 58 case BluetoothLowEnergyEventRouter::kStatusSuccess: 59 NOTREACHED(); 60 break; 61 default: 62 return kErrorOperationFailed; 63 } 64 return ""; 65 } 66 67 extensions::BluetoothLowEnergyEventRouter* GetEventRouter( 68 BrowserContext* context) { 69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 70 return extensions::BluetoothLowEnergyAPI::Get(context)->event_router(); 71 } 72 73 void DoWorkCallback(const base::Callback<bool()>& callback) { 74 DCHECK(!callback.is_null()); 75 callback.Run(); 76 } 77 78 } // namespace 79 80 81 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI> > 82 g_factory = LAZY_INSTANCE_INITIALIZER; 83 84 // static 85 BrowserContextKeyedAPIFactory<BluetoothLowEnergyAPI>* 86 BluetoothLowEnergyAPI::GetFactoryInstance() { 87 return g_factory.Pointer(); 88 } 89 90 // static 91 BluetoothLowEnergyAPI* BluetoothLowEnergyAPI::Get(BrowserContext* context) { 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 93 return GetFactoryInstance()->Get(context); 94 } 95 96 BluetoothLowEnergyAPI::BluetoothLowEnergyAPI(BrowserContext* context) 97 : event_router_(new BluetoothLowEnergyEventRouter(context)), 98 browser_context_(context) { 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 100 } 101 102 BluetoothLowEnergyAPI::~BluetoothLowEnergyAPI() { 103 } 104 105 void BluetoothLowEnergyAPI::Shutdown() { 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 107 } 108 109 namespace api { 110 111 BluetoothLowEnergyExtensionFunction::BluetoothLowEnergyExtensionFunction() { 112 } 113 114 BluetoothLowEnergyExtensionFunction::~BluetoothLowEnergyExtensionFunction() { 115 } 116 117 bool BluetoothLowEnergyExtensionFunction::RunAsync() { 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 119 120 if (!BluetoothManifestData::CheckLowEnergyPermitted(GetExtension())) { 121 error_ = kErrorPermissionDenied; 122 return false; 123 } 124 125 BluetoothLowEnergyEventRouter* event_router = 126 GetEventRouter(browser_context()); 127 if (!event_router->IsBluetoothSupported()) { 128 SetError(kErrorPlatformNotSupported); 129 return false; 130 } 131 132 // It is safe to pass |this| here as ExtensionFunction is refcounted. 133 if (!event_router->InitializeAdapterAndInvokeCallback(base::Bind( 134 &DoWorkCallback, 135 base::Bind(&BluetoothLowEnergyExtensionFunction::DoWork, this)))) { 136 SetError(kErrorAdapterNotInitialized); 137 return false; 138 } 139 140 return true; 141 } 142 143 bool BluetoothLowEnergyConnectFunction::DoWork() { 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 145 146 BluetoothLowEnergyEventRouter* event_router = 147 GetEventRouter(browser_context()); 148 149 // The adapter must be initialized at this point, but return an error instead 150 // of asserting. 151 if (!event_router->HasAdapter()) { 152 SetError(kErrorAdapterNotInitialized); 153 SendResponse(false); 154 return false; 155 } 156 157 scoped_ptr<apibtle::Connect::Params> params( 158 apibtle::Connect::Params::Create(*args_)); 159 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 160 161 bool persistent = false; // Not persistent by default. 162 apibtle::ConnectProperties* properties = params.get()->properties.get(); 163 if (properties) 164 persistent = properties->persistent; 165 166 event_router->Connect( 167 persistent, 168 GetExtension(), 169 params->device_address, 170 base::Bind(&BluetoothLowEnergyConnectFunction::SuccessCallback, this), 171 base::Bind(&BluetoothLowEnergyConnectFunction::ErrorCallback, this)); 172 173 return true; 174 } 175 176 void BluetoothLowEnergyConnectFunction::SuccessCallback() { 177 SendResponse(true); 178 } 179 180 void BluetoothLowEnergyConnectFunction::ErrorCallback( 181 BluetoothLowEnergyEventRouter::Status status) { 182 SetError(StatusToString(status)); 183 SendResponse(false); 184 } 185 186 bool BluetoothLowEnergyDisconnectFunction::DoWork() { 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 188 189 BluetoothLowEnergyEventRouter* event_router = 190 GetEventRouter(browser_context()); 191 192 // The adapter must be initialized at this point, but return an error instead 193 // of asserting. 194 if (!event_router->HasAdapter()) { 195 SetError(kErrorAdapterNotInitialized); 196 SendResponse(false); 197 return false; 198 } 199 200 scoped_ptr<apibtle::Disconnect::Params> params( 201 apibtle::Disconnect::Params::Create(*args_)); 202 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 203 204 event_router->Disconnect( 205 GetExtension(), 206 params->device_address, 207 base::Bind(&BluetoothLowEnergyDisconnectFunction::SuccessCallback, this), 208 base::Bind(&BluetoothLowEnergyDisconnectFunction::ErrorCallback, this)); 209 210 return true; 211 } 212 213 void BluetoothLowEnergyDisconnectFunction::SuccessCallback() { 214 SendResponse(true); 215 } 216 217 void BluetoothLowEnergyDisconnectFunction::ErrorCallback( 218 BluetoothLowEnergyEventRouter::Status status) { 219 SetError(StatusToString(status)); 220 SendResponse(false); 221 } 222 223 bool BluetoothLowEnergyGetServiceFunction::DoWork() { 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 225 226 BluetoothLowEnergyEventRouter* event_router = 227 GetEventRouter(browser_context()); 228 229 // The adapter must be initialized at this point, but return an error instead 230 // of asserting. 231 if (!event_router->HasAdapter()) { 232 SetError(kErrorAdapterNotInitialized); 233 SendResponse(false); 234 return false; 235 } 236 237 scoped_ptr<apibtle::GetService::Params> params( 238 apibtle::GetService::Params::Create(*args_)); 239 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 240 241 apibtle::Service service; 242 BluetoothLowEnergyEventRouter::Status status = 243 event_router->GetService(params->service_id, &service); 244 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 245 SetError(StatusToString(status)); 246 SendResponse(false); 247 return false; 248 } 249 250 results_ = apibtle::GetService::Results::Create(service); 251 SendResponse(true); 252 253 return true; 254 } 255 256 bool BluetoothLowEnergyGetServicesFunction::DoWork() { 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 258 259 BluetoothLowEnergyEventRouter* event_router = 260 GetEventRouter(browser_context()); 261 262 // The adapter must be initialized at this point, but return an error instead 263 // of asserting. 264 if (!event_router->HasAdapter()) { 265 SetError(kErrorAdapterNotInitialized); 266 SendResponse(false); 267 return false; 268 } 269 270 scoped_ptr<apibtle::GetServices::Params> params( 271 apibtle::GetServices::Params::Create(*args_)); 272 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 273 274 BluetoothLowEnergyEventRouter::ServiceList service_list; 275 if (!event_router->GetServices(params->device_address, &service_list)) { 276 SetError(kErrorNotFound); 277 SendResponse(false); 278 return false; 279 } 280 281 results_ = apibtle::GetServices::Results::Create(service_list); 282 SendResponse(true); 283 284 return true; 285 } 286 287 bool BluetoothLowEnergyGetCharacteristicFunction::DoWork() { 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 289 290 BluetoothLowEnergyEventRouter* event_router = 291 GetEventRouter(browser_context()); 292 293 // The adapter must be initialized at this point, but return an error instead 294 // of asserting. 295 if (!event_router->HasAdapter()) { 296 SetError(kErrorAdapterNotInitialized); 297 SendResponse(false); 298 return false; 299 } 300 301 scoped_ptr<apibtle::GetCharacteristic::Params> params( 302 apibtle::GetCharacteristic::Params::Create(*args_)); 303 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 304 305 apibtle::Characteristic characteristic; 306 BluetoothLowEnergyEventRouter::Status status = 307 event_router->GetCharacteristic( 308 GetExtension(), params->characteristic_id, &characteristic); 309 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 310 SetError(StatusToString(status)); 311 SendResponse(false); 312 return false; 313 } 314 315 // Manually construct the result instead of using 316 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of 317 // enums correctly. 318 SetResult(apibtle::CharacteristicToValue(&characteristic).release()); 319 SendResponse(true); 320 321 return true; 322 } 323 324 bool BluetoothLowEnergyGetCharacteristicsFunction::DoWork() { 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 326 327 BluetoothLowEnergyEventRouter* event_router = 328 GetEventRouter(browser_context()); 329 330 // The adapter must be initialized at this point, but return an error instead 331 // of asserting. 332 if (!event_router->HasAdapter()) { 333 SetError(kErrorAdapterNotInitialized); 334 SendResponse(false); 335 return false; 336 } 337 338 scoped_ptr<apibtle::GetCharacteristics::Params> params( 339 apibtle::GetCharacteristics::Params::Create(*args_)); 340 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 341 342 BluetoothLowEnergyEventRouter::CharacteristicList characteristic_list; 343 BluetoothLowEnergyEventRouter::Status status = 344 event_router->GetCharacteristics( 345 GetExtension(), params->service_id, &characteristic_list); 346 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 347 SetError(StatusToString(status)); 348 SendResponse(false); 349 return false; 350 } 351 352 // Manually construct the result instead of using 353 // apibtle::GetCharacteristics::Result::Create as it doesn't convert lists of 354 // enums correctly. 355 scoped_ptr<base::ListValue> result(new base::ListValue()); 356 for (BluetoothLowEnergyEventRouter::CharacteristicList::iterator iter = 357 characteristic_list.begin(); 358 iter != characteristic_list.end(); 359 ++iter) 360 result->Append(apibtle::CharacteristicToValue(iter->get()).release()); 361 362 SetResult(result.release()); 363 SendResponse(true); 364 365 return true; 366 } 367 368 bool BluetoothLowEnergyGetIncludedServicesFunction::DoWork() { 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 370 371 BluetoothLowEnergyEventRouter* event_router = 372 GetEventRouter(browser_context()); 373 374 // The adapter must be initialized at this point, but return an error instead 375 // of asserting. 376 if (!event_router->HasAdapter()) { 377 SetError(kErrorAdapterNotInitialized); 378 SendResponse(false); 379 return false; 380 } 381 382 scoped_ptr<apibtle::GetIncludedServices::Params> params( 383 apibtle::GetIncludedServices::Params::Create(*args_)); 384 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 385 386 BluetoothLowEnergyEventRouter::ServiceList service_list; 387 BluetoothLowEnergyEventRouter::Status status = 388 event_router->GetIncludedServices(params->service_id, &service_list); 389 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 390 SetError(StatusToString(status)); 391 SendResponse(false); 392 return false; 393 } 394 395 results_ = apibtle::GetIncludedServices::Results::Create(service_list); 396 SendResponse(true); 397 398 return true; 399 } 400 401 bool BluetoothLowEnergyGetDescriptorFunction::DoWork() { 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 403 404 BluetoothLowEnergyEventRouter* event_router = 405 GetEventRouter(browser_context()); 406 407 // The adapter must be initialized at this point, but return an error instead 408 // of asserting. 409 if (!event_router->HasAdapter()) { 410 SetError(kErrorAdapterNotInitialized); 411 SendResponse(false); 412 return false; 413 } 414 415 scoped_ptr<apibtle::GetDescriptor::Params> params( 416 apibtle::GetDescriptor::Params::Create(*args_)); 417 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 418 419 apibtle::Descriptor descriptor; 420 BluetoothLowEnergyEventRouter::Status status = event_router->GetDescriptor( 421 GetExtension(), params->descriptor_id, &descriptor); 422 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 423 SetError(StatusToString(status)); 424 SendResponse(false); 425 return false; 426 } 427 428 // Manually construct the result instead of using 429 // apibtle::GetDescriptor::Result::Create as it doesn't convert lists of enums 430 // correctly. 431 SetResult(apibtle::DescriptorToValue(&descriptor).release()); 432 SendResponse(true); 433 434 return true; 435 } 436 437 bool BluetoothLowEnergyGetDescriptorsFunction::DoWork() { 438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 439 440 BluetoothLowEnergyEventRouter* event_router = 441 GetEventRouter(browser_context()); 442 443 // The adapter must be initialized at this point, but return an error instead 444 // of asserting. 445 if (!event_router->HasAdapter()) { 446 SetError(kErrorAdapterNotInitialized); 447 SendResponse(false); 448 return false; 449 } 450 451 scoped_ptr<apibtle::GetDescriptors::Params> params( 452 apibtle::GetDescriptors::Params::Create(*args_)); 453 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 454 455 BluetoothLowEnergyEventRouter::DescriptorList descriptor_list; 456 BluetoothLowEnergyEventRouter::Status status = event_router->GetDescriptors( 457 GetExtension(), params->characteristic_id, &descriptor_list); 458 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 459 SetError(StatusToString(status)); 460 SendResponse(false); 461 return false; 462 } 463 464 // Manually construct the result instead of using 465 // apibtle::GetDescriptors::Result::Create as it doesn't convert lists of 466 // enums correctly. 467 scoped_ptr<base::ListValue> result(new base::ListValue()); 468 for (BluetoothLowEnergyEventRouter::DescriptorList::iterator iter = 469 descriptor_list.begin(); 470 iter != descriptor_list.end(); 471 ++iter) 472 result->Append(apibtle::DescriptorToValue(iter->get()).release()); 473 474 SetResult(result.release()); 475 SendResponse(true); 476 477 return true; 478 } 479 480 bool BluetoothLowEnergyReadCharacteristicValueFunction::DoWork() { 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 482 483 BluetoothLowEnergyEventRouter* event_router = 484 GetEventRouter(browser_context()); 485 486 // The adapter must be initialized at this point, but return an error instead 487 // of asserting. 488 if (!event_router->HasAdapter()) { 489 SetError(kErrorAdapterNotInitialized); 490 SendResponse(false); 491 return false; 492 } 493 494 scoped_ptr<apibtle::ReadCharacteristicValue::Params> params( 495 apibtle::ReadCharacteristicValue::Params::Create(*args_)); 496 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 497 498 instance_id_ = params->characteristic_id; 499 event_router->ReadCharacteristicValue( 500 GetExtension(), 501 instance_id_, 502 base::Bind( 503 &BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback, 504 this), 505 base::Bind( 506 &BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback, 507 this)); 508 509 return true; 510 } 511 512 void BluetoothLowEnergyReadCharacteristicValueFunction::SuccessCallback() { 513 // Obtain info on the characteristic and see whether or not the characteristic 514 // is still around. 515 apibtle::Characteristic characteristic; 516 BluetoothLowEnergyEventRouter::Status status = 517 GetEventRouter(browser_context()) 518 ->GetCharacteristic(GetExtension(), instance_id_, &characteristic); 519 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 520 SetError(StatusToString(status)); 521 SendResponse(false); 522 return; 523 } 524 525 // Manually construct the result instead of using 526 // apibtle::GetCharacteristic::Result::Create as it doesn't convert lists of 527 // enums correctly. 528 SetResult(apibtle::CharacteristicToValue(&characteristic).release()); 529 SendResponse(true); 530 } 531 532 void BluetoothLowEnergyReadCharacteristicValueFunction::ErrorCallback( 533 BluetoothLowEnergyEventRouter::Status status) { 534 SetError(StatusToString(status)); 535 SendResponse(false); 536 } 537 538 bool BluetoothLowEnergyWriteCharacteristicValueFunction::DoWork() { 539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 540 541 BluetoothLowEnergyEventRouter* event_router = 542 GetEventRouter(browser_context()); 543 544 // The adapter must be initialized at this point, but return an error instead 545 // of asserting. 546 if (!event_router->HasAdapter()) { 547 SetError(kErrorAdapterNotInitialized); 548 SendResponse(false); 549 return false; 550 } 551 552 scoped_ptr<apibtle::WriteCharacteristicValue::Params> params( 553 apibtle::WriteCharacteristicValue::Params::Create(*args_)); 554 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 555 556 std::vector<uint8> value(params->value.begin(), params->value.end()); 557 event_router->WriteCharacteristicValue( 558 GetExtension(), 559 params->characteristic_id, 560 value, 561 base::Bind( 562 &BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback, 563 this), 564 base::Bind( 565 &BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback, 566 this)); 567 568 return true; 569 } 570 571 void BluetoothLowEnergyWriteCharacteristicValueFunction::SuccessCallback() { 572 results_ = apibtle::WriteCharacteristicValue::Results::Create(); 573 SendResponse(true); 574 } 575 576 void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback( 577 BluetoothLowEnergyEventRouter::Status status) { 578 SetError(StatusToString(status)); 579 SendResponse(false); 580 } 581 582 bool BluetoothLowEnergyStartCharacteristicNotificationsFunction::DoWork() { 583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 584 585 BluetoothLowEnergyEventRouter* event_router = 586 GetEventRouter(browser_context()); 587 588 // The adapter must be initialized at this point, but return an error instead 589 // of asserting. 590 if (!event_router->HasAdapter()) { 591 SetError(kErrorAdapterNotInitialized); 592 SendResponse(false); 593 return false; 594 } 595 596 scoped_ptr<apibtle::StartCharacteristicNotifications::Params> params( 597 apibtle::StartCharacteristicNotifications::Params::Create(*args_)); 598 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 599 600 bool persistent = false; // Not persistent by default. 601 apibtle::NotificationProperties* properties = params.get()->properties.get(); 602 if (properties) 603 persistent = properties->persistent; 604 605 event_router->StartCharacteristicNotifications( 606 persistent, 607 GetExtension(), 608 params->characteristic_id, 609 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction:: 610 SuccessCallback, 611 this), 612 base::Bind(&BluetoothLowEnergyStartCharacteristicNotificationsFunction:: 613 ErrorCallback, 614 this)); 615 616 return true; 617 } 618 619 void 620 BluetoothLowEnergyStartCharacteristicNotificationsFunction::SuccessCallback() { 621 SendResponse(true); 622 } 623 624 void BluetoothLowEnergyStartCharacteristicNotificationsFunction::ErrorCallback( 625 BluetoothLowEnergyEventRouter::Status status) { 626 SetError(StatusToString(status)); 627 SendResponse(false); 628 } 629 630 bool BluetoothLowEnergyStopCharacteristicNotificationsFunction::DoWork() { 631 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 632 633 BluetoothLowEnergyEventRouter* event_router = 634 GetEventRouter(browser_context()); 635 636 // The adapter must be initialized at this point, but return an error instead 637 // of asserting. 638 if (!event_router->HasAdapter()) { 639 SetError(kErrorAdapterNotInitialized); 640 SendResponse(false); 641 return false; 642 } 643 644 scoped_ptr<apibtle::StopCharacteristicNotifications::Params> params( 645 apibtle::StopCharacteristicNotifications::Params::Create(*args_)); 646 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 647 648 event_router->StopCharacteristicNotifications( 649 GetExtension(), 650 params->characteristic_id, 651 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction:: 652 SuccessCallback, 653 this), 654 base::Bind(&BluetoothLowEnergyStopCharacteristicNotificationsFunction:: 655 ErrorCallback, 656 this)); 657 658 return true; 659 } 660 661 void 662 BluetoothLowEnergyStopCharacteristicNotificationsFunction::SuccessCallback() { 663 SendResponse(true); 664 } 665 666 void BluetoothLowEnergyStopCharacteristicNotificationsFunction::ErrorCallback( 667 BluetoothLowEnergyEventRouter::Status status) { 668 SetError(StatusToString(status)); 669 SendResponse(false); 670 } 671 672 bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() { 673 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 674 675 BluetoothLowEnergyEventRouter* event_router = 676 GetEventRouter(browser_context()); 677 678 // The adapter must be initialized at this point, but return an error instead 679 // of asserting. 680 if (!event_router->HasAdapter()) { 681 SetError(kErrorAdapterNotInitialized); 682 SendResponse(false); 683 return false; 684 } 685 686 scoped_ptr<apibtle::ReadDescriptorValue::Params> params( 687 apibtle::ReadDescriptorValue::Params::Create(*args_)); 688 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 689 690 instance_id_ = params->descriptor_id; 691 event_router->ReadDescriptorValue( 692 GetExtension(), 693 instance_id_, 694 base::Bind( 695 &BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback, 696 this), 697 base::Bind(&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback, 698 this)); 699 700 return true; 701 } 702 703 void BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback() { 704 // Obtain info on the descriptor and see whether or not the descriptor is 705 // still around. 706 apibtle::Descriptor descriptor; 707 BluetoothLowEnergyEventRouter::Status status = 708 GetEventRouter(browser_context()) 709 ->GetDescriptor(GetExtension(), instance_id_, &descriptor); 710 if (status != BluetoothLowEnergyEventRouter::kStatusSuccess) { 711 SetError(StatusToString(status)); 712 SendResponse(false); 713 return; 714 } 715 716 // Manually construct the result instead of using 717 // apibtle::GetDescriptor::Results::Create as it doesn't convert lists of 718 // enums correctly. 719 SetResult(apibtle::DescriptorToValue(&descriptor).release()); 720 SendResponse(true); 721 } 722 723 void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback( 724 BluetoothLowEnergyEventRouter::Status status) { 725 SetError(StatusToString(status)); 726 SendResponse(false); 727 } 728 729 bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() { 730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 731 732 BluetoothLowEnergyEventRouter* event_router = 733 GetEventRouter(browser_context()); 734 735 // The adapter must be initialized at this point, but return an error instead 736 // of asserting. 737 if (!event_router->HasAdapter()) { 738 SetError(kErrorAdapterNotInitialized); 739 SendResponse(false); 740 return false; 741 } 742 743 scoped_ptr<apibtle::WriteDescriptorValue::Params> params( 744 apibtle::WriteDescriptorValue::Params::Create(*args_)); 745 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 746 747 std::vector<uint8> value(params->value.begin(), params->value.end()); 748 event_router->WriteDescriptorValue( 749 GetExtension(), 750 params->descriptor_id, 751 value, 752 base::Bind( 753 &BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback, 754 this), 755 base::Bind(&BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback, 756 this)); 757 758 return true; 759 } 760 761 void BluetoothLowEnergyWriteDescriptorValueFunction::SuccessCallback() { 762 results_ = apibtle::WriteDescriptorValue::Results::Create(); 763 SendResponse(true); 764 } 765 766 void BluetoothLowEnergyWriteDescriptorValueFunction::ErrorCallback( 767 BluetoothLowEnergyEventRouter::Status status) { 768 SetError(StatusToString(status)); 769 SendResponse(false); 770 } 771 772 } // namespace api 773 } // namespace extensions 774