| 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   WebBluetoothError GetWebError() { | 
|  | 288     switch (outcome) { | 
|  | 289       case CacheQueryOutcome::SUCCESS: | 
|  | 290       case CacheQueryOutcome::BAD_RENDERER: | 
|  | 291         NOTREACHED(); | 
|  | 292         return WebBluetoothError::DeviceNoLongerInRange; | 
|  | 293       case CacheQueryOutcome::NO_DEVICE: | 
|  | 294         return WebBluetoothError::DeviceNoLongerInRange; | 
|  | 295       case CacheQueryOutcome::NO_SERVICE: | 
|  | 296         return WebBluetoothError::ServiceNoLongerExists; | 
|  | 297       case CacheQueryOutcome::NO_CHARACTERISTIC: | 
|  | 298         return WebBluetoothError::CharacteristicNoLongerExists; | 
|  | 299     } | 
|  | 300     NOTREACHED(); | 
|  | 301     return WebBluetoothError::DeviceNoLongerInRange; | 
|  | 302   } | 
|  | 303 | 
|  | 304   device::BluetoothDevice* device; | 
|  | 305   device::BluetoothGattService* service; | 
|  | 306   device::BluetoothGattCharacteristic* characteristic; | 
|  | 307   CacheQueryOutcome outcome; | 
|  | 308 }; | 
|  | 309 | 
| 286 void BluetoothDispatcherHost::set_adapter( | 310 void BluetoothDispatcherHost::set_adapter( | 
| 287     scoped_refptr<device::BluetoothAdapter> adapter) { | 311     scoped_refptr<device::BluetoothAdapter> adapter) { | 
| 288   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 312   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 289   connections_.clear(); | 313   connections_.clear(); | 
| 290   if (adapter_.get()) | 314   if (adapter_.get()) | 
| 291     adapter_->RemoveObserver(this); | 315     adapter_->RemoveObserver(this); | 
| 292   adapter_ = adapter; | 316   adapter_ = adapter; | 
| 293   if (adapter_.get()) | 317   if (adapter_.get()) | 
| 294     adapter_->AddObserver(this); | 318     adapter_->AddObserver(this); | 
| 295 } | 319 } | 
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 510     int request_id, | 534     int request_id, | 
| 511     const std::string& device_instance_id) { | 535     const std::string& device_instance_id) { | 
| 512   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 536   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 513   RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 537   RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 
| 514   const base::TimeTicks start_time = base::TimeTicks::Now(); | 538   const base::TimeTicks start_time = base::TimeTicks::Now(); | 
| 515 | 539 | 
| 516   // TODO(ortuno): Right now it's pointless to check if the domain has access to | 540   // 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 | 541   // 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 | 542   // permissions are implemented we should check that the domain has access to | 
| 519   // the device. https://crbug.com/484745 | 543   // the device. https://crbug.com/484745 | 
| 520   device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 544 | 
| 521   if (device == nullptr) {  // See "NETWORK_ERROR Note" above. | 545   CacheQueryResult query_result = CacheQueryResult(); | 
| 522     RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); | 546   QueryCacheForDevice(device_instance_id, query_result); | 
| 523     Send(new BluetoothMsg_ConnectGATTError( | 547 | 
| 524         thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 548   if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
|  | 549     RecordConnectGATTOutcome(query_result.outcome); | 
|  | 550     Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id, | 
|  | 551                                            query_result.GetWebError())); | 
| 525     return; | 552     return; | 
| 526   } | 553   } | 
| 527   device->CreateGattConnection( | 554 | 
|  | 555   query_result.device->CreateGattConnection( | 
| 528       base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 556       base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 
| 529                  weak_ptr_on_ui_thread_, thread_id, request_id, | 557                  weak_ptr_on_ui_thread_, thread_id, request_id, | 
| 530                  device_instance_id, start_time), | 558                  device_instance_id, start_time), | 
| 531       base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 559       base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 
| 532                  weak_ptr_on_ui_thread_, thread_id, request_id, | 560                  weak_ptr_on_ui_thread_, thread_id, request_id, | 
| 533                  device_instance_id, start_time)); | 561                  device_instance_id, start_time)); | 
| 534 } | 562 } | 
| 535 | 563 | 
| 536 void BluetoothDispatcherHost::OnGetPrimaryService( | 564 void BluetoothDispatcherHost::OnGetPrimaryService( | 
| 537     int thread_id, | 565     int thread_id, | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 558 | 586 | 
| 559 void BluetoothDispatcherHost::OnGetCharacteristic( | 587 void BluetoothDispatcherHost::OnGetCharacteristic( | 
| 560     int thread_id, | 588     int thread_id, | 
| 561     int request_id, | 589     int request_id, | 
| 562     const std::string& service_instance_id, | 590     const std::string& service_instance_id, | 
| 563     const std::string& characteristic_uuid) { | 591     const std::string& characteristic_uuid) { | 
| 564   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 592   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 565   RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 593   RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 
| 566   RecordGetCharacteristicCharacteristic(characteristic_uuid); | 594   RecordGetCharacteristicCharacteristic(characteristic_uuid); | 
| 567 | 595 | 
| 568   auto device_iter = service_to_device_.find(service_instance_id); | 596   CacheQueryResult query_result = CacheQueryResult(); | 
| 569   // Kill the renderer, see "ID Not In Map Note" above. | 597   QueryCacheForService(service_instance_id, query_result); | 
| 570   if (device_iter == service_to_device_.end()) { | 598 | 
| 571     bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | 599   if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 
| 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     RecordGetCharacteristicOutcome(query_result.outcome); | 
| 577   device::BluetoothDevice* device = | 605     Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id, | 
| 578       adapter_->GetDevice(device_iter->second /* device_instance_id */); | 606                                                  query_result.GetWebError())); | 
| 579 |  | 
| 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; | 607     return; | 
| 596   } | 608   } | 
| 597 | 609 | 
| 598   for (BluetoothGattCharacteristic* characteristic : | 610   for (BluetoothGattCharacteristic* characteristic : | 
| 599        service->GetCharacteristics()) { | 611        query_result.service->GetCharacteristics()) { | 
| 600     if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 612     if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 
| 601       const std::string& characteristic_instance_id = | 613       const std::string& characteristic_instance_id = | 
| 602           characteristic->GetIdentifier(); | 614           characteristic->GetIdentifier(); | 
| 603 | 615 | 
| 604       auto insert_result = characteristic_to_service_.insert( | 616       auto insert_result = characteristic_to_service_.insert( | 
| 605           make_pair(characteristic_instance_id, service_instance_id)); | 617           make_pair(characteristic_instance_id, service_instance_id)); | 
| 606 | 618 | 
| 607       // If  value is already in map, DCHECK it's valid. | 619       // If  value is already in map, DCHECK it's valid. | 
| 608       if (!insert_result.second) | 620       if (!insert_result.second) | 
| 609         DCHECK(insert_result.first->second == service_instance_id); | 621         DCHECK(insert_result.first->second == service_instance_id); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 622 } | 634 } | 
| 623 | 635 | 
| 624 void BluetoothDispatcherHost::OnReadValue( | 636 void BluetoothDispatcherHost::OnReadValue( | 
| 625     int thread_id, | 637     int thread_id, | 
| 626     int request_id, | 638     int request_id, | 
| 627     const std::string& characteristic_instance_id) { | 639     const std::string& characteristic_instance_id) { | 
| 628   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 640   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 629   RecordWebBluetoothFunctionCall( | 641   RecordWebBluetoothFunctionCall( | 
| 630       UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 642       UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 
| 631 | 643 | 
| 632   auto characteristic_iter = | 644   CacheQueryResult query_result = CacheQueryResult(); | 
| 633       characteristic_to_service_.find(characteristic_instance_id); | 645   QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 
| 634 | 646 | 
| 635   // Kill the renderer, see "ID Not In Map Note" above. | 647   if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 
| 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; | 648     return; | 
| 654   } | 649   } | 
| 655 | 650 | 
| 656   BluetoothGattService* service = device->GetGattService(service_instance_id); | 651   if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 657   if (service == nullptr) { | 652     RecordCharacteristicReadValueOutcome(query_result.outcome); | 
| 658     RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); |  | 
| 659     Send(new BluetoothMsg_ReadCharacteristicValueError( | 653     Send(new BluetoothMsg_ReadCharacteristicValueError( | 
| 660         thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 654         thread_id, request_id, query_result.GetWebError())); | 
| 661     return; | 655     return; | 
| 662   } | 656   } | 
| 663 | 657 | 
| 664   BluetoothGattCharacteristic* characteristic = | 658   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, | 659       base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 
| 677                  weak_ptr_on_ui_thread_, thread_id, request_id), | 660                  weak_ptr_on_ui_thread_, thread_id, request_id), | 
| 678       base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 661       base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 
| 679                  weak_ptr_on_ui_thread_, thread_id, request_id)); | 662                  weak_ptr_on_ui_thread_, thread_id, request_id)); | 
| 680 } | 663 } | 
| 681 | 664 | 
| 682 void BluetoothDispatcherHost::OnWriteValue( | 665 void BluetoothDispatcherHost::OnWriteValue( | 
| 683     int thread_id, | 666     int thread_id, | 
| 684     int request_id, | 667     int request_id, | 
| 685     const std::string& characteristic_instance_id, | 668     const std::string& characteristic_instance_id, | 
| 686     const std::vector<uint8_t>& value) { | 669     const std::vector<uint8_t>& value) { | 
| 687   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 670   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 688   RecordWebBluetoothFunctionCall( | 671   RecordWebBluetoothFunctionCall( | 
| 689       UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | 672       UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | 
| 690 | 673 | 
| 691   // Length check per step 3 of writeValue algorithm: | 674   // Length check per step 3 of writeValue algorithm: | 
| 692   // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
      teristic-writevalue | 675   // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
      teristic-writevalue | 
| 693   // We perform the length check on the renderer side. So if we | 676   // 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 | 677   // get a value with length > 512, we can assume it's a hostile | 
| 695   // renderer and kill it. | 678   // renderer and kill it. | 
| 696   if (value.size() > 512) { | 679   if (value.size() > 512) { | 
| 697     bad_message::ReceivedBadMessage( | 680     bad_message::ReceivedBadMessage( | 
| 698         this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 681         this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 
| 699     return; | 682     return; | 
| 700   } | 683   } | 
| 701 | 684 | 
| 702   auto characteristic_iter = | 685   CacheQueryResult query_result = CacheQueryResult(); | 
| 703       characteristic_to_service_.find(characteristic_instance_id); | 686   QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 
| 704 | 687 | 
| 705   // Kill the renderer, see "ID Not In Map Note" above. | 688   if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 
| 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; | 689     return; | 
| 724   } | 690   } | 
| 725 | 691 | 
| 726   BluetoothGattService* service = device->GetGattService(service_instance_id); | 692   if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 727   if (service == nullptr) { | 693     RecordCharacteristicWriteValueOutcome(query_result.outcome); | 
| 728     RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); |  | 
| 729     Send(new BluetoothMsg_WriteCharacteristicValueError( | 694     Send(new BluetoothMsg_WriteCharacteristicValueError( | 
| 730         thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 695         thread_id, request_id, query_result.GetWebError())); | 
| 731     return; | 696     return; | 
| 732   } | 697   } | 
| 733 | 698 | 
| 734   BluetoothGattCharacteristic* characteristic = | 699   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, | 700       value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | 
| 746                         weak_ptr_on_ui_thread_, thread_id, request_id), | 701                         weak_ptr_on_ui_thread_, thread_id, request_id), | 
| 747       base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 702       base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 
| 748                  weak_ptr_on_ui_thread_, thread_id, request_id)); | 703                  weak_ptr_on_ui_thread_, thread_id, request_id)); | 
| 749 } | 704 } | 
| 750 | 705 | 
| 751 void BluetoothDispatcherHost::OnStartNotifications( | 706 void BluetoothDispatcherHost::OnStartNotifications( | 
| 752     int thread_id, | 707     int thread_id, | 
| 753     int request_id, | 708     int request_id, | 
| 754     const std::string& characteristic_instance_id) { | 709     const std::string& characteristic_instance_id) { | 
| 755   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 710   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 756   RecordWebBluetoothFunctionCall( | 711   RecordWebBluetoothFunctionCall( | 
| 757       UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); | 712       UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); | 
| 758 | 713 | 
| 759   // BluetoothDispatcher will never send a request for a characteristic | 714   // BluetoothDispatcher will never send a request for a characteristic | 
| 760   // already subscribed to notifications. | 715   // already subscribed to notifications. | 
| 761   if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != | 716   if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != | 
| 762       characteristic_id_to_notify_session_.end()) { | 717       characteristic_id_to_notify_session_.end()) { | 
| 763     bad_message::ReceivedBadMessage( | 718     bad_message::ReceivedBadMessage( | 
| 764         this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); | 719         this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); | 
| 765     return; | 720     return; | 
| 766   } | 721   } | 
| 767 | 722 | 
| 768   // TODO(ortuno): Check if notify/indicate bit is set. | 723   // TODO(ortuno): Check if notify/indicate bit is set. | 
| 769   // http://crbug.com/538869 | 724   // http://crbug.com/538869 | 
| 770 | 725 | 
| 771   auto characteristic_iter = | 726   CacheQueryResult query_result = CacheQueryResult(); | 
| 772       characteristic_to_service_.find(characteristic_instance_id); | 727   QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 
| 773 | 728 | 
| 774   // Kill the renderer, see "ID Not In Map Note" above. | 729   if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 
| 775   if (characteristic_iter == characteristic_to_service_.end()) { |  | 
| 776     bad_message::ReceivedBadMessage(this, |  | 
| 777                                     bad_message::BDH_INVALID_CHARACTERISTIC_ID); |  | 
| 778     return; | 730     return; | 
| 779   } | 731   } | 
| 780 | 732 | 
| 781   const std::string& service_instance_id = characteristic_iter->second; | 733   if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 782   auto device_iter = service_to_device_.find(service_instance_id); | 734     RecordStartNotificationsOutcome(query_result.outcome); | 
| 783   CHECK(device_iter != service_to_device_.end()); | 735     Send(new BluetoothMsg_StartNotificationsError(thread_id, request_id, | 
| 784 | 736                                                   query_result.GetWebError())); | 
| 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; | 737     return; | 
| 792   } | 738   } | 
| 793 | 739 | 
| 794   BluetoothGattService* service = device->GetGattService(service_instance_id); | 740   query_result.characteristic->StartNotifySession( | 
| 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, | 741       base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionSuccess, | 
| 814                  weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 742                  weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 
| 815       base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionFailed, | 743       base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionFailed, | 
| 816                  weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 744                  weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 
| 817 } | 745 } | 
| 818 | 746 | 
| 819 void BluetoothDispatcherHost::OnStopNotifications( | 747 void BluetoothDispatcherHost::OnStopNotifications( | 
| 820     int thread_id, | 748     int thread_id, | 
| 821     int request_id, | 749     int request_id, | 
| 822     const std::string& characteristic_instance_id) { | 750     const std::string& characteristic_instance_id) { | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1019                                          TranslateConnectError(error_code))); | 947                                          TranslateConnectError(error_code))); | 
| 1020 } | 948 } | 
| 1021 | 949 | 
| 1022 void BluetoothDispatcherHost::OnServicesDiscovered( | 950 void BluetoothDispatcherHost::OnServicesDiscovered( | 
| 1023     int thread_id, | 951     int thread_id, | 
| 1024     int request_id, | 952     int request_id, | 
| 1025     const std::string& device_instance_id, | 953     const std::string& device_instance_id, | 
| 1026     const std::string& service_uuid) { | 954     const std::string& service_uuid) { | 
| 1027   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 955   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1028 | 956 | 
| 1029   device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 957   CacheQueryResult query_result = CacheQueryResult(); | 
| 1030   if (device == nullptr) {  // See "NETWORK_ERROR Note" above. | 958   QueryCacheForDevice(device_instance_id, query_result); | 
| 1031     RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); | 959 | 
| 1032     Send(new BluetoothMsg_GetPrimaryServiceError( | 960   if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| 1033         thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 961     RecordGetPrimaryServiceOutcome(query_result.outcome); | 
|  | 962     Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | 
|  | 963                                                  query_result.GetWebError())); | 
| 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.outcome = CacheQueryOutcome::NO_DEVICE; | 
|  | 1072   } | 
|  | 1073 } | 
|  | 1074 | 
|  | 1075 void 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     result.outcome = CacheQueryOutcome::BAD_RENDERER; | 
|  | 1084     return; | 
|  | 1085   } | 
|  | 1086 | 
|  | 1087   // TODO(ortuno): Check if domain has access to device. | 
|  | 1088   // https://crbug.com/493459 | 
|  | 1089 | 
|  | 1090   QueryCacheForDevice(device_iter->second, result); | 
|  | 1091 | 
|  | 1092   if (result.outcome != CacheQueryOutcome::SUCCESS) { | 
|  | 1093     return; | 
|  | 1094   } | 
|  | 1095 | 
|  | 1096   result.service = result.device->GetGattService(service_instance_id); | 
|  | 1097   if (result.service == nullptr) { | 
|  | 1098     result.outcome = CacheQueryOutcome::NO_SERVICE; | 
|  | 1099   } | 
|  | 1100 } | 
|  | 1101 | 
|  | 1102 void BluetoothDispatcherHost::QueryCacheForCharacteristic( | 
|  | 1103     const std::string& characteristic_instance_id, | 
|  | 1104     CacheQueryResult& result) { | 
|  | 1105   auto characteristic_iter = | 
|  | 1106       characteristic_to_service_.find(characteristic_instance_id); | 
|  | 1107 | 
|  | 1108   // Kill the renderer, see "ID Not In Map Note" above. | 
|  | 1109   if (characteristic_iter == characteristic_to_service_.end()) { | 
|  | 1110     bad_message::ReceivedBadMessage(this, | 
|  | 1111                                     bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 
|  | 1112     result.outcome = CacheQueryOutcome::BAD_RENDERER; | 
|  | 1113     return; | 
|  | 1114   } | 
|  | 1115 | 
|  | 1116   QueryCacheForService(characteristic_iter->second, result); | 
|  | 1117   if (result.outcome != CacheQueryOutcome::SUCCESS) { | 
|  | 1118     return; | 
|  | 1119   } | 
|  | 1120 | 
|  | 1121   result.characteristic = | 
|  | 1122       result.service->GetCharacteristic(characteristic_instance_id); | 
|  | 1123 | 
|  | 1124   if (result.characteristic == nullptr) { | 
|  | 1125     result.outcome = CacheQueryOutcome::NO_CHARACTERISTIC; | 
|  | 1126   } | 
|  | 1127 } | 
|  | 1128 | 
| 1132 void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | 1129 void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | 
| 1133   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1130   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1134   NOTIMPLEMENTED(); | 1131   NOTIMPLEMENTED(); | 
| 1135 } | 1132 } | 
| 1136 | 1133 | 
| 1137 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | 1134 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | 
| 1138   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1135   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1139   NOTIMPLEMENTED(); | 1136   NOTIMPLEMENTED(); | 
| 1140 } | 1137 } | 
| 1141 | 1138 | 
| 1142 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | 1139 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | 
| 1143   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1140   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 1144   NOTIMPLEMENTED(); | 1141   NOTIMPLEMENTED(); | 
| 1145 } | 1142 } | 
| 1146 | 1143 | 
| 1147 }  // namespace content | 1144 }  // namespace content | 
| OLD | NEW | 
|---|