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 c1a2395c4f2bb918ab826e0a4242535217dbd999..a2eca4d02a600fb7ae03493cffaf48916d253805 100644 |
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc |
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc |
@@ -251,6 +251,101 @@ struct BluetoothDispatcherHost::RequestDeviceSession { |
scoped_ptr<device::BluetoothDiscoverySession> discovery_session; |
}; |
+blink::WebBluetoothError |
+BluetoothDispatcherHost::CacheQueryOutcomeToWebBluetoothError( |
+ BluetoothDispatcherHost::CacheQueryOutcome outcome) { |
+ switch (outcome) { |
+ case CacheQueryOutcome::SUCCESS: |
+ case CacheQueryOutcome::BAD_RENDERER: |
+ CHECK(false) << "Not errors"; |
+ case CacheQueryOutcome::NO_DEVICE: |
+ return WebBluetoothError::DeviceNoLongerInRange; |
+ case CacheQueryOutcome::NO_SERVICE: |
+ return WebBluetoothError::ServiceNoLongerExists; |
+ case CacheQueryOutcome::NO_CHARACTERISTIC: |
+ return WebBluetoothError::CharacteristicNoLongerExists; |
+ } |
+ NOTIMPLEMENTED(); |
+ return WebBluetoothError::ENUM_MAX_VALUE; |
+} |
+ |
+// TODO(ortuno): There shouldn't be a need for each user of these functions |
+// to histogram the outcome on their own. We should refactor bluetooth_metrics |
+// to use RecordOperationOutcome(WebBluetooth::Operation, Outcome), that way |
+// histogramming can be done inside these functions directly. |
+std::pair<BluetoothDispatcherHost::CacheQueryOutcome, device::BluetoothDevice*> |
+BluetoothDispatcherHost::QueryForDevice(const std::string& device_instance_id) { |
+ device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); |
+ CacheQueryOutcome device_outcome = CacheQueryOutcome::SUCCESS; |
+ if (device == nullptr) { // See "NETWORK_ERROR Note" above. |
+ device_outcome = CacheQueryOutcome::NO_DEVICE; |
+ } |
+ return std::make_pair(device_outcome, device); |
+} |
+ |
+std::pair<BluetoothDispatcherHost::CacheQueryOutcome, |
+ device::BluetoothGattService*> |
+BluetoothDispatcherHost::QueryForService( |
+ const std::string& service_instance_id) { |
+ auto device_iter = service_to_device_.find(service_instance_id); |
+ // A service_instance_id not in the map implies a hostile renderer |
+ // because a renderer obtains the service id from this class and |
+ // it will be added to the map at that time. |
+ if (device_iter == service_to_device_.end()) { |
+ // Kill the renderer |
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); |
+ return std::make_pair(CacheQueryOutcome::BAD_RENDERER, nullptr); |
+ } |
+ |
+ // TODO(ortuno): Check if domain has access to device. |
+ // https://crbug.com/493459 |
+ auto device_query_outcome = QueryForDevice(device_iter->second); |
+ if (device_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
+ return std::make_pair(device_query_outcome.first, nullptr); |
+ } |
+ |
+ CacheQueryOutcome service_outcome = CacheQueryOutcome::SUCCESS; |
+ // TODO(ortuno): Check if domain has access to service |
+ // http://crbug.com/493460 |
+ device::BluetoothGattService* service = |
+ device_query_outcome.second->GetGattService(service_instance_id); |
+ if (!service) { |
+ service_outcome = CacheQueryOutcome::NO_SERVICE; |
+ } |
+ return std::make_pair(service_outcome, service); |
+} |
+ |
+std::pair<BluetoothDispatcherHost::CacheQueryOutcome, |
+ device::BluetoothGattCharacteristic*> |
+BluetoothDispatcherHost::QueryForCharacteristic( |
+ const std::string& characteristic_instance_id) { |
+ auto characteristic_iter = |
+ characteristic_to_service_.find(characteristic_instance_id); |
+ // A characteristic_instance_id not in the map implies a hostile renderer |
+ // because a renderer obtains the characteristic id from this class and |
+ // it will be added to the map at that time. |
+ if (characteristic_iter == characteristic_to_service_.end()) { |
+ // Kill the renderer |
+ bad_message::ReceivedBadMessage(this, |
+ bad_message::BDH_INVALID_CHARACTERISTIC_ID); |
+ return std::make_pair(CacheQueryOutcome::BAD_RENDERER, nullptr); |
+ } |
+ |
+ auto service_query_outcome = QueryForService(characteristic_iter->second); |
+ if (service_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
+ return std::make_pair(service_query_outcome.first, nullptr); |
+ } |
+ |
+ CacheQueryOutcome characteristic_outcome = CacheQueryOutcome::SUCCESS; |
+ BluetoothGattCharacteristic* characteristic = |
+ service_query_outcome.second->GetCharacteristic( |
+ characteristic_instance_id); |
+ if (!characteristic) { |
+ characteristic_outcome = CacheQueryOutcome::NO_CHARACTERISTIC; |
+ } |
+ return std::make_pair(characteristic_outcome, characteristic); |
+} |
+ |
void BluetoothDispatcherHost::set_adapter( |
scoped_refptr<device::BluetoothAdapter> adapter) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
@@ -448,14 +543,17 @@ 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); |
+ auto device_query_result = QueryForDevice(device_instance_id); |
+ if (device_query_result.first != CacheQueryOutcome::SUCCESS) { |
+ if (device_query_result.first == CacheQueryOutcome::NO_DEVICE) { |
+ RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); |
+ } |
Send(new BluetoothMsg_ConnectGATTError( |
- thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); |
+ thread_id, request_id, |
+ CacheQueryOutcomeToWebBluetoothError(device_query_result.first))); |
return; |
} |
- device->CreateGattConnection( |
+ device_query_result.second->CreateGattConnection( |
base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
device_instance_id, start_time), |
@@ -496,41 +594,27 @@ void BluetoothDispatcherHost::OnGetCharacteristic( |
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); |
RecordGetCharacteristicCharacteristic(characteristic_uuid); |
- auto device_iter = service_to_device_.find(service_instance_id); |
- // A service_instance_id not in the map implies a hostile renderer |
- // because a renderer obtains the service id from this class and |
- // it will be added to the map at that time. |
- if (device_iter == service_to_device_.end()) { |
- // Kill the renderer |
- 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)); |
- return; |
- } |
+ auto service_query_outcome = QueryForService(service_instance_id); |
- // 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); |
+ if (service_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
+ CacheQueryOutcome error_outcome = service_query_outcome.first; |
+ if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
+ // QueryForService already took care of sending the message |
+ return; |
+ } |
+ if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
+ RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE); |
+ } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
+ RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_SERVICE); |
+ } |
Send(new BluetoothMsg_GetCharacteristicError( |
- thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); |
+ thread_id, request_id, |
+ CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
return; |
} |
for (BluetoothGattCharacteristic* characteristic : |
- service->GetCharacteristics()) { |
+ service_query_outcome.second->GetCharacteristics()) { |
if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { |
const std::string& characteristic_instance_id = |
characteristic->GetIdentifier(); |
@@ -563,52 +647,30 @@ void BluetoothDispatcherHost::OnReadValue( |
RecordWebBluetoothFunctionCall( |
UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); |
- auto characteristic_iter = |
- characteristic_to_service_.find(characteristic_instance_id); |
- // A characteristic_instance_id not in the map implies a hostile renderer |
- // because a renderer obtains the characteristic id from this class and |
- // it will be added to the map at that time. |
- if (characteristic_iter == characteristic_to_service_.end()) { |
- // Kill the renderer |
- 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()); |
+ auto characteristic_query_outcome = |
+ QueryForCharacteristic(characteristic_instance_id); |
- 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)); |
- return; |
- } |
- |
- BluetoothGattCharacteristic* characteristic = |
- service->GetCharacteristic(characteristic_instance_id); |
- if (characteristic == nullptr) { |
- RecordCharacteristicReadValueOutcome( |
- UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
+ if (characteristic_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
+ CacheQueryOutcome error_outcome = characteristic_query_outcome.first; |
+ if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
+ // The query handles the message. |
+ return; |
+ } |
+ if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
+ RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); |
+ } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
+ RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); |
+ } else if (error_outcome == CacheQueryOutcome::NO_CHARACTERISTIC) { |
+ RecordCharacteristicReadValueOutcome( |
+ UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
+ } |
Send(new BluetoothMsg_ReadCharacteristicValueError( |
thread_id, request_id, |
- WebBluetoothError::CharacteristicNoLongerExists)); |
+ CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
return; |
} |
- characteristic->ReadRemoteCharacteristic( |
+ characteristic_query_outcome.second->ReadRemoteCharacteristic( |
base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, |
weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, |
@@ -635,50 +697,31 @@ void BluetoothDispatcherHost::OnWriteValue( |
return; |
} |
- auto characteristic_iter = |
- characteristic_to_service_.find(characteristic_instance_id); |
- // A characteristic_instance_id not in the map implies a hostile renderer |
- // because a renderer obtains the characteristic id from this class and |
- // it will be added to the map at that time. |
- 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); |
+ auto characteristic_query_outcome = |
+ QueryForCharacteristic(characteristic_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)); |
- 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)); |
- return; |
- } |
- |
- BluetoothGattCharacteristic* characteristic = |
- service->GetCharacteristic(characteristic_instance_id); |
- if (characteristic == nullptr) { |
- RecordCharacteristicWriteValueOutcome( |
- UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
+ if (characteristic_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
+ CacheQueryOutcome error_outcome = characteristic_query_outcome.first; |
+ if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
+ // The query handles the message. |
+ return; |
+ } |
+ if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
+ RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); |
+ } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
+ RecordCharacteristicWriteValueOutcome( |
+ UMAGATTOperationOutcome::NO_SERVICE); |
+ } else if (error_outcome == CacheQueryOutcome::NO_CHARACTERISTIC) { |
+ RecordCharacteristicWriteValueOutcome( |
+ UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
+ } |
Send(new BluetoothMsg_WriteCharacteristicValueError( |
thread_id, request_id, |
- WebBluetoothError::CharacteristicNoLongerExists)); |
+ CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
return; |
} |
- characteristic->WriteRemoteCharacteristic( |
+ |
+ characteristic_query_outcome.second->WriteRemoteCharacteristic( |
value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, |
weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, |
@@ -849,14 +892,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); |
+ auto device_query_result = QueryForDevice(device_instance_id); |
+ if (device_query_result.first != CacheQueryOutcome::SUCCESS) { |
+ if (device_query_result.first == CacheQueryOutcome::NO_DEVICE) { |
+ RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); |
+ } |
Send(new BluetoothMsg_GetPrimaryServiceError( |
- thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); |
+ thread_id, request_id, |
+ CacheQueryOutcomeToWebBluetoothError(device_query_result.first))); |
return; |
} |
- for (BluetoothGattService* service : device->GetGattServices()) { |
+ |
+ for (BluetoothGattService* service : |
+ device_query_result.second->GetGattServices()) { |
if (service->GetUUID().canonical_value() == service_uuid) { |
// TODO(ortuno): Use generated instance ID instead. |
// https://crbug.com/495379 |