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 // ID Not In Map Note: | 5 // ID Not In Map Note: |
6 // A service, characteristic, or descriptor ID not in the corresponding | 6 // A service, characteristic, or descriptor ID not in the corresponding |
7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, |
8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer | 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer |
9 // 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 |
10 // at that time. | 10 // at that time. |
11 | 11 |
12 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 12 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
13 | 13 |
14 #include <stddef.h> | 14 #include <stddef.h> |
15 | 15 |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
18 #include "base/bind.h" | 18 #include "base/bind.h" |
19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
21 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" |
22 #include "content/browser/bad_message.h" | 22 #include "content/browser/bad_message.h" |
23 #include "content/browser/bluetooth/bluetooth_blacklist.h" | 23 #include "content/browser/bluetooth/bluetooth_blacklist.h" |
24 #include "content/browser/bluetooth/bluetooth_metrics.h" | |
25 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" | 24 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" |
26 #include "content/browser/frame_host/render_frame_host_impl.h" | 25 #include "content/browser/frame_host/render_frame_host_impl.h" |
27 #include "content/common/bluetooth/bluetooth_messages.h" | |
28 #include "content/public/browser/content_browser_client.h" | 26 #include "content/public/browser/content_browser_client.h" |
29 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
30 #include "content/public/browser/web_contents_delegate.h" | 28 #include "content/public/browser/web_contents_delegate.h" |
31 #include "device/bluetooth/bluetooth_adapter.h" | 29 #include "device/bluetooth/bluetooth_adapter.h" |
32 #include "device/bluetooth/bluetooth_adapter_factory.h" | 30 #include "device/bluetooth/bluetooth_adapter_factory.h" |
33 #include "device/bluetooth/bluetooth_device.h" | 31 #include "device/bluetooth/bluetooth_device.h" |
34 #include "device/bluetooth/bluetooth_discovery_session.h" | 32 #include "device/bluetooth/bluetooth_discovery_session.h" |
35 #include "device/bluetooth/bluetooth_gatt_characteristic.h" | 33 #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
36 #include "device/bluetooth/bluetooth_gatt_service.h" | 34 #include "device/bluetooth/bluetooth_gatt_service.h" |
37 | 35 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 RecordConnectGATTOutcome(UMAConnectGATTOutcome::WRITE_NOT_PERMITTED); | 160 RecordConnectGATTOutcome(UMAConnectGATTOutcome::WRITE_NOT_PERMITTED); |
163 return WebBluetoothError::CONNECT_WRITE_NOT_PERMITTED; | 161 return WebBluetoothError::CONNECT_WRITE_NOT_PERMITTED; |
164 case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES: | 162 case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES: |
165 NOTREACHED(); | 163 NOTREACHED(); |
166 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; | 164 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; |
167 } | 165 } |
168 NOTREACHED(); | 166 NOTREACHED(); |
169 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; | 167 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; |
170 } | 168 } |
171 | 169 |
172 blink::WebBluetoothError TranslateGATTError( | 170 WebBluetoothError TranslateGATTError( |
173 BluetoothGattService::GattErrorCode error_code, | 171 BluetoothGattService::GattErrorCode error_code, |
174 UMAGATTOperation operation) { | 172 UMAGATTOperation operation) { |
175 switch (error_code) { | 173 switch (error_code) { |
176 case BluetoothGattService::GATT_ERROR_UNKNOWN: | 174 case BluetoothGattService::GATT_ERROR_UNKNOWN: |
177 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN); | 175 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN); |
178 return blink::WebBluetoothError::GATT_UNKNOWN_ERROR; | 176 return blink::WebBluetoothError::GATT_UNKNOWN_ERROR; |
179 case BluetoothGattService::GATT_ERROR_FAILED: | 177 case BluetoothGattService::GATT_ERROR_FAILED: |
180 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED); | 178 RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED); |
181 return blink::WebBluetoothError::GATT_UNKNOWN_FAILURE; | 179 return blink::WebBluetoothError::GATT_UNKNOWN_FAILURE; |
182 case BluetoothGattService::GATT_ERROR_IN_PROGRESS: | 180 case BluetoothGattService::GATT_ERROR_IN_PROGRESS: |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 bool handled = true; | 301 bool handled = true; |
304 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) | 302 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) |
305 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) | 303 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) |
306 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerConnect, OnGATTServerConnect) | 304 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerConnect, OnGATTServerConnect) |
307 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerDisconnect, | 305 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerDisconnect, |
308 OnGATTServerDisconnect) | 306 OnGATTServerDisconnect) |
309 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService) | 307 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService) |
310 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic) | 308 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic) |
311 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristics, OnGetCharacteristics) | 309 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristics, OnGetCharacteristics) |
312 IPC_MESSAGE_HANDLER(BluetoothHostMsg_ReadValue, OnReadValue) | 310 IPC_MESSAGE_HANDLER(BluetoothHostMsg_ReadValue, OnReadValue) |
313 IPC_MESSAGE_HANDLER(BluetoothHostMsg_WriteValue, OnWriteValue) | |
314 IPC_MESSAGE_HANDLER(BluetoothHostMsg_StartNotifications, OnStartNotifications) | 311 IPC_MESSAGE_HANDLER(BluetoothHostMsg_StartNotifications, OnStartNotifications) |
315 IPC_MESSAGE_HANDLER(BluetoothHostMsg_StopNotifications, OnStopNotifications) | 312 IPC_MESSAGE_HANDLER(BluetoothHostMsg_StopNotifications, OnStopNotifications) |
316 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RegisterCharacteristic, | 313 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RegisterCharacteristic, |
317 OnRegisterCharacteristicObject); | 314 OnRegisterCharacteristicObject); |
318 IPC_MESSAGE_HANDLER(BluetoothHostMsg_UnregisterCharacteristic, | 315 IPC_MESSAGE_HANDLER(BluetoothHostMsg_UnregisterCharacteristic, |
319 OnUnregisterCharacteristicObject); | 316 OnUnregisterCharacteristicObject); |
320 IPC_MESSAGE_UNHANDLED(handled = false) | 317 IPC_MESSAGE_UNHANDLED(handled = false) |
321 IPC_END_MESSAGE_MAP() | 318 IPC_END_MESSAGE_MAP() |
322 return handled; | 319 return handled; |
323 } | 320 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 const int thread_id; | 399 const int thread_id; |
403 const int request_id; | 400 const int request_id; |
404 const int frame_routing_id; | 401 const int frame_routing_id; |
405 const url::Origin origin; | 402 const url::Origin origin; |
406 const std::vector<BluetoothScanFilter> filters; | 403 const std::vector<BluetoothScanFilter> filters; |
407 const std::vector<BluetoothUUID> optional_services; | 404 const std::vector<BluetoothUUID> optional_services; |
408 scoped_ptr<BluetoothChooser> chooser; | 405 scoped_ptr<BluetoothChooser> chooser; |
409 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 406 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; |
410 }; | 407 }; |
411 | 408 |
412 struct BluetoothDispatcherHost::CacheQueryResult { | 409 BluetoothDispatcherHost::CacheQueryResult::CacheQueryResult() {} |
413 CacheQueryResult() | 410 |
414 : device(nullptr), | 411 BluetoothDispatcherHost::CacheQueryResult::CacheQueryResult( |
415 service(nullptr), | 412 CacheQueryOutcome outcome) |
416 characteristic(nullptr), | 413 : outcome(outcome) {} |
417 outcome(CacheQueryOutcome::SUCCESS) {} | 414 |
418 CacheQueryResult(CacheQueryOutcome outcome) | 415 BluetoothDispatcherHost::CacheQueryResult::~CacheQueryResult() {} |
419 : device(nullptr), | 416 |
420 service(nullptr), | 417 WebBluetoothError BluetoothDispatcherHost::CacheQueryResult::GetWebError() |
421 characteristic(nullptr), | 418 const { |
422 outcome(outcome) {} | 419 switch (outcome) { |
423 ~CacheQueryResult() {} | 420 case CacheQueryOutcome::SUCCESS: |
424 WebBluetoothError GetWebError() const { | 421 case CacheQueryOutcome::BAD_RENDERER: |
425 switch (outcome) { | 422 NOTREACHED(); |
426 case CacheQueryOutcome::SUCCESS: | 423 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
427 case CacheQueryOutcome::BAD_RENDERER: | 424 case CacheQueryOutcome::NO_DEVICE: |
428 NOTREACHED(); | 425 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
429 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; | 426 case CacheQueryOutcome::NO_SERVICE: |
430 case CacheQueryOutcome::NO_DEVICE: | 427 return WebBluetoothError::SERVICE_NO_LONGER_EXISTS; |
431 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; | 428 case CacheQueryOutcome::NO_CHARACTERISTIC: |
432 case CacheQueryOutcome::NO_SERVICE: | 429 return WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS; |
433 return WebBluetoothError::SERVICE_NO_LONGER_EXISTS; | |
434 case CacheQueryOutcome::NO_CHARACTERISTIC: | |
435 return WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS; | |
436 } | |
437 NOTREACHED(); | |
438 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; | |
439 } | 430 } |
440 | 431 NOTREACHED(); |
441 device::BluetoothDevice* device; | 432 return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
442 device::BluetoothGattService* service; | 433 } |
443 device::BluetoothGattCharacteristic* characteristic; | |
444 CacheQueryOutcome outcome; | |
445 }; | |
446 | 434 |
447 struct BluetoothDispatcherHost::PrimaryServicesRequest { | 435 struct BluetoothDispatcherHost::PrimaryServicesRequest { |
448 enum CallingFunction { GET_PRIMARY_SERVICE, GET_PRIMARY_SERVICES }; | 436 enum CallingFunction { GET_PRIMARY_SERVICE, GET_PRIMARY_SERVICES }; |
449 | 437 |
450 PrimaryServicesRequest(int thread_id, | 438 PrimaryServicesRequest(int thread_id, |
451 int request_id, | 439 int request_id, |
452 const std::string& service_uuid, | 440 const std::string& service_uuid, |
453 PrimaryServicesRequest::CallingFunction func) | 441 PrimaryServicesRequest::CallingFunction func) |
454 : thread_id(thread_id), | 442 : thread_id(thread_id), |
455 request_id(request_id), | 443 request_id(request_id), |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 return; | 968 return; |
981 } | 969 } |
982 | 970 |
983 query_result.characteristic->ReadRemoteCharacteristic( | 971 query_result.characteristic->ReadRemoteCharacteristic( |
984 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 972 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, |
985 weak_ptr_on_ui_thread_, thread_id, request_id), | 973 weak_ptr_on_ui_thread_, thread_id, request_id), |
986 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 974 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, |
987 weak_ptr_on_ui_thread_, thread_id, request_id)); | 975 weak_ptr_on_ui_thread_, thread_id, request_id)); |
988 } | 976 } |
989 | 977 |
990 void BluetoothDispatcherHost::OnWriteValue( | |
991 int thread_id, | |
992 int request_id, | |
993 int frame_routing_id, | |
994 const std::string& characteristic_instance_id, | |
995 const std::vector<uint8_t>& value) { | |
996 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
997 RecordWebBluetoothFunctionCall( | |
998 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | |
999 | |
1000 // Length check per step 3 of writeValue algorithm: | |
1001 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
teristic-writevalue | |
1002 // We perform the length check on the renderer side. So if we | |
1003 // get a value with length > 512, we can assume it's a hostile | |
1004 // renderer and kill it. | |
1005 if (value.size() > 512) { | |
1006 bad_message::ReceivedBadMessage( | |
1007 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | |
1008 return; | |
1009 } | |
1010 | |
1011 const CacheQueryResult query_result = QueryCacheForCharacteristic( | |
1012 GetOrigin(frame_routing_id), characteristic_instance_id); | |
1013 | |
1014 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | |
1015 return; | |
1016 } | |
1017 | |
1018 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | |
1019 RecordCharacteristicWriteValueOutcome(query_result.outcome); | |
1020 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
1021 thread_id, request_id, query_result.GetWebError())); | |
1022 return; | |
1023 } | |
1024 | |
1025 if (BluetoothBlacklist::Get().IsExcludedFromWrites( | |
1026 query_result.characteristic->GetUUID())) { | |
1027 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::BLACKLISTED); | |
1028 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
1029 thread_id, request_id, WebBluetoothError::BLACKLISTED_WRITE)); | |
1030 return; | |
1031 } | |
1032 | |
1033 query_result.characteristic->WriteRemoteCharacteristic( | |
1034 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | |
1035 weak_ptr_on_ui_thread_, thread_id, request_id), | |
1036 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | |
1037 weak_ptr_on_ui_thread_, thread_id, request_id)); | |
1038 } | |
1039 | |
1040 void BluetoothDispatcherHost::OnStartNotifications( | 978 void BluetoothDispatcherHost::OnStartNotifications( |
1041 int thread_id, | 979 int thread_id, |
1042 int request_id, | 980 int request_id, |
1043 int frame_routing_id, | 981 int frame_routing_id, |
1044 const std::string& characteristic_instance_id) { | 982 const std::string& characteristic_instance_id) { |
1045 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 983 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1046 RecordWebBluetoothFunctionCall( | 984 RecordWebBluetoothFunctionCall( |
1047 UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); | 985 UMAWebBluetoothFunction::CHARACTERISTIC_START_NOTIFICATIONS); |
1048 | 986 |
1049 // BluetoothDispatcher will never send a request for a characteristic | 987 // BluetoothDispatcher will never send a request for a characteristic |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 int thread_id, | 1455 int thread_id, |
1518 int request_id, | 1456 int request_id, |
1519 device::BluetoothGattService::GattErrorCode error_code) { | 1457 device::BluetoothGattService::GattErrorCode error_code) { |
1520 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1458 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1521 // TranslateGATTError calls RecordGATTOperationOutcome. | 1459 // TranslateGATTError calls RecordGATTOperationOutcome. |
1522 Send(new BluetoothMsg_ReadCharacteristicValueError( | 1460 Send(new BluetoothMsg_ReadCharacteristicValueError( |
1523 thread_id, request_id, | 1461 thread_id, request_id, |
1524 TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_READ))); | 1462 TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_READ))); |
1525 } | 1463 } |
1526 | 1464 |
1527 void BluetoothDispatcherHost::OnWriteValueSuccess(int thread_id, | |
1528 int request_id) { | |
1529 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1530 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS); | |
1531 Send(new BluetoothMsg_WriteCharacteristicValueSuccess(thread_id, request_id)); | |
1532 } | |
1533 | |
1534 void BluetoothDispatcherHost::OnWriteValueFailed( | |
1535 int thread_id, | |
1536 int request_id, | |
1537 device::BluetoothGattService::GattErrorCode error_code) { | |
1538 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1539 // TranslateGATTError calls RecordGATTOperationOutcome. | |
1540 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
1541 thread_id, request_id, | |
1542 TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_WRITE))); | |
1543 } | |
1544 | |
1545 void BluetoothDispatcherHost::OnStartNotifySessionSuccess( | 1465 void BluetoothDispatcherHost::OnStartNotifySessionSuccess( |
1546 int thread_id, | 1466 int thread_id, |
1547 int request_id, | 1467 int request_id, |
1548 scoped_ptr<device::BluetoothGattNotifySession> notify_session) { | 1468 scoped_ptr<device::BluetoothGattNotifySession> notify_session) { |
1549 RecordStartNotificationsOutcome(UMAGATTOperationOutcome::SUCCESS); | 1469 RecordStartNotificationsOutcome(UMAGATTOperationOutcome::SUCCESS); |
1550 | 1470 |
1551 // Copy Characteristic Instance ID before passing scoped pointer because | 1471 // Copy Characteristic Instance ID before passing scoped pointer because |
1552 // compilers may evaluate arguments in any order. | 1472 // compilers may evaluate arguments in any order. |
1553 const std::string characteristic_instance_id = | 1473 const std::string characteristic_instance_id = |
1554 notify_session->GetCharacteristicIdentifier(); | 1474 notify_session->GetCharacteristicIdentifier(); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1683 | 1603 |
1684 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( | 1604 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( |
1685 int frame_routing_id, | 1605 int frame_routing_id, |
1686 const std::string& characteristic_instance_id) { | 1606 const std::string& characteristic_instance_id) { |
1687 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), | 1607 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), |
1688 characteristic_instance_id) | 1608 characteristic_instance_id) |
1689 .outcome != CacheQueryOutcome::BAD_RENDERER; | 1609 .outcome != CacheQueryOutcome::BAD_RENDERER; |
1690 } | 1610 } |
1691 | 1611 |
1692 } // namespace content | 1612 } // namespace content |
OLD | NEW |