 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| Index: content/browser/bluetooth/bluetooth_dispatcher_host.cc | 
| diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/content/browser/bluetooth/bluetooth_dispatcher_host.cc | 
| index 7a63827e0234f19158ad0f3bdc2b50ac051cf3db..0f7f7a25bddef0aeab53ebf8b693b27645ed21a2 100644 | 
| --- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc | 
| +++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc | 
| @@ -2,12 +2,6 @@ | 
| // Use of this source code is governed by a BSD-style license that can be | 
| // found in the LICENSE file. | 
| -// NETWORK_ERROR Note: | 
| -// When a device can't be found in the BluetoothAdapter, that generally | 
| -// indicates that it's gone out of range. We reject with a NetworkError in that | 
| -// case. | 
| -// https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-connectgatt | 
| - | 
| // ID Not In Map Note: | 
| // A service, characteristic, or descriptor ID not in the corresponding | 
| // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 
| @@ -283,6 +277,37 @@ struct BluetoothDispatcherHost::RequestDeviceSession { | 
| scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 
| }; | 
| +struct BluetoothDispatcherHost::CacheQueryResult { | 
| + CacheQueryResult() | 
| + : device(nullptr), | 
| + service(nullptr), | 
| + characteristic(nullptr), | 
| + outcome(CacheQueryOutcome::SUCCESS) {} | 
| + ~CacheQueryResult() {} | 
| + void SetError(CacheQueryOutcome error_outcome) { | 
| + outcome = error_outcome; | 
| + switch (error_outcome) { | 
| + case CacheQueryOutcome::NO_DEVICE: | 
| + error = WebBluetoothError::DeviceNoLongerInRange; | 
| + return; | 
| + case CacheQueryOutcome::NO_SERVICE: | 
| + error = WebBluetoothError::ServiceNoLongerExists; | 
| + return; | 
| + case CacheQueryOutcome::NO_CHARACTERISTIC: | 
| + error = WebBluetoothError::CharacteristicNoLongerExists; | 
| + return; | 
| + case CacheQueryOutcome::SUCCESS: | 
| + return; | 
| + } | 
| + } | 
| + | 
| + device::BluetoothDevice* device; | 
| + device::BluetoothGattService* service; | 
| + device::BluetoothGattCharacteristic* characteristic; | 
| + CacheQueryOutcome outcome; | 
| + 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.
 | 
| +}; | 
| + | 
| void BluetoothDispatcherHost::set_adapter( | 
| scoped_refptr<device::BluetoothAdapter> adapter) { | 
| DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| @@ -517,14 +542,19 @@ void BluetoothDispatcherHost::OnConnectGATT( | 
| // the device, because any domain can connect to any device. But once | 
| // permissions are implemented we should check that the domain has access to | 
| // the device. https://crbug.com/484745 | 
| - device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_ConnectGATTError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| + | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + QueryCacheForDevice(device_instance_id, query_result); | 
| + | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + RecordOutcomeWithCacheQueryResult(UMAWebBluetoothFunction::CONNECT_GATT, | 
| + query_result.outcome); | 
| + Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| - device->CreateGattConnection( | 
| + | 
| + query_result.device->CreateGattConnection( | 
| base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 
| weak_ptr_on_ui_thread_, thread_id, request_id, | 
| device_instance_id, start_time), | 
| @@ -565,38 +595,21 @@ void BluetoothDispatcherHost::OnGetCharacteristic( | 
| RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 
| RecordGetCharacteristicCharacteristic(characteristic_uuid); | 
| - auto device_iter = service_to_device_.find(service_instance_id); | 
| - // Kill the renderer, see "ID Not In Map Note" above. | 
| - if (device_iter == service_to_device_.end()) { | 
| - bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | 
| - return; | 
| - } | 
| - | 
| - // TODO(ortuno): Check if domain has access to device. | 
| - // https://crbug.com/493459 | 
| - device::BluetoothDevice* device = | 
| - adapter_->GetDevice(device_iter->second /* device_instance_id */); | 
| - | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_GetCharacteristicError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + 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
 | 
| return; | 
| } | 
| - // TODO(ortuno): Check if domain has access to service | 
| - // http://crbug.com/493460 | 
| - device::BluetoothGattService* service = | 
| - device->GetGattService(service_instance_id); | 
| - if (!service) { | 
| - RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_SERVICE); | 
| - Send(new BluetoothMsg_GetCharacteristicError( | 
| - thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + 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.
 | 
| + UMAWebBluetoothFunction::GET_CHARACTERISTIC, query_result.outcome); | 
| + Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| for (BluetoothGattCharacteristic* characteristic : | 
| - service->GetCharacteristics()) { | 
| + query_result.service->GetCharacteristics()) { | 
| if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 
| const std::string& characteristic_instance_id = | 
| characteristic->GetIdentifier(); | 
| @@ -629,50 +642,21 @@ void BluetoothDispatcherHost::OnReadValue( | 
| RecordWebBluetoothFunctionCall( | 
| UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 
| - auto characteristic_iter = | 
| - characteristic_to_service_.find(characteristic_instance_id); | 
| - | 
| - // Kill the renderer, see "ID Not In Map Note" above. | 
| - if (characteristic_iter == characteristic_to_service_.end()) { | 
| - bad_message::ReceivedBadMessage(this, | 
| - bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 
| - return; | 
| - } | 
| - const std::string& service_instance_id = characteristic_iter->second; | 
| - | 
| - auto device_iter = service_to_device_.find(service_instance_id); | 
| - | 
| - CHECK(device_iter != service_to_device_.end()); | 
| - | 
| - device::BluetoothDevice* device = | 
| - adapter_->GetDevice(device_iter->second /* device_instance_id */); | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_ReadCharacteristicValueError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| - return; | 
| - } | 
| - | 
| - BluetoothGattService* service = device->GetGattService(service_instance_id); | 
| - if (service == nullptr) { | 
| - RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | 
| - Send(new BluetoothMsg_ReadCharacteristicValueError( | 
| - thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + if (QueryCacheForCharacteristic(characteristic_instance_id, query_result)) { | 
| return; | 
| } | 
| - BluetoothGattCharacteristic* characteristic = | 
| - service->GetCharacteristic(characteristic_instance_id); | 
| - if (characteristic == nullptr) { | 
| - RecordCharacteristicReadValueOutcome( | 
| - UMAGATTOperationOutcome::NO_CHARACTERISTIC); | 
| - Send(new BluetoothMsg_ReadCharacteristicValueError( | 
| - thread_id, request_id, | 
| - WebBluetoothError::CharacteristicNoLongerExists)); | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + RecordOutcomeWithCacheQueryResult( | 
| + UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE, | 
| + query_result.outcome); | 
| + Send(new BluetoothMsg_ReadCharacteristicValueError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| - characteristic->ReadRemoteCharacteristic( | 
| + query_result.characteristic->ReadRemoteCharacteristic( | 
| base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 
| weak_ptr_on_ui_thread_, thread_id, request_id), | 
| base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 
| @@ -699,49 +683,21 @@ void BluetoothDispatcherHost::OnWriteValue( | 
| return; | 
| } | 
| - auto characteristic_iter = | 
| - characteristic_to_service_.find(characteristic_instance_id); | 
| - | 
| - // Kill the renderer, see "ID Not In Map Note" above. | 
| - if (characteristic_iter == characteristic_to_service_.end()) { | 
| - bad_message::ReceivedBadMessage(this, | 
| - bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 
| - return; | 
| - } | 
| - const std::string& service_instance_id = characteristic_iter->second; | 
| - | 
| - auto device_iter = service_to_device_.find(service_instance_id); | 
| - | 
| - CHECK(device_iter != service_to_device_.end()); | 
| - | 
| - device::BluetoothDevice* device = | 
| - adapter_->GetDevice(device_iter->second /* device_instance_id */); | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_WriteCharacteristicValueError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + if (QueryCacheForCharacteristic(characteristic_instance_id, query_result)) { | 
| return; | 
| } | 
| - BluetoothGattService* service = device->GetGattService(service_instance_id); | 
| - if (service == nullptr) { | 
| - RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | 
| - Send(new BluetoothMsg_WriteCharacteristicValueError( | 
| - thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + RecordOutcomeWithCacheQueryResult( | 
| + UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE, | 
| + query_result.outcome); | 
| + Send(new BluetoothMsg_WriteCharacteristicValueError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| - BluetoothGattCharacteristic* characteristic = | 
| - service->GetCharacteristic(characteristic_instance_id); | 
| - if (characteristic == nullptr) { | 
| - RecordCharacteristicWriteValueOutcome( | 
| - UMAGATTOperationOutcome::NO_CHARACTERISTIC); | 
| - Send(new BluetoothMsg_WriteCharacteristicValueError( | 
| - thread_id, request_id, | 
| - WebBluetoothError::CharacteristicNoLongerExists)); | 
| - return; | 
| - } | 
| - characteristic->WriteRemoteCharacteristic( | 
| + query_result.characteristic->WriteRemoteCharacteristic( | 
| value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | 
| weak_ptr_on_ui_thread_, thread_id, request_id), | 
| base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 
| @@ -768,48 +724,19 @@ void BluetoothDispatcherHost::OnStartNotifications( | 
| // TODO(ortuno): Check if notify/indicate bit is set. | 
| // http://crbug.com/538869 | 
| - auto characteristic_iter = | 
| - characteristic_to_service_.find(characteristic_instance_id); | 
| - | 
| - // Kill the renderer, see "ID Not In Map Note" above. | 
| - if (characteristic_iter == characteristic_to_service_.end()) { | 
| - bad_message::ReceivedBadMessage(this, | 
| - bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 
| - return; | 
| - } | 
| - | 
| - const std::string& service_instance_id = characteristic_iter->second; | 
| - auto device_iter = service_to_device_.find(service_instance_id); | 
| - CHECK(device_iter != service_to_device_.end()); | 
| - | 
| - device::BluetoothDevice* device = | 
| - adapter_->GetDevice(device_iter->second /* device_instance_id */); | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_StartNotificationsError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| - return; | 
| - } | 
| - | 
| - BluetoothGattService* service = device->GetGattService(service_instance_id); | 
| - if (service == nullptr) { | 
| - RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_SERVICE); | 
| - Send(new BluetoothMsg_StartNotificationsError( | 
| - thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | 
| - return; | 
| - } | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 
| - BluetoothGattCharacteristic* characteristic = | 
| - service->GetCharacteristic(characteristic_instance_id); | 
| - if (characteristic == nullptr) { | 
| - RecordStartNotificationsOutcome(UMAGATTOperationOutcome::NO_CHARACTERISTIC); | 
| - Send(new BluetoothMsg_StartNotificationsError( | 
| - thread_id, request_id, | 
| - WebBluetoothError::CharacteristicNoLongerExists)); | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + RecordOutcomeWithCacheQueryResult( | 
| + UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS, | 
| + query_result.outcome); | 
| + Send(new BluetoothMsg_StartNotificationsError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| - characteristic->StartNotifySession( | 
| + query_result.characteristic->StartNotifySession( | 
| base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionSuccess, | 
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 
| base::Bind(&BluetoothDispatcherHost::OnStartNotifySessionFailed, | 
| @@ -1026,16 +953,19 @@ void BluetoothDispatcherHost::OnServicesDiscovered( | 
| const std::string& service_uuid) { | 
| DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| - device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 
| - if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 
| - RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); | 
| - Send(new BluetoothMsg_GetPrimaryServiceError( | 
| - thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 
| + CacheQueryResult query_result = CacheQueryResult(); | 
| + QueryCacheForDevice(device_instance_id, query_result); | 
| + | 
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + RecordOutcomeWithCacheQueryResult( | 
| + UMAWebBluetoothFunction::GET_PRIMARY_SERVICE, query_result.outcome); | 
| + Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | 
| + query_result.error)); | 
| return; | 
| } | 
| VLOG(1) << "Looking for service: " << service_uuid; | 
| - for (BluetoothGattService* service : device->GetGattServices()) { | 
| + for (BluetoothGattService* service : query_result.device->GetGattServices()) { | 
| VLOG(1) << "Service in cache: " << service->GetUUID().canonical_value(); | 
| if (service->GetUUID().canonical_value() == service_uuid) { | 
| // TODO(ortuno): Use generated instance ID instead. | 
| @@ -1129,6 +1059,77 @@ void BluetoothDispatcherHost::OnStopNotifySession( | 
| Send(new BluetoothMsg_StopNotificationsSuccess(thread_id, request_id)); | 
| } | 
| +void BluetoothDispatcherHost::QueryCacheForDevice( | 
| + const std::string& device_instance_id, | 
| + CacheQueryResult& result) { | 
| + result.device = adapter_->GetDevice(device_instance_id); | 
| + // When a device can't be found in the BluetoothAdapter, that generally | 
| + // indicates that it's gone out of range. We reject with a NetworkError in | 
| + // that case. | 
| + // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-connectgatt | 
| + if (result.device == nullptr) { | 
| + result.SetError(CacheQueryOutcome::NO_DEVICE); | 
| + } | 
| +} | 
| + | 
| +bool BluetoothDispatcherHost::QueryCacheForService( | 
| + const std::string& service_instance_id, | 
| + CacheQueryResult& result) { | 
| + auto device_iter = service_to_device_.find(service_instance_id); | 
| + | 
| + // Kill the renderer, see "ID Not In Map Note" above. | 
| + if (device_iter == service_to_device_.end()) { | 
| + bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | 
| + return true; | 
| + } | 
| + | 
| + // TODO(ortuno): Check if domain has access to device. | 
| + // https://crbug.com/493459 | 
| + | 
| + QueryCacheForDevice(device_iter->second, result); | 
| + | 
| + if (result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + return false; | 
| + } | 
| + | 
| + result.service = result.device->GetGattService(service_instance_id); | 
| + | 
| + if (result.service == nullptr) { | 
| + result.SetError(CacheQueryOutcome::NO_SERVICE); | 
| + } | 
| + return false; | 
| +} | 
| + | 
| +bool BluetoothDispatcherHost::QueryCacheForCharacteristic( | 
| + const std::string& characteristic_instance_id, | 
| + CacheQueryResult& result) { | 
| + auto characteristic_iter = | 
| + characteristic_to_service_.find(characteristic_instance_id); | 
| + | 
| + // Kill the renderer, see "ID Not In Map Note" above. | 
| + if (characteristic_iter == characteristic_to_service_.end()) { | 
| + bad_message::ReceivedBadMessage(this, | 
| + bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 
| + return true; | 
| + } | 
| + | 
| + if (QueryCacheForService(characteristic_iter->second, result)) { | 
| + return true; | 
| + } | 
| + | 
| + if (result.outcome != CacheQueryOutcome::SUCCESS) { | 
| + return false; | 
| + } | 
| + | 
| + result.characteristic = | 
| + result.service->GetCharacteristic(characteristic_instance_id); | 
| + | 
| + if (result.characteristic == nullptr) { | 
| + result.SetError(CacheQueryOutcome::NO_CHARACTERISTIC); | 
| + } | 
| + return false; | 
| +} | 
| + | 
| void BluetoothDispatcherHost::ShowBluetoothOverviewLink() { | 
| DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| NOTIMPLEMENTED(); |