 Chromium Code Reviews
 Chromium Code Reviews Issue 1397983004:
  bluetooth: Refactor repeated code used to find a Bluetooth object from its ID.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@bluetooth-characteristic-changed-1
    
  
    Issue 1397983004:
  bluetooth: Refactor repeated code used to find a Bluetooth object from its ID.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@bluetooth-characteristic-changed-1| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 // NETWORK_ERROR Note: | |
| 6 // When a device can't be found in the BluetoothAdapter, that generally | |
| 7 // indicates that it's gone out of range. We reject with a NetworkError in that | |
| 8 // case. | |
| 9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne ctgatt | |
| 10 | |
| 11 // ID Not In Map Note: | 5 // ID Not In Map Note: | 
| 12 // A service, characteristic, or descriptor ID not in the corresponding | 6 // A service, characteristic, or descriptor ID not in the corresponding | 
| 13 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 
| 14 // descriptor_to_characteristic_] implies a hostile renderer because a renderer | 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer | 
| 15 // obtains the corresponding ID from this class and it will be added to the map | 9 // obtains the corresponding ID from this class and it will be added to the map | 
| 16 // at that time. | 10 // at that time. | 
| 17 | 11 | 
| 18 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 12 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 
| 19 | 13 | 
| 20 #include "base/bind.h" | 14 #include "base/bind.h" | 
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 } | 270 } | 
| 277 | 271 | 
| 278 const int thread_id; | 272 const int thread_id; | 
| 279 const int request_id; | 273 const int request_id; | 
| 280 const std::vector<BluetoothScanFilter> filters; | 274 const std::vector<BluetoothScanFilter> filters; | 
| 281 const std::vector<BluetoothUUID> optional_services; | 275 const std::vector<BluetoothUUID> optional_services; | 
| 282 scoped_ptr<BluetoothChooser> chooser; | 276 scoped_ptr<BluetoothChooser> chooser; | 
| 283 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 277 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 
| 284 }; | 278 }; | 
| 285 | 279 | 
| 280 struct BluetoothDispatcherHost::CacheQueryResult { | |
| 281 CacheQueryResult() | |
| 282 : device(nullptr), | |
| 283 service(nullptr), | |
| 284 characteristic(nullptr), | |
| 285 outcome(CacheQueryOutcome::SUCCESS) {} | |
| 286 ~CacheQueryResult() {} | |
| 287 void SetError(CacheQueryOutcome error_outcome) { | |
| 288 outcome = error_outcome; | |
| 289 switch (error_outcome) { | |
| 290 case CacheQueryOutcome::NO_DEVICE: | |
| 291 error = WebBluetoothError::DeviceNoLongerInRange; | |
| 292 return; | |
| 293 case CacheQueryOutcome::NO_SERVICE: | |
| 294 error = WebBluetoothError::ServiceNoLongerExists; | |
| 295 return; | |
| 296 case CacheQueryOutcome::NO_CHARACTERISTIC: | |
| 297 error = WebBluetoothError::CharacteristicNoLongerExists; | |
| 298 return; | |
| 299 case CacheQueryOutcome::SUCCESS: | |
| 300 return; | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 device::BluetoothDevice* device; | |
| 305 device::BluetoothGattService* service; | |
| 306 device::BluetoothGattCharacteristic* characteristic; | |
| 307 CacheQueryOutcome outcome; | |
| 308 blink::WebBluetoothError error; | |
| 
scheib
2015/10/19 23:15:54
Instead of storing 'error', just have an accessor
 
ortuno
2015/10/20 17:44:03
Done.
 | |
| 309 }; | |
| 310 | |
| 286 void BluetoothDispatcherHost::set_adapter( | 311 void BluetoothDispatcherHost::set_adapter( | 
| 287 scoped_refptr<device::BluetoothAdapter> adapter) { | 312 scoped_refptr<device::BluetoothAdapter> adapter) { | 
| 288 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 313 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 289 connections_.clear(); | 314 connections_.clear(); | 
| 290 if (adapter_.get()) | 315 if (adapter_.get()) | 
| 291 adapter_->RemoveObserver(this); | 316 adapter_->RemoveObserver(this); | 
| 292 adapter_ = adapter; | 317 adapter_ = adapter; | 
| 293 if (adapter_.get()) | 318 if (adapter_.get()) | 
| 294 adapter_->AddObserver(this); | 319 adapter_->AddObserver(this); | 
| 295 } | 320 } | 
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 int request_id, | 535 int request_id, | 
| 511 const std::string& device_instance_id) { | 536 const std::string& device_instance_id) { | 
| 512 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 537 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 513 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 538 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 
| 514 const base::TimeTicks start_time = base::TimeTicks::Now(); | 539 const base::TimeTicks start_time = base::TimeTicks::Now(); | 
| 515 | 540 | 
| 516 // TODO(ortuno): Right now it's pointless to check if the domain has access to | 541 // TODO(ortuno): Right now it's pointless to check if the domain has access to | 
| 517 // the device, because any domain can connect to any device. But once | 542 // the device, because any domain can connect to any device. But once | 
| 518 // permissions are implemented we should check that the domain has access to | 543 // permissions are implemented we should check that the domain has access to | 
| 519 // the device. https://crbug.com/484745 | 544 // the device. https://crbug.com/484745 | 
| 520 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 545 | 
| 521 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 546 CacheQueryResult query_result = CacheQueryResult(); | 
| 522 RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); | 547 QueryCacheForDevice(device_instance_id, query_result); | 
| 523 Send(new BluetoothMsg_ConnectGATTError( | 548 | 
| 524 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 549 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 550 RecordOutcomeWithCacheQueryResult(UMAWebBluetoothFunction::CONNECT_GATT, | |
| 551 query_result.outcome); | |
| 552 Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id, | |
| 553 query_result.error)); | |
| 525 return; | 554 return; | 
| 526 } | 555 } | 
| 527 device->CreateGattConnection( | 556 | 
| 557 query_result.device->CreateGattConnection( | |
| 528 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 558 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 
| 529 weak_ptr_on_ui_thread_, thread_id, request_id, | 559 weak_ptr_on_ui_thread_, thread_id, request_id, | 
| 530 device_instance_id, start_time), | 560 device_instance_id, start_time), | 
| 531 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 561 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 
| 532 weak_ptr_on_ui_thread_, thread_id, request_id, | 562 weak_ptr_on_ui_thread_, thread_id, request_id, | 
| 533 device_instance_id, start_time)); | 563 device_instance_id, start_time)); | 
| 534 } | 564 } | 
| 535 | 565 | 
| 536 void BluetoothDispatcherHost::OnGetPrimaryService( | 566 void BluetoothDispatcherHost::OnGetPrimaryService( | 
| 537 int thread_id, | 567 int thread_id, | 
| (...skipping 20 matching lines...) Expand all Loading... | |
| 558 | 588 | 
| 559 void BluetoothDispatcherHost::OnGetCharacteristic( | 589 void BluetoothDispatcherHost::OnGetCharacteristic( | 
| 560 int thread_id, | 590 int thread_id, | 
| 561 int request_id, | 591 int request_id, | 
| 562 const std::string& service_instance_id, | 592 const std::string& service_instance_id, | 
| 563 const std::string& characteristic_uuid) { | 593 const std::string& characteristic_uuid) { | 
| 564 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 594 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 565 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 595 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 
| 566 RecordGetCharacteristicCharacteristic(characteristic_uuid); | 596 RecordGetCharacteristicCharacteristic(characteristic_uuid); | 
| 567 | 597 | 
| 568 auto device_iter = service_to_device_.find(service_instance_id); | 598 CacheQueryResult query_result = CacheQueryResult(); | 
| 569 // Kill the renderer, see "ID Not In Map Note" above. | 599 if (QueryCacheForService(service_instance_id, query_result)) { | 
| 
scheib
2015/10/19 23:15:54
Just feels like it should be
if(!QueryCache...)
 
ortuno
2015/10/20 17:44:03
Removed the confusing return value and added an en
 | |
| 570 if (device_iter == service_to_device_.end()) { | |
| 571 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | |
| 572 return; | 600 return; | 
| 573 } | 601 } | 
| 574 | 602 | 
| 575 // TODO(ortuno): Check if domain has access to device. | 603 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 576 // https://crbug.com/493459 | 604 RecordOutcomeWithCacheQueryResult( | 
| 
scheib
2015/10/19 23:15:54
We already have to list the specific function (e.g
 
ortuno
2015/10/20 17:44:03
Done.
 | |
| 577 device::BluetoothDevice* device = | 605 UMAWebBluetoothFunction::GET_CHARACTERISTIC, query_result.outcome); | 
| 578 adapter_->GetDevice(device_iter->second /* device_instance_id */); | 606 Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id, | 
| 579 | 607 query_result.error)); | 
| 580 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | |
| 581 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE); | |
| 582 Send(new BluetoothMsg_GetCharacteristicError( | |
| 583 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | |
| 584 return; | |
| 585 } | |
| 586 | |
| 587 // TODO(ortuno): Check if domain has access to service | |
| 588 // http://crbug.com/493460 | |
| 589 device::BluetoothGattService* service = | |
| 590 device->GetGattService(service_instance_id); | |
| 591 if (!service) { | |
| 592 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_SERVICE); | |
| 593 Send(new BluetoothMsg_GetCharacteristicError( | |
| 594 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | |
| 595 return; | 608 return; | 
| 596 } | 609 } | 
| 597 | 610 | 
| 598 for (BluetoothGattCharacteristic* characteristic : | 611 for (BluetoothGattCharacteristic* characteristic : | 
| 599 service->GetCharacteristics()) { | 612 query_result.service->GetCharacteristics()) { | 
| 600 if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 613 if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 
| 601 const std::string& characteristic_instance_id = | 614 const std::string& characteristic_instance_id = | 
| 602 characteristic->GetIdentifier(); | 615 characteristic->GetIdentifier(); | 
| 603 | 616 | 
| 604 auto insert_result = characteristic_to_service_.insert( | 617 auto insert_result = characteristic_to_service_.insert( | 
| 605 make_pair(characteristic_instance_id, service_instance_id)); | 618 make_pair(characteristic_instance_id, service_instance_id)); | 
| 606 | 619 | 
| 607 // If value is already in map, DCHECK it's valid. | 620 // If value is already in map, DCHECK it's valid. | 
| 608 if (!insert_result.second) | 621 if (!insert_result.second) | 
| 609 DCHECK(insert_result.first->second == service_instance_id); | 622 DCHECK(insert_result.first->second == service_instance_id); | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 622 } | 635 } | 
| 623 | 636 | 
| 624 void BluetoothDispatcherHost::OnReadValue( | 637 void BluetoothDispatcherHost::OnReadValue( | 
| 625 int thread_id, | 638 int thread_id, | 
| 626 int request_id, | 639 int request_id, | 
| 627 const std::string& characteristic_instance_id) { | 640 const std::string& characteristic_instance_id) { | 
| 628 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 641 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 629 RecordWebBluetoothFunctionCall( | 642 RecordWebBluetoothFunctionCall( | 
| 630 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 643 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 
| 631 | 644 | 
| 632 auto characteristic_iter = | 645 CacheQueryResult query_result = CacheQueryResult(); | 
| 633 characteristic_to_service_.find(characteristic_instance_id); | 646 if (QueryCacheForCharacteristic(characteristic_instance_id, query_result)) { | 
| 634 | |
| 635 // Kill the renderer, see "ID Not In Map Note" above. | |
| 636 if (characteristic_iter == characteristic_to_service_.end()) { | |
| 637 bad_message::ReceivedBadMessage(this, | |
| 638 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | |
| 639 return; | |
| 640 } | |
| 641 const std::string& service_instance_id = characteristic_iter->second; | |
| 642 | |
| 643 auto device_iter = service_to_device_.find(service_instance_id); | |
| 644 | |
| 645 CHECK(device_iter != service_to_device_.end()); | |
| 646 | |
| 647 device::BluetoothDevice* device = | |
| 648 adapter_->GetDevice(device_iter->second /* device_instance_id */); | |
| 649 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | |
| 650 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | |
| 651 Send(new BluetoothMsg_ReadCharacteristicValueError( | |
| 652 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | |
| 653 return; | 647 return; | 
| 654 } | 648 } | 
| 655 | 649 | 
| 656 BluetoothGattService* service = device->GetGattService(service_instance_id); | 650 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 657 if (service == nullptr) { | 651 RecordOutcomeWithCacheQueryResult( | 
| 658 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | 652 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE, | 
| 659 Send(new BluetoothMsg_ReadCharacteristicValueError( | 653 query_result.outcome); | 
| 660 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 654 Send(new BluetoothMsg_ReadCharacteristicValueError(thread_id, request_id, | 
| 655 query_result.error)); | |
| 661 return; | 656 return; | 
| 662 } | 657 } | 
| 663 | 658 | 
| 664 BluetoothGattCharacteristic* characteristic = | 659 query_result.characteristic->ReadRemoteCharacteristic( | 
| 665 service->GetCharacteristic(characteristic_instance_id); | |
| 666 if (characteristic == nullptr) { | |
| 667 RecordCharacteristicReadValueOutcome( | |
| 668 UMAGATTOperationOutcome::NO_CHARACTERISTIC); | |
| 669 Send(new BluetoothMsg_ReadCharacteristicValueError( | |
| 670 thread_id, request_id, | |
| 671 WebBluetoothError::CharacteristicNoLongerExists)); | |
| 672 return; | |
| 673 } | |
| 674 | |
| 675 characteristic->ReadRemoteCharacteristic( | |
| 676 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 660 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 
| 677 weak_ptr_on_ui_thread_, thread_id, request_id), | 661 weak_ptr_on_ui_thread_, thread_id, request_id), | 
| 678 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 662 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 
| 679 weak_ptr_on_ui_thread_, thread_id, request_id)); | 663 weak_ptr_on_ui_thread_, thread_id, request_id)); | 
| 680 } | 664 } | 
| 681 | 665 | 
| 682 void BluetoothDispatcherHost::OnWriteValue( | 666 void BluetoothDispatcherHost::OnWriteValue( | 
| 683 int thread_id, | 667 int thread_id, | 
| 684 int request_id, | 668 int request_id, | 
| 685 const std::string& characteristic_instance_id, | 669 const std::string& characteristic_instance_id, | 
| 686 const std::vector<uint8_t>& value) { | 670 const std::vector<uint8_t>& value) { | 
| 687 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 671 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 688 RecordWebBluetoothFunctionCall( | 672 RecordWebBluetoothFunctionCall( | 
| 689 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | 673 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | 
| 690 | 674 | 
| 691 // Length check per step 3 of writeValue algorithm: | 675 // Length check per step 3 of writeValue algorithm: | 
| 692 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac teristic-writevalue | 676 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac teristic-writevalue | 
| 693 // We perform the length check on the renderer side. So if we | 677 // We perform the length check on the renderer side. So if we | 
| 694 // get a value with length > 512, we can assume it's a hostile | 678 // get a value with length > 512, we can assume it's a hostile | 
| 695 // renderer and kill it. | 679 // renderer and kill it. | 
| 696 if (value.size() > 512) { | 680 if (value.size() > 512) { | 
| 697 bad_message::ReceivedBadMessage( | 681 bad_message::ReceivedBadMessage( | 
| 698 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 682 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 
| 699 return; | 683 return; | 
| 700 } | 684 } | 
| 701 | 685 | 
| 702 auto characteristic_iter = | 686 CacheQueryResult query_result = CacheQueryResult(); | 
| 703 characteristic_to_service_.find(characteristic_instance_id); | 687 if (QueryCacheForCharacteristic(characteristic_instance_id, query_result)) { | 
| 704 | |
| 705 // Kill the renderer, see "ID Not In Map Note" above. | |
| 706 if (characteristic_iter == characteristic_to_service_.end()) { | |
| 707 bad_message::ReceivedBadMessage(this, | |
| 708 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | |
| 709 return; | |
| 710 } | |
| 711 const std::string& service_instance_id = characteristic_iter->second; | |
| 712 | |
| 713 auto device_iter = service_to_device_.find(service_instance_id); | |
| 714 | |
| 715 CHECK(device_iter != service_to_device_.end()); | |
| 716 | |
| 717 device::BluetoothDevice* device = | |
| 718 adapter_->GetDevice(device_iter->second /* device_instance_id */); | |
| 719 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | |
| 720 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | |
| 721 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
| 722 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | |
| 723 return; | 688 return; | 
| 724 } | 689 } | 
| 725 | 690 | 
| 726 BluetoothGattService* service = device->GetGattService(service_instance_id); | 691 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 727 if (service == nullptr) { | 692 RecordOutcomeWithCacheQueryResult( | 
| 728 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | 693 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE, | 
| 729 Send(new BluetoothMsg_WriteCharacteristicValueError( | 694 query_result.outcome); | 
| 730 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 695 Send(new BluetoothMsg_WriteCharacteristicValueError(thread_id, request_id, | 
| 696 query_result.error)); | |
| 731 return; | 697 return; | 
| 732 } | 698 } | 
| 733 | 699 | 
| 734 BluetoothGattCharacteristic* characteristic = | 700 query_result.characteristic->WriteRemoteCharacteristic( | 
| 735 service->GetCharacteristic(characteristic_instance_id); | |
| 736 if (characteristic == nullptr) { | |
| 737 RecordCharacteristicWriteValueOutcome( | |
| 738 UMAGATTOperationOutcome::NO_CHARACTERISTIC); | |
| 739 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
| 740 thread_id, request_id, | |
| 741 WebBluetoothError::CharacteristicNoLongerExists)); | |
| 742 return; | |
| 743 } | |
| 744 characteristic->WriteRemoteCharacteristic( | |
| 745 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | 701 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | 
| 746 weak_ptr_on_ui_thread_, thread_id, request_id), | 702 weak_ptr_on_ui_thread_, thread_id, request_id), | 
| 747 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 703 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 
| 748 weak_ptr_on_ui_thread_, thread_id, request_id)); | 704 weak_ptr_on_ui_thread_, thread_id, request_id)); | 
| 749 } | 705 } | 
| 750 | 706 | 
| 751 void BluetoothDispatcherHost::OnStartNotifications( | 707 void BluetoothDispatcherHost::OnStartNotifications( | 
| 752 int thread_id, | 708 int thread_id, | 
| 753 int request_id, | 709 int request_id, | 
| 754 const std::string& characteristic_instance_id) { | 710 const std::string& characteristic_instance_id) { | 
| 755 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 711 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 756 RecordWebBluetoothFunctionCall( | 712 RecordWebBluetoothFunctionCall( | 
| 757 UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); | 713 UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); | 
| 758 | 714 | 
| 759 // BluetoothDispatcher will never send a request for a characteristic | 715 // BluetoothDispatcher will never send a request for a characteristic | 
| 760 // already subscribed to notifications. | 716 // already subscribed to notifications. | 
| 761 if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != | 717 if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != | 
| 762 characteristic_id_to_notify_session_.end()) { | 718 characteristic_id_to_notify_session_.end()) { | 
| 763 bad_message::ReceivedBadMessage( | 719 bad_message::ReceivedBadMessage( | 
| 764 this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); | 720 this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); | 
| 765 return; | 721 return; | 
| 766 } | 722 } | 
| 767 | 723 | 
| 768 // TODO(ortuno): Check if notify/indicate bit is set. | 724 // TODO(ortuno): Check if notify/indicate bit is set. | 
| 769 // http://crbug.com/538869 | 725 // http://crbug.com/538869 | 
| 770 | 726 | 
| 771 auto characteristic_iter = | 727 CacheQueryResult query_result = CacheQueryResult(); | 
| 772 characteristic_to_service_.find(characteristic_instance_id); | 728 QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 
| 773 | 729 | 
| 774 // Kill the renderer, see "ID Not In Map Note" above. | 730 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 775 if (characteristic_iter == characteristic_to_service_.end()) { | 731 RecordOutcomeWithCacheQueryResult( | 
| 776 bad_message::ReceivedBadMessage(this, | 732 UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS, | 
| 777 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 733 query_result.outcome); | 
| 734 Send(new BluetoothMsg_StartNotificationsError(thread_id, request_id, | |
| 735 query_result.error)); | |
| 778 return; | 736 return; | 
| 779 } | 737 } | 
| 780 | 738 | 
| 781 const std::string& service_instance_id = characteristic_iter->second; | 739 query_result.characteristic->StartNotifySession( | 
| 782 auto device_iter = service_to_device_.find(service_instance_id); | |
| 783 CHECK(device_iter != service_to_device_.end()); | |
| 784 | |
| 785 device::BluetoothDevice* device = | |
| 786 adapter_->GetDevice(device_iter->second /* device_instance_id */); | |
| 787 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | |
| 788 RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_DEVICE); | |
| 789 Send(new BluetoothMsg_StartNotificationsError( | |
| 790 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | |
| 791 return; | |
| 792 } | |
| 793 | |
| 794 BluetoothGattService* service = device->GetGattService(service_instance_id); | |
| 795 if (service == nullptr) { | |
| 796 RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_SERVICE); | |
| 797 Send(new BluetoothMsg_StartNotificationsError( | |
| 798 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | |
| 799 return; | |
| 800 } | |
| 801 | |
| 802 BluetoothGattCharacteristic* characteristic = | |
| 803 service->GetCharacteristic(characteristic_instance_id); | |
| 804 if (characteristic == nullptr) { | |
| 805 RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_CHARACTERISTIC); | |
| 806 Send(new BluetoothMsg_StartNotificationsError( | |
| 807 thread_id, request_id, | |
| 808 WebBluetoothError::CharacteristicNoLongerExists)); | |
| 809 return; | |
| 810 } | |
| 811 | |
| 812 characteristic->StartNotifySession( | |
| 813 base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionSuccess, | 740 base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionSuccess, | 
| 814 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 741 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 
| 815 base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionFailed, | 742 base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionFailed, | 
| 816 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 743 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 
| 817 } | 744 } | 
| 818 | 745 | 
| 819 void BluetoothDispatcherHost::OnStopNotifications( | 746 void BluetoothDispatcherHost::OnStopNotifications( | 
| 820 int thread_id, | 747 int thread_id, | 
| 821 int request_id, | 748 int request_id, | 
| 822 const std::string& characteristic_instance_id) { | 749 const std::string& characteristic_instance_id) { | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1019 TranslateConnectError(error_code))); | 946 TranslateConnectError(error_code))); | 
| 1020 } | 947 } | 
| 1021 | 948 | 
| 1022 void BluetoothDispatcherHost::OnServicesDiscovered( | 949 void BluetoothDispatcherHost::OnServicesDiscovered( | 
| 1023 int thread_id, | 950 int thread_id, | 
| 1024 int request_id, | 951 int request_id, | 
| 1025 const std::string& device_instance_id, | 952 const std::string& device_instance_id, | 
| 1026 const std::string& service_uuid) { | 953 const std::string& service_uuid) { | 
| 1027 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 954 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1028 | 955 | 
| 1029 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 956 CacheQueryResult query_result = CacheQueryResult(); | 
| 1030 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 957 QueryCacheForDevice(device_instance_id, query_result); | 
| 1031 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); | 958 | 
| 1032 Send(new BluetoothMsg_GetPrimaryServiceError( | 959 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 1033 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 960 RecordOutcomeWithCacheQueryResult( | 
| 961 UMAWebBluetoothFunction::GET_PRIMARY_SERVICE, query_result.outcome); | |
| 962 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | |
| 963 query_result.error)); | |
| 1034 return; | 964 return; | 
| 1035 } | 965 } | 
| 1036 | 966 | 
| 1037 VLOG(1) << "Looking for service: " << service_uuid; | 967 VLOG(1) << "Looking for service: " << service_uuid; | 
| 1038 for (BluetoothGattService* service : device->GetGattServices()) { | 968 for (BluetoothGattService* service : query_result.device->GetGattServices()) { | 
| 1039 VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value(); | 969 VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value(); | 
| 1040 if (service->GetUUID().canonical_value() == service_uuid) { | 970 if (service->GetUUID().canonical_value() == service_uuid) { | 
| 1041 // TODO(ortuno): Use generated instance ID instead. | 971 // TODO(ortuno): Use generated instance ID instead. | 
| 1042 // https://crbug.com/495379 | 972 // https://crbug.com/495379 | 
| 1043 const std::string& service_identifier = service->GetIdentifier(); | 973 const std::string& service_identifier = service->GetIdentifier(); | 
| 1044 auto insert_result = service_to_device_.insert( | 974 auto insert_result = service_to_device_.insert( | 
| 1045 make_pair(service_identifier, device_instance_id)); | 975 make_pair(service_identifier, device_instance_id)); | 
| 1046 | 976 | 
| 1047 // If a value is already in map, DCHECK it's valid. | 977 // If a value is already in map, DCHECK it's valid. | 
| 1048 if (!insert_result.second) | 978 if (!insert_result.second) | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1122 } | 1052 } | 
| 1123 | 1053 | 
| 1124 void BluetoothDispatcherHost::OnStopNotifySession( | 1054 void BluetoothDispatcherHost::OnStopNotifySession( | 
| 1125 int thread_id, | 1055 int thread_id, | 
| 1126 int request_id, | 1056 int request_id, | 
| 1127 const std::string& characteristic_instance_id) { | 1057 const std::string& characteristic_instance_id) { | 
| 1128 characteristic_id_to_notify_session_.erase(characteristic_instance_id); | 1058 characteristic_id_to_notify_session_.erase(characteristic_instance_id); | 
| 1129 Send(new BluetoothMsg_StopNotificationsSuccess(thread_id, request_id)); | 1059 Send(new BluetoothMsg_StopNotificationsSuccess(thread_id, request_id)); | 
| 1130 } | 1060 } | 
| 1131 | 1061 | 
| 1062 void BluetoothDispatcherHost::QueryCacheForDevice( | |
| 1063 const std::string& device_instance_id, | |
| 1064 CacheQueryResult& result) { | |
| 1065 result.device = adapter_->GetDevice(device_instance_id); | |
| 1066 // When a device can't be found in the BluetoothAdapter, that generally | |
| 1067 // indicates that it's gone out of range. We reject with a NetworkError in | |
| 1068 // that case. | |
| 1069 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-con nectgatt | |
| 1070 if (result.device == nullptr) { | |
| 1071 result.SetError(CacheQueryOutcome::NO_DEVICE); | |
| 1072 } | |
| 1073 } | |
| 1074 | |
| 1075 bool BluetoothDispatcherHost::QueryCacheForService( | |
| 1076 const std::string& service_instance_id, | |
| 1077 CacheQueryResult& result) { | |
| 1078 auto device_iter = service_to_device_.find(service_instance_id); | |
| 1079 | |
| 1080 // Kill the renderer, see "ID Not In Map Note" above. | |
| 1081 if (device_iter == service_to_device_.end()) { | |
| 1082 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | |
| 1083 return true; | |
| 1084 } | |
| 1085 | |
| 1086 // TODO(ortuno): Check if domain has access to device. | |
| 1087 // https://crbug.com/493459 | |
| 1088 | |
| 1089 QueryCacheForDevice(device_iter->second, result); | |
| 1090 | |
| 1091 if (result.outcome != CacheQueryOutcome::SUCCESS) { | |
| 1092 return false; | |
| 1093 } | |
| 1094 | |
| 1095 result.service = result.device->GetGattService(service_instance_id); | |
| 1096 | |
| 1097 if (result.service == nullptr) { | |
| 1098 result.SetError(CacheQueryOutcome::NO_SERVICE); | |
| 1099 } | |
| 1100 return false; | |
| 1101 } | |
| 1102 | |
| 1103 bool BluetoothDispatcherHost::QueryCacheForCharacteristic( | |
| 1104 const std::string& characteristic_instance_id, | |
| 1105 CacheQueryResult& result) { | |
| 1106 auto characteristic_iter = | |
| 1107 characteristic_to_service_.find(characteristic_instance_id); | |
| 1108 | |
| 1109 // Kill the renderer, see "ID Not In Map Note" above. | |
| 1110 if (characteristic_iter == characteristic_to_service_.end()) { | |
| 1111 bad_message::ReceivedBadMessage(this, | |
| 1112 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | |
| 1113 return true; | |
| 1114 } | |
| 1115 | |
| 1116 if (QueryCacheForService(characteristic_iter->second, result)) { | |
| 1117 return true; | |
| 1118 } | |
| 1119 | |
| 1120 if (result.outcome != CacheQueryOutcome::SUCCESS) { | |
| 1121 return false; | |
| 1122 } | |
| 1123 | |
| 1124 result.characteristic = | |
| 1125 result.service->GetCharacteristic(characteristic_instance_id); | |
| 1126 | |
| 1127 if (result.characteristic == nullptr) { | |
| 1128 result.SetError(CacheQueryOutcome::NO_CHARACTERISTIC); | |
| 1129 } | |
| 1130 return false; | |
| 1131 } | |
| 1132 | |
| 1132 void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | 1133 void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | 
| 1133 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1134 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1134 NOTIMPLEMENTED(); | 1135 NOTIMPLEMENTED(); | 
| 1135 } | 1136 } | 
| 1136 | 1137 | 
| 1137 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | 1138 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | 
| 1138 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1139 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1139 NOTIMPLEMENTED(); | 1140 NOTIMPLEMENTED(); | 
| 1140 } | 1141 } | 
| 1141 | 1142 | 
| 1142 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | 1143 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | 
| 1143 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1144 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1144 NOTIMPLEMENTED(); | 1145 NOTIMPLEMENTED(); | 
| 1145 } | 1146 } | 
| 1146 | 1147 | 
| 1147 } // namespace content | 1148 } // namespace content | 
| OLD | NEW |