| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 // ID Not In Map Note: |
| 6 // A service, characteristic, or descriptor ID not in the corresponding |
| 7 // BluetoothDispatcherHost map [service_to_device_, |
| 8 // characteristic_id_to_service_id_, descriptor_to_characteristic_] implies a |
| 9 // hostile renderer because a renderer obtains the corresponding ID from this |
| 10 // class and it will be added to the map at that time. |
| 11 |
| 5 #include "content/browser/bluetooth/web_bluetooth_service_impl.h" | 12 #include "content/browser/bluetooth/web_bluetooth_service_impl.h" |
| 6 | 13 |
| 7 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 8 #include "content/browser/bluetooth/bluetooth_blacklist.h" | 15 #include "content/browser/bluetooth/bluetooth_blacklist.h" |
| 9 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 16 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| 10 #include "content/browser/renderer_host/render_process_host_impl.h" | 17 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 11 #include "content/public/browser/navigation_handle.h" | 18 #include "content/public/browser/navigation_handle.h" |
| 12 #include "content/public/browser/render_frame_host.h" | 19 #include "content/public/browser/render_frame_host.h" |
| 13 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
| 14 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" | 21 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" |
| 15 | 22 |
| 16 using device::BluetoothRemoteGattService; | |
| 17 | |
| 18 namespace content { | 23 namespace content { |
| 19 | 24 |
| 20 namespace { | 25 namespace { |
| 21 | 26 |
| 22 blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord( | 27 blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord( |
| 23 BluetoothRemoteGattService::GattErrorCode error_code, | 28 device::BluetoothRemoteGattService::GattErrorCode error_code, |
| 24 UMAGATTOperation operation) { | 29 UMAGATTOperation operation) { |
| 25 switch (error_code) { | 30 switch (error_code) { |
| 26 case BluetoothRemoteGattService::GATT_ERROR_UNKNOWN: | 31 case device::BluetoothRemoteGattService::GATT_ERROR_UNKNOWN: |
| 27 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN); | 32 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN); |
| 28 return blink::mojom::WebBluetoothError::GATT_UNKNOWN_ERROR; | 33 return blink::mojom::WebBluetoothError::GATT_UNKNOWN_ERROR; |
| 29 case BluetoothRemoteGattService::GATT_ERROR_FAILED: | 34 case device::BluetoothRemoteGattService::GATT_ERROR_FAILED: |
| 30 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED); | 35 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED); |
| 31 return blink::mojom::WebBluetoothError::GATT_UNKNOWN_FAILURE; | 36 return blink::mojom::WebBluetoothError::GATT_UNKNOWN_FAILURE; |
| 32 case BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS: | 37 case device::BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS: |
| 33 RecordGATTOperationOutcome(operation, | 38 RecordGATTOperationOutcome(operation, |
| 34 UMAGATTOperationOutcome::IN_PROGRESS); | 39 UMAGATTOperationOutcome::IN_PROGRESS); |
| 35 return blink::mojom::WebBluetoothError::GATT_OPERATION_IN_PROGRESS; | 40 return blink::mojom::WebBluetoothError::GATT_OPERATION_IN_PROGRESS; |
| 36 case BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH: | 41 case device::BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH: |
| 37 RecordGATTOperationOutcome(operation, | 42 RecordGATTOperationOutcome(operation, |
| 38 UMAGATTOperationOutcome::INVALID_LENGTH); | 43 UMAGATTOperationOutcome::INVALID_LENGTH); |
| 39 return blink::mojom::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH; | 44 return blink::mojom::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH; |
| 40 case BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED: | 45 case device::BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED: |
| 41 RecordGATTOperationOutcome(operation, | 46 RecordGATTOperationOutcome(operation, |
| 42 UMAGATTOperationOutcome::NOT_PERMITTED); | 47 UMAGATTOperationOutcome::NOT_PERMITTED); |
| 43 return blink::mojom::WebBluetoothError::GATT_NOT_PERMITTED; | 48 return blink::mojom::WebBluetoothError::GATT_NOT_PERMITTED; |
| 44 case BluetoothRemoteGattService::GATT_ERROR_NOT_AUTHORIZED: | 49 case device::BluetoothRemoteGattService::GATT_ERROR_NOT_AUTHORIZED: |
| 45 RecordGATTOperationOutcome(operation, | 50 RecordGATTOperationOutcome(operation, |
| 46 UMAGATTOperationOutcome::NOT_AUTHORIZED); | 51 UMAGATTOperationOutcome::NOT_AUTHORIZED); |
| 47 return blink::mojom::WebBluetoothError::GATT_NOT_AUTHORIZED; | 52 return blink::mojom::WebBluetoothError::GATT_NOT_AUTHORIZED; |
| 48 case BluetoothRemoteGattService::GATT_ERROR_NOT_PAIRED: | 53 case device::BluetoothRemoteGattService::GATT_ERROR_NOT_PAIRED: |
| 49 RecordGATTOperationOutcome(operation, | 54 RecordGATTOperationOutcome(operation, |
| 50 UMAGATTOperationOutcome::NOT_PAIRED); | 55 UMAGATTOperationOutcome::NOT_PAIRED); |
| 51 return blink::mojom::WebBluetoothError::GATT_NOT_PAIRED; | 56 return blink::mojom::WebBluetoothError::GATT_NOT_PAIRED; |
| 52 case BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED: | 57 case device::BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED: |
| 53 RecordGATTOperationOutcome(operation, | 58 RecordGATTOperationOutcome(operation, |
| 54 UMAGATTOperationOutcome::NOT_SUPPORTED); | 59 UMAGATTOperationOutcome::NOT_SUPPORTED); |
| 55 return blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED; | 60 return blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED; |
| 56 } | 61 } |
| 57 NOTREACHED(); | 62 NOTREACHED(); |
| 58 return blink::mojom::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE; | 63 return blink::mojom::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE; |
| 59 } | 64 } |
| 60 | 65 |
| 66 // TODO(ortuno): This should really be a BluetoothDevice method. |
| 67 // Replace when implemented. http://crbug.com/552022 |
| 68 std::vector<device::BluetoothRemoteGattCharacteristic*> |
| 69 GetCharacteristicsByUUID(device::BluetoothRemoteGattService* service, |
| 70 const std::string& characteristic_uuid) { |
| 71 std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics; |
| 72 VLOG(1) << "Looking for characteristic: " << characteristic_uuid; |
| 73 for (device::BluetoothRemoteGattCharacteristic* characteristic : |
| 74 service->GetCharacteristics()) { |
| 75 VLOG(1) << "Characteristic in cache: " |
| 76 << characteristic->GetUUID().canonical_value(); |
| 77 if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { |
| 78 characteristics.push_back(characteristic); |
| 79 } |
| 80 } |
| 81 return characteristics; |
| 82 } |
| 83 |
| 61 } // namespace | 84 } // namespace |
| 62 | 85 |
| 63 using CacheQueryResult = BluetoothDispatcherHost::CacheQueryResult; | |
| 64 | |
| 65 WebBluetoothServiceImpl::WebBluetoothServiceImpl( | 86 WebBluetoothServiceImpl::WebBluetoothServiceImpl( |
| 66 RenderFrameHost* render_frame_host, | 87 RenderFrameHost* render_frame_host, |
| 67 blink::mojom::WebBluetoothServiceRequest request) | 88 blink::mojom::WebBluetoothServiceRequest request) |
| 68 : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)), | 89 : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)), |
| 69 render_frame_host_(render_frame_host), | 90 render_frame_host_(render_frame_host), |
| 70 binding_(this, std::move(request)), | 91 binding_(this, std::move(request)), |
| 71 weak_ptr_factory_(this) { | 92 weak_ptr_factory_(this) { |
| 72 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 93 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 73 CHECK(web_contents()); | 94 CHECK(web_contents()); |
| 74 | 95 |
| 75 GetBluetoothDispatcherHost()->AddAdapterObserver(this); | 96 GetBluetoothDispatcherHost()->AddAdapterObserver(this); |
| 76 } | 97 } |
| 77 | 98 |
| 78 WebBluetoothServiceImpl::~WebBluetoothServiceImpl() { | 99 WebBluetoothServiceImpl::~WebBluetoothServiceImpl() { |
| 79 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 100 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 80 GetBluetoothDispatcherHost()->RemoveAdapterObserver(this); | 101 GetBluetoothDispatcherHost()->RemoveAdapterObserver(this); |
| 81 } | 102 } |
| 82 | 103 |
| 83 void WebBluetoothServiceImpl::SetClientConnectionErrorHandler( | 104 void WebBluetoothServiceImpl::SetClientConnectionErrorHandler( |
| 84 base::Closure closure) { | 105 base::Closure closure) { |
| 85 binding_.set_connection_error_handler(closure); | 106 binding_.set_connection_error_handler(closure); |
| 86 } | 107 } |
| 87 | 108 |
| 88 void WebBluetoothServiceImpl::DidFinishNavigation( | 109 void WebBluetoothServiceImpl::DidFinishNavigation( |
| 89 NavigationHandle* navigation_handle) { | 110 NavigationHandle* navigation_handle) { |
| 90 if (navigation_handle->HasCommitted() && | 111 if (navigation_handle->HasCommitted() && |
| 91 navigation_handle->GetRenderFrameHost() == render_frame_host_ && | 112 navigation_handle->GetRenderFrameHost() == render_frame_host_ && |
| 92 !navigation_handle->IsSamePage()) { | 113 !navigation_handle->IsSamePage()) { |
| 93 // After navigation we need to clear the frame's state. | |
| 94 ClearState(); | 114 ClearState(); |
| 95 } | 115 } |
| 96 } | 116 } |
| 97 | 117 |
| 98 void WebBluetoothServiceImpl::AdapterPresentChanged( | 118 void WebBluetoothServiceImpl::AdapterPresentChanged( |
| 99 device::BluetoothAdapter* adapter, | 119 device::BluetoothAdapter* adapter, |
| 100 bool present) { | 120 bool present) { |
| 101 if (!present) { | 121 if (!present) { |
| 102 ClearState(); | 122 ClearState(); |
| 103 } | 123 } |
| 104 } | 124 } |
| 105 | 125 |
| 106 void WebBluetoothServiceImpl::GattCharacteristicValueChanged( | 126 void WebBluetoothServiceImpl::GattCharacteristicValueChanged( |
| 107 device::BluetoothAdapter* adapter, | 127 device::BluetoothAdapter* adapter, |
| 108 device::BluetoothRemoteGattCharacteristic* characteristic, | 128 device::BluetoothRemoteGattCharacteristic* characteristic, |
| 109 const std::vector<uint8_t>& value) { | 129 const std::vector<uint8_t>& value) { |
| 110 // TODO(ortuno): Only send characteristic value changed events for | 130 // Don't notify of characteristics that we haven't returned. |
| 111 // characteristics that we've returned in the past. We can't yet do | 131 if (!ContainsKey(characteristic_id_to_service_id_, |
| 112 // this because WebBluetoothServiceImpl doesn't have direct access | 132 characteristic->GetIdentifier())) { |
| 113 // to the list of returned characteristics. | |
| 114 // https://crbug.com/508771 | |
| 115 if (BluetoothBlacklist::Get().IsExcluded(characteristic->GetUUID())) { | |
| 116 return; | 133 return; |
| 117 } | 134 } |
| 118 | 135 |
| 119 // On Chrome OS and Linux, GattCharacteristicValueChanged is called before the | 136 // On Chrome OS and Linux, GattCharacteristicValueChanged is called before the |
| 120 // success callback for ReadRemoteCharacteristic is called, which could result | 137 // success callback for ReadRemoteCharacteristic is called, which could result |
| 121 // in an event being fired before the readValue promise is resolved. | 138 // in an event being fired before the readValue promise is resolved. |
| 122 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( | 139 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 123 FROM_HERE, | 140 FROM_HERE, |
| 124 base::Bind(&WebBluetoothServiceImpl::NotifyCharacteristicValueChanged, | 141 base::Bind(&WebBluetoothServiceImpl::NotifyCharacteristicValueChanged, |
| 125 weak_ptr_factory_.GetWeakPtr(), | 142 weak_ptr_factory_.GetWeakPtr(), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 136 characteristic_instance_id, mojo::Array<uint8_t>(std::move(value))); | 153 characteristic_instance_id, mojo::Array<uint8_t>(std::move(value))); |
| 137 } | 154 } |
| 138 } | 155 } |
| 139 | 156 |
| 140 void WebBluetoothServiceImpl::SetClient( | 157 void WebBluetoothServiceImpl::SetClient( |
| 141 blink::mojom::WebBluetoothServiceClientAssociatedPtrInfo client) { | 158 blink::mojom::WebBluetoothServiceClientAssociatedPtrInfo client) { |
| 142 DCHECK(!client_.get()); | 159 DCHECK(!client_.get()); |
| 143 client_.Bind(std::move(client)); | 160 client_.Bind(std::move(client)); |
| 144 } | 161 } |
| 145 | 162 |
| 163 void WebBluetoothServiceImpl::RemoteServiceGetCharacteristics( |
| 164 const mojo::String& service_instance_id, |
| 165 blink::mojom::WebBluetoothGATTQueryQuantity quantity, |
| 166 const mojo::String& characteristics_uuid, |
| 167 const RemoteServiceGetCharacteristicsCallback& callback) { |
| 168 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 169 RecordWebBluetoothFunctionCall( |
| 170 quantity == blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE |
| 171 ? UMAWebBluetoothFunction::SERVICE_GET_CHARACTERISTIC |
| 172 : UMAWebBluetoothFunction::SERVICE_GET_CHARACTERISTICS); |
| 173 RecordGetCharacteristicsCharacteristic(quantity, characteristics_uuid); |
| 174 |
| 175 if (!characteristics_uuid.is_null() && |
| 176 BluetoothBlacklist::Get().IsExcluded( |
| 177 device::BluetoothUUID(characteristics_uuid))) { |
| 178 RecordGetCharacteristicsOutcome(quantity, |
| 179 UMAGetCharacteristicOutcome::BLACKLISTED); |
| 180 callback.Run( |
| 181 blink::mojom::WebBluetoothError::BLACKLISTED_CHARACTERISTIC_UUID, |
| 182 nullptr /* characteristics */); |
| 183 return; |
| 184 } |
| 185 |
| 186 const CacheQueryResult query_result = |
| 187 GetBluetoothDispatcherHost()->QueryCacheForService(GetOrigin(), |
| 188 service_instance_id); |
| 189 |
| 190 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 191 binding_.Close(); |
| 192 return; |
| 193 } |
| 194 |
| 195 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| 196 RecordGetCharacteristicsOutcome(quantity, query_result.outcome); |
| 197 callback.Run(query_result.GetWebError(), nullptr /* characteristics */); |
| 198 return; |
| 199 } |
| 200 |
| 201 std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics = |
| 202 characteristics_uuid.is_null() |
| 203 ? query_result.service->GetCharacteristics() |
| 204 : GetCharacteristicsByUUID(query_result.service, |
| 205 characteristics_uuid); |
| 206 |
| 207 mojo::Array<blink::mojom::WebBluetoothRemoteGATTCharacteristicPtr> |
| 208 response_characteristics; |
| 209 for (device::BluetoothRemoteGattCharacteristic* characteristic : |
| 210 characteristics) { |
| 211 if (BluetoothBlacklist::Get().IsExcluded(characteristic->GetUUID())) { |
| 212 continue; |
| 213 } |
| 214 std::string characteristic_instance_id = characteristic->GetIdentifier(); |
| 215 auto insert_result = characteristic_id_to_service_id_.insert( |
| 216 std::make_pair(characteristic_instance_id, service_instance_id)); |
| 217 // If value is already in map, DCHECK it's valid. |
| 218 if (!insert_result.second) |
| 219 DCHECK(insert_result.first->second == service_instance_id); |
| 220 |
| 221 blink::mojom::WebBluetoothRemoteGATTCharacteristicPtr characteristic_ptr = |
| 222 blink::mojom::WebBluetoothRemoteGATTCharacteristic::New(); |
| 223 characteristic_ptr->instance_id = |
| 224 mojo::String::From(characteristic_instance_id); |
| 225 characteristic_ptr->uuid = |
| 226 mojo::String::From(characteristic->GetUUID().canonical_value()); |
| 227 characteristic_ptr->properties = |
| 228 static_cast<uint32_t>(characteristic->GetProperties()); |
| 229 response_characteristics.push_back(std::move(characteristic_ptr)); |
| 230 |
| 231 if (quantity == blink::mojom::WebBluetoothGATTQueryQuantity::SINGLE) { |
| 232 break; |
| 233 } |
| 234 } |
| 235 |
| 236 if (!response_characteristics.empty()) { |
| 237 RecordGetCharacteristicsOutcome(quantity, |
| 238 UMAGetCharacteristicOutcome::SUCCESS); |
| 239 callback.Run(blink::mojom::WebBluetoothError::SUCCESS, |
| 240 std::move(response_characteristics)); |
| 241 return; |
| 242 } |
| 243 RecordGetCharacteristicsOutcome( |
| 244 quantity, characteristics_uuid.is_null() |
| 245 ? UMAGetCharacteristicOutcome::NO_CHARACTERISTICS |
| 246 : UMAGetCharacteristicOutcome::NOT_FOUND); |
| 247 callback.Run(characteristics_uuid.is_null() |
| 248 ? blink::mojom::WebBluetoothError::NO_CHARACTERISTICS_FOUND |
| 249 : blink::mojom::WebBluetoothError::CHARACTERISTIC_NOT_FOUND, |
| 250 nullptr /* characteristics */); |
| 251 return; |
| 252 } |
| 253 |
| 146 void WebBluetoothServiceImpl::RemoteCharacteristicReadValue( | 254 void WebBluetoothServiceImpl::RemoteCharacteristicReadValue( |
| 147 const mojo::String& characteristic_instance_id, | 255 const mojo::String& characteristic_instance_id, |
| 148 const RemoteCharacteristicReadValueCallback& callback) { | 256 const RemoteCharacteristicReadValueCallback& callback) { |
| 149 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 257 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 150 RecordWebBluetoothFunctionCall( | 258 RecordWebBluetoothFunctionCall( |
| 151 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 259 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); |
| 152 | 260 |
| 153 const CacheQueryResult query_result = | 261 const CacheQueryResult query_result = |
| 154 GetBluetoothDispatcherHost()->QueryCacheForCharacteristic( | 262 QueryCacheForCharacteristic(characteristic_instance_id); |
| 155 GetOrigin(), characteristic_instance_id); | |
| 156 | 263 |
| 157 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 264 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 158 return; | 265 return; |
| 159 } | 266 } |
| 160 | 267 |
| 161 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 268 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| 162 RecordCharacteristicReadValueOutcome(query_result.outcome); | 269 RecordCharacteristicReadValueOutcome(query_result.outcome); |
| 163 callback.Run(query_result.GetWebError(), nullptr /* value */); | 270 callback.Run(query_result.GetWebError(), nullptr /* value */); |
| 164 return; | 271 return; |
| 165 } | 272 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 189 | 296 |
| 190 // We perform the length check on the renderer side. So if we | 297 // We perform the length check on the renderer side. So if we |
| 191 // get a value with length > 512, we can assume it's a hostile | 298 // get a value with length > 512, we can assume it's a hostile |
| 192 // renderer and kill it. | 299 // renderer and kill it. |
| 193 if (value.size() > 512) { | 300 if (value.size() > 512) { |
| 194 CrashRendererAndClosePipe(bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 301 CrashRendererAndClosePipe(bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); |
| 195 return; | 302 return; |
| 196 } | 303 } |
| 197 | 304 |
| 198 const CacheQueryResult query_result = | 305 const CacheQueryResult query_result = |
| 199 GetBluetoothDispatcherHost()->QueryCacheForCharacteristic( | 306 QueryCacheForCharacteristic(characteristic_instance_id); |
| 200 GetOrigin(), characteristic_instance_id); | |
| 201 | 307 |
| 202 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 308 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 203 binding_.Close(); | |
| 204 return; | 309 return; |
| 205 } | 310 } |
| 206 | 311 |
| 207 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 312 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| 208 RecordCharacteristicWriteValueOutcome(query_result.outcome); | 313 RecordCharacteristicWriteValueOutcome(query_result.outcome); |
| 209 callback.Run(query_result.GetWebError()); | 314 callback.Run(query_result.GetWebError()); |
| 210 return; | 315 return; |
| 211 } | 316 } |
| 212 | 317 |
| 213 if (BluetoothBlacklist::Get().IsExcludedFromWrites( | 318 if (BluetoothBlacklist::Get().IsExcludedFromWrites( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 236 characteristic_id_to_notify_session_.find(characteristic_instance_id); | 341 characteristic_id_to_notify_session_.find(characteristic_instance_id); |
| 237 if (iter != characteristic_id_to_notify_session_.end() && | 342 if (iter != characteristic_id_to_notify_session_.end() && |
| 238 iter->second->IsActive()) { | 343 iter->second->IsActive()) { |
| 239 // If the frame has already started notifications and the notifications | 344 // If the frame has already started notifications and the notifications |
| 240 // are active we return SUCCESS. | 345 // are active we return SUCCESS. |
| 241 callback.Run(blink::mojom::WebBluetoothError::SUCCESS); | 346 callback.Run(blink::mojom::WebBluetoothError::SUCCESS); |
| 242 return; | 347 return; |
| 243 } | 348 } |
| 244 | 349 |
| 245 const CacheQueryResult query_result = | 350 const CacheQueryResult query_result = |
| 246 GetBluetoothDispatcherHost()->QueryCacheForCharacteristic( | 351 QueryCacheForCharacteristic(characteristic_instance_id); |
| 247 GetOrigin(), characteristic_instance_id); | |
| 248 | 352 |
| 249 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 353 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 250 binding_.Close(); | |
| 251 return; | 354 return; |
| 252 } | 355 } |
| 253 | 356 |
| 254 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 357 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| 255 RecordStartNotificationsOutcome(query_result.outcome); | 358 RecordStartNotificationsOutcome(query_result.outcome); |
| 256 callback.Run(query_result.GetWebError()); | 359 callback.Run(query_result.GetWebError()); |
| 257 return; | 360 return; |
| 258 } | 361 } |
| 259 | 362 |
| 260 device::BluetoothRemoteGattCharacteristic::Properties notify_or_indicate = | 363 device::BluetoothRemoteGattCharacteristic::Properties notify_or_indicate = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 274 } | 377 } |
| 275 | 378 |
| 276 void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications( | 379 void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications( |
| 277 const mojo::String& characteristic_instance_id, | 380 const mojo::String& characteristic_instance_id, |
| 278 const RemoteCharacteristicStopNotificationsCallback& callback) { | 381 const RemoteCharacteristicStopNotificationsCallback& callback) { |
| 279 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 382 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 280 RecordWebBluetoothFunctionCall( | 383 RecordWebBluetoothFunctionCall( |
| 281 UMAWebBluetoothFunction::CHARACTERISTIC_STOP_NOTIFICATIONS); | 384 UMAWebBluetoothFunction::CHARACTERISTIC_STOP_NOTIFICATIONS); |
| 282 | 385 |
| 283 const CacheQueryResult query_result = | 386 const CacheQueryResult query_result = |
| 284 GetBluetoothDispatcherHost()->QueryCacheForCharacteristic( | 387 QueryCacheForCharacteristic(characteristic_instance_id); |
| 285 GetOrigin(), characteristic_instance_id); | |
| 286 | 388 |
| 287 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 389 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 288 binding_.Close(); | |
| 289 return; | 390 return; |
| 290 } | 391 } |
| 291 | 392 |
| 292 auto notify_session_iter = | 393 auto notify_session_iter = |
| 293 characteristic_id_to_notify_session_.find(characteristic_instance_id); | 394 characteristic_id_to_notify_session_.find(characteristic_instance_id); |
| 294 if (notify_session_iter == characteristic_id_to_notify_session_.end()) { | 395 if (notify_session_iter == characteristic_id_to_notify_session_.end()) { |
| 295 // If the frame hasn't subscribed to notifications before we just | 396 // If the frame hasn't subscribed to notifications before we just |
| 296 // run the callback. | 397 // run the callback. |
| 297 callback.Run(); | 398 callback.Run(); |
| 298 return; | 399 return; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 error_code, UMAGATTOperation::START_NOTIFICATIONS)); | 458 error_code, UMAGATTOperation::START_NOTIFICATIONS)); |
| 358 } | 459 } |
| 359 | 460 |
| 360 void WebBluetoothServiceImpl::OnStopNotifySessionComplete( | 461 void WebBluetoothServiceImpl::OnStopNotifySessionComplete( |
| 361 const std::string& characteristic_instance_id, | 462 const std::string& characteristic_instance_id, |
| 362 const RemoteCharacteristicStopNotificationsCallback& callback) { | 463 const RemoteCharacteristicStopNotificationsCallback& callback) { |
| 363 characteristic_id_to_notify_session_.erase(characteristic_instance_id); | 464 characteristic_id_to_notify_session_.erase(characteristic_instance_id); |
| 364 callback.Run(); | 465 callback.Run(); |
| 365 } | 466 } |
| 366 | 467 |
| 468 CacheQueryResult WebBluetoothServiceImpl::QueryCacheForCharacteristic( |
| 469 const std::string& characteristic_instance_id) { |
| 470 auto characteristic_iter = |
| 471 characteristic_id_to_service_id_.find(characteristic_instance_id); |
| 472 |
| 473 // Kill the render, see "ID Not in Map Note" above. |
| 474 if (characteristic_iter == characteristic_id_to_service_id_.end()) { |
| 475 CrashRendererAndClosePipe(bad_message::BDH_INVALID_CHARACTERISTIC_ID); |
| 476 return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
| 477 } |
| 478 |
| 479 CacheQueryResult result = GetBluetoothDispatcherHost()->QueryCacheForService( |
| 480 GetOrigin(), characteristic_iter->second); |
| 481 |
| 482 // TODO(ortuno): Remove once QueryCacheForService closes binding_. |
| 483 // http://crbug.com/508771 |
| 484 if (result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| 485 binding_.Close(); |
| 486 } |
| 487 |
| 488 if (result.outcome != CacheQueryOutcome::SUCCESS) { |
| 489 return result; |
| 490 } |
| 491 |
| 492 result.characteristic = |
| 493 result.service->GetCharacteristic(characteristic_instance_id); |
| 494 |
| 495 if (result.characteristic == nullptr) { |
| 496 result.outcome = CacheQueryOutcome::NO_CHARACTERISTIC; |
| 497 } |
| 498 |
| 499 return result; |
| 500 } |
| 501 |
| 367 RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() { | 502 RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() { |
| 368 return render_frame_host_->GetProcess(); | 503 return render_frame_host_->GetProcess(); |
| 369 } | 504 } |
| 370 | 505 |
| 371 BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() { | 506 BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() { |
| 372 RenderProcessHostImpl* render_process_host_impl = | 507 RenderProcessHostImpl* render_process_host_impl = |
| 373 static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()); | 508 static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()); |
| 374 return render_process_host_impl->GetBluetoothDispatcherHost(); | 509 return render_process_host_impl->GetBluetoothDispatcherHost(); |
| 375 } | 510 } |
| 376 | 511 |
| 377 void WebBluetoothServiceImpl::CrashRendererAndClosePipe( | 512 void WebBluetoothServiceImpl::CrashRendererAndClosePipe( |
| 378 bad_message::BadMessageReason reason) { | 513 bad_message::BadMessageReason reason) { |
| 379 bad_message::ReceivedBadMessage(GetRenderProcessHost(), reason); | 514 bad_message::ReceivedBadMessage(GetRenderProcessHost(), reason); |
| 380 binding_.Close(); | 515 binding_.Close(); |
| 381 } | 516 } |
| 382 | 517 |
| 383 url::Origin WebBluetoothServiceImpl::GetOrigin() { | 518 url::Origin WebBluetoothServiceImpl::GetOrigin() { |
| 384 return render_frame_host_->GetLastCommittedOrigin(); | 519 return render_frame_host_->GetLastCommittedOrigin(); |
| 385 } | 520 } |
| 386 | 521 |
| 387 void WebBluetoothServiceImpl::ClearState() { | 522 void WebBluetoothServiceImpl::ClearState() { |
| 388 characteristic_id_to_notify_session_.clear(); | 523 characteristic_id_to_notify_session_.clear(); |
| 524 characteristic_id_to_service_id_.clear(); |
| 389 } | 525 } |
| 390 | 526 |
| 391 } // namespace content | 527 } // namespace content |
| OLD | NEW |