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. |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 scoped_ptr<BluetoothChooser> chooser; | 346 scoped_ptr<BluetoothChooser> chooser; |
347 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 347 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; |
348 }; | 348 }; |
349 | 349 |
350 struct BluetoothDispatcherHost::CacheQueryResult { | 350 struct BluetoothDispatcherHost::CacheQueryResult { |
351 CacheQueryResult() | 351 CacheQueryResult() |
352 : device(nullptr), | 352 : device(nullptr), |
353 service(nullptr), | 353 service(nullptr), |
354 characteristic(nullptr), | 354 characteristic(nullptr), |
355 outcome(CacheQueryOutcome::SUCCESS) {} | 355 outcome(CacheQueryOutcome::SUCCESS) {} |
| 356 CacheQueryResult(CacheQueryOutcome outcome) |
| 357 : device(nullptr), |
| 358 service(nullptr), |
| 359 characteristic(nullptr), |
| 360 outcome(outcome) {} |
356 ~CacheQueryResult() {} | 361 ~CacheQueryResult() {} |
357 WebBluetoothError GetWebError() { | 362 WebBluetoothError GetWebError() const { |
358 switch (outcome) { | 363 switch (outcome) { |
359 case CacheQueryOutcome::SUCCESS: | 364 case CacheQueryOutcome::SUCCESS: |
360 case CacheQueryOutcome::BAD_RENDERER: | 365 case CacheQueryOutcome::BAD_RENDERER: |
361 NOTREACHED(); | 366 NOTREACHED(); |
362 return WebBluetoothError::DeviceNoLongerInRange; | 367 return WebBluetoothError::DeviceNoLongerInRange; |
363 case CacheQueryOutcome::NO_DEVICE: | 368 case CacheQueryOutcome::NO_DEVICE: |
364 return WebBluetoothError::DeviceNoLongerInRange; | 369 return WebBluetoothError::DeviceNoLongerInRange; |
365 case CacheQueryOutcome::NO_SERVICE: | 370 case CacheQueryOutcome::NO_SERVICE: |
366 return WebBluetoothError::ServiceNoLongerExists; | 371 return WebBluetoothError::ServiceNoLongerExists; |
367 case CacheQueryOutcome::NO_CHARACTERISTIC: | 372 case CacheQueryOutcome::NO_CHARACTERISTIC: |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 const std::string& device_id) { | 688 const std::string& device_id) { |
684 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 689 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
685 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 690 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); |
686 const base::TimeTicks start_time = base::TimeTicks::Now(); | 691 const base::TimeTicks start_time = base::TimeTicks::Now(); |
687 | 692 |
688 // TODO(ortuno): Right now it's pointless to check if the domain has access to | 693 // TODO(ortuno): Right now it's pointless to check if the domain has access to |
689 // the device, because any domain can connect to any device. But once | 694 // the device, because any domain can connect to any device. But once |
690 // permissions are implemented we should check that the domain has access to | 695 // permissions are implemented we should check that the domain has access to |
691 // the device. https://crbug.com/484745 | 696 // the device. https://crbug.com/484745 |
692 | 697 |
693 CacheQueryResult query_result; | 698 const CacheQueryResult query_result = QueryCacheForDevice(device_id); |
694 QueryCacheForDevice(device_id, query_result); | |
695 | 699 |
696 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 700 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
697 RecordConnectGATTOutcome(query_result.outcome); | 701 RecordConnectGATTOutcome(query_result.outcome); |
698 Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id, | 702 Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id, |
699 query_result.GetWebError())); | 703 query_result.GetWebError())); |
700 return; | 704 return; |
701 } | 705 } |
702 | 706 |
703 query_result.device->CreateGattConnection( | 707 query_result.device->CreateGattConnection( |
704 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 708 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
(...skipping 11 matching lines...) Expand all Loading... |
716 const std::string& service_uuid) { | 720 const std::string& service_uuid) { |
717 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 721 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
718 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE); | 722 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE); |
719 RecordGetPrimaryServiceService(BluetoothUUID(service_uuid)); | 723 RecordGetPrimaryServiceService(BluetoothUUID(service_uuid)); |
720 | 724 |
721 // TODO(ortuno): Check if device_id is in "allowed devices" | 725 // TODO(ortuno): Check if device_id is in "allowed devices" |
722 // https://crbug.com/493459 | 726 // https://crbug.com/493459 |
723 // TODO(ortuno): Check if service_uuid is in "allowed services" | 727 // TODO(ortuno): Check if service_uuid is in "allowed services" |
724 // https://crbug.com/493460 | 728 // https://crbug.com/493460 |
725 | 729 |
726 CacheQueryResult query_result; | 730 const CacheQueryResult query_result = QueryCacheForDevice(device_id); |
727 QueryCacheForDevice(device_id, query_result); | |
728 | 731 |
729 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 732 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
730 RecordGetPrimaryServiceOutcome(query_result.outcome); | 733 RecordGetPrimaryServiceOutcome(query_result.outcome); |
731 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | 734 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, |
732 query_result.GetWebError())); | 735 query_result.GetWebError())); |
733 return; | 736 return; |
734 } | 737 } |
735 | 738 |
736 // There are four possibilities here: | 739 // There are four possibilities here: |
737 // 1. Services not discovered and service present in |device|: Send back the | 740 // 1. Services not discovered and service present in |device|: Send back the |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 | 776 |
774 void BluetoothDispatcherHost::OnGetCharacteristic( | 777 void BluetoothDispatcherHost::OnGetCharacteristic( |
775 int thread_id, | 778 int thread_id, |
776 int request_id, | 779 int request_id, |
777 const std::string& service_instance_id, | 780 const std::string& service_instance_id, |
778 const std::string& characteristic_uuid) { | 781 const std::string& characteristic_uuid) { |
779 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 782 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
780 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 783 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); |
781 RecordGetCharacteristicCharacteristic(characteristic_uuid); | 784 RecordGetCharacteristicCharacteristic(characteristic_uuid); |
782 | 785 |
783 CacheQueryResult query_result; | 786 const CacheQueryResult query_result = |
784 QueryCacheForService(service_instance_id, query_result); | 787 QueryCacheForService(service_instance_id); |
785 | 788 |
786 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 789 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
787 return; | 790 return; |
788 } | 791 } |
789 | 792 |
790 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 793 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
791 RecordGetCharacteristicOutcome(query_result.outcome); | 794 RecordGetCharacteristicOutcome(query_result.outcome); |
792 Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id, | 795 Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id, |
793 query_result.GetWebError())); | 796 query_result.GetWebError())); |
794 return; | 797 return; |
(...skipping 27 matching lines...) Expand all Loading... |
822 } | 825 } |
823 | 826 |
824 void BluetoothDispatcherHost::OnReadValue( | 827 void BluetoothDispatcherHost::OnReadValue( |
825 int thread_id, | 828 int thread_id, |
826 int request_id, | 829 int request_id, |
827 const std::string& characteristic_instance_id) { | 830 const std::string& characteristic_instance_id) { |
828 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 831 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
829 RecordWebBluetoothFunctionCall( | 832 RecordWebBluetoothFunctionCall( |
830 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 833 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); |
831 | 834 |
832 CacheQueryResult query_result; | 835 const CacheQueryResult query_result = |
833 QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 836 QueryCacheForCharacteristic(characteristic_instance_id); |
834 | 837 |
835 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 838 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
836 return; | 839 return; |
837 } | 840 } |
838 | 841 |
839 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 842 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
840 RecordCharacteristicReadValueOutcome(query_result.outcome); | 843 RecordCharacteristicReadValueOutcome(query_result.outcome); |
841 Send(new BluetoothMsg_ReadCharacteristicValueError( | 844 Send(new BluetoothMsg_ReadCharacteristicValueError( |
842 thread_id, request_id, query_result.GetWebError())); | 845 thread_id, request_id, query_result.GetWebError())); |
843 return; | 846 return; |
(...skipping 19 matching lines...) Expand all Loading... |
863 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
teristic-writevalue | 866 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
teristic-writevalue |
864 // We perform the length check on the renderer side. So if we | 867 // We perform the length check on the renderer side. So if we |
865 // get a value with length > 512, we can assume it's a hostile | 868 // get a value with length > 512, we can assume it's a hostile |
866 // renderer and kill it. | 869 // renderer and kill it. |
867 if (value.size() > 512) { | 870 if (value.size() > 512) { |
868 bad_message::ReceivedBadMessage( | 871 bad_message::ReceivedBadMessage( |
869 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 872 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); |
870 return; | 873 return; |
871 } | 874 } |
872 | 875 |
873 CacheQueryResult query_result; | 876 const CacheQueryResult query_result = |
874 QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 877 QueryCacheForCharacteristic(characteristic_instance_id); |
875 | 878 |
876 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 879 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
877 return; | 880 return; |
878 } | 881 } |
879 | 882 |
880 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 883 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
881 RecordCharacteristicWriteValueOutcome(query_result.outcome); | 884 RecordCharacteristicWriteValueOutcome(query_result.outcome); |
882 Send(new BluetoothMsg_WriteCharacteristicValueError( | 885 Send(new BluetoothMsg_WriteCharacteristicValueError( |
883 thread_id, request_id, query_result.GetWebError())); | 886 thread_id, request_id, query_result.GetWebError())); |
884 return; | 887 return; |
(...skipping 19 matching lines...) Expand all Loading... |
904 if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != | 907 if (characteristic_id_to_notify_session_.find(characteristic_instance_id) != |
905 characteristic_id_to_notify_session_.end()) { | 908 characteristic_id_to_notify_session_.end()) { |
906 bad_message::ReceivedBadMessage( | 909 bad_message::ReceivedBadMessage( |
907 this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); | 910 this, bad_message::BDH_CHARACTERISTIC_ALREADY_SUBSCRIBED); |
908 return; | 911 return; |
909 } | 912 } |
910 | 913 |
911 // TODO(ortuno): Check if notify/indicate bit is set. | 914 // TODO(ortuno): Check if notify/indicate bit is set. |
912 // http://crbug.com/538869 | 915 // http://crbug.com/538869 |
913 | 916 |
914 CacheQueryResult query_result; | 917 const CacheQueryResult query_result = |
915 QueryCacheForCharacteristic(characteristic_instance_id, query_result); | 918 QueryCacheForCharacteristic(characteristic_instance_id); |
916 | 919 |
917 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { | 920 if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
918 return; | 921 return; |
919 } | 922 } |
920 | 923 |
921 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 924 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
922 RecordStartNotificationsOutcome(query_result.outcome); | 925 RecordStartNotificationsOutcome(query_result.outcome); |
923 Send(new BluetoothMsg_StartNotificationsError(thread_id, request_id, | 926 Send(new BluetoothMsg_StartNotificationsError(thread_id, request_id, |
924 query_result.GetWebError())); | 927 query_result.GetWebError())); |
925 return; | 928 return; |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 } | 1239 } |
1237 | 1240 |
1238 void BluetoothDispatcherHost::OnStopNotifySession( | 1241 void BluetoothDispatcherHost::OnStopNotifySession( |
1239 int thread_id, | 1242 int thread_id, |
1240 int request_id, | 1243 int request_id, |
1241 const std::string& characteristic_instance_id) { | 1244 const std::string& characteristic_instance_id) { |
1242 characteristic_id_to_notify_session_.erase(characteristic_instance_id); | 1245 characteristic_id_to_notify_session_.erase(characteristic_instance_id); |
1243 Send(new BluetoothMsg_StopNotificationsSuccess(thread_id, request_id)); | 1246 Send(new BluetoothMsg_StopNotificationsSuccess(thread_id, request_id)); |
1244 } | 1247 } |
1245 | 1248 |
1246 void BluetoothDispatcherHost::QueryCacheForDevice(const std::string& device_id, | 1249 BluetoothDispatcherHost::CacheQueryResult |
1247 CacheQueryResult& result) { | 1250 BluetoothDispatcherHost::QueryCacheForDevice(const std::string& device_id) { |
| 1251 CacheQueryResult result; |
1248 result.device = adapter_->GetDevice(device_id); | 1252 result.device = adapter_->GetDevice(device_id); |
1249 // When a device can't be found in the BluetoothAdapter, that generally | 1253 // When a device can't be found in the BluetoothAdapter, that generally |
1250 // indicates that it's gone out of range. We reject with a NetworkError in | 1254 // indicates that it's gone out of range. We reject with a NetworkError in |
1251 // that case. | 1255 // that case. |
1252 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-con
nectgatt | 1256 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-con
nectgatt |
1253 if (result.device == nullptr) { | 1257 if (result.device == nullptr) { |
1254 result.outcome = CacheQueryOutcome::NO_DEVICE; | 1258 result.outcome = CacheQueryOutcome::NO_DEVICE; |
1255 } | 1259 } |
| 1260 return result; |
1256 } | 1261 } |
1257 | 1262 |
1258 void BluetoothDispatcherHost::QueryCacheForService( | 1263 BluetoothDispatcherHost::CacheQueryResult |
1259 const std::string& service_instance_id, | 1264 BluetoothDispatcherHost::QueryCacheForService( |
1260 CacheQueryResult& result) { | 1265 const std::string& service_instance_id) { |
1261 auto device_iter = service_to_device_.find(service_instance_id); | 1266 auto device_iter = service_to_device_.find(service_instance_id); |
1262 | 1267 |
1263 // Kill the renderer, see "ID Not In Map Note" above. | 1268 // Kill the renderer, see "ID Not In Map Note" above. |
1264 if (device_iter == service_to_device_.end()) { | 1269 if (device_iter == service_to_device_.end()) { |
1265 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | 1270 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); |
1266 result.outcome = CacheQueryOutcome::BAD_RENDERER; | 1271 return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
1267 return; | |
1268 } | 1272 } |
1269 | 1273 |
1270 // TODO(ortuno): Check if domain has access to device. | 1274 // TODO(ortuno): Check if domain has access to device. |
1271 // https://crbug.com/493459 | 1275 // https://crbug.com/493459 |
1272 | 1276 |
1273 QueryCacheForDevice(device_iter->second, result); | 1277 CacheQueryResult result = QueryCacheForDevice(device_iter->second); |
1274 | 1278 |
1275 if (result.outcome != CacheQueryOutcome::SUCCESS) { | 1279 if (result.outcome != CacheQueryOutcome::SUCCESS) { |
1276 return; | 1280 return result; |
1277 } | 1281 } |
1278 | 1282 |
1279 result.service = result.device->GetGattService(service_instance_id); | 1283 result.service = result.device->GetGattService(service_instance_id); |
1280 if (result.service == nullptr) { | 1284 if (result.service == nullptr) { |
1281 result.outcome = CacheQueryOutcome::NO_SERVICE; | 1285 result.outcome = CacheQueryOutcome::NO_SERVICE; |
1282 } | 1286 } |
| 1287 return result; |
1283 } | 1288 } |
1284 | 1289 |
1285 void BluetoothDispatcherHost::QueryCacheForCharacteristic( | 1290 BluetoothDispatcherHost::CacheQueryResult |
1286 const std::string& characteristic_instance_id, | 1291 BluetoothDispatcherHost::QueryCacheForCharacteristic( |
1287 CacheQueryResult& result) { | 1292 const std::string& characteristic_instance_id) { |
1288 auto characteristic_iter = | 1293 auto characteristic_iter = |
1289 characteristic_to_service_.find(characteristic_instance_id); | 1294 characteristic_to_service_.find(characteristic_instance_id); |
1290 | 1295 |
1291 // Kill the renderer, see "ID Not In Map Note" above. | 1296 // Kill the renderer, see "ID Not In Map Note" above. |
1292 if (characteristic_iter == characteristic_to_service_.end()) { | 1297 if (characteristic_iter == characteristic_to_service_.end()) { |
1293 bad_message::ReceivedBadMessage(this, | 1298 bad_message::ReceivedBadMessage(this, |
1294 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | 1299 bad_message::BDH_INVALID_CHARACTERISTIC_ID); |
1295 result.outcome = CacheQueryOutcome::BAD_RENDERER; | 1300 return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
1296 return; | |
1297 } | 1301 } |
1298 | 1302 |
1299 QueryCacheForService(characteristic_iter->second, result); | 1303 CacheQueryResult result = QueryCacheForService(characteristic_iter->second); |
1300 if (result.outcome != CacheQueryOutcome::SUCCESS) { | 1304 if (result.outcome != CacheQueryOutcome::SUCCESS) { |
1301 return; | 1305 return result; |
1302 } | 1306 } |
1303 | 1307 |
1304 result.characteristic = | 1308 result.characteristic = |
1305 result.service->GetCharacteristic(characteristic_instance_id); | 1309 result.service->GetCharacteristic(characteristic_instance_id); |
1306 | 1310 |
1307 if (result.characteristic == nullptr) { | 1311 if (result.characteristic == nullptr) { |
1308 result.outcome = CacheQueryOutcome::NO_CHARACTERISTIC; | 1312 result.outcome = CacheQueryOutcome::NO_CHARACTERISTIC; |
1309 } | 1313 } |
| 1314 |
| 1315 return result; |
1310 } | 1316 } |
1311 | 1317 |
1312 bool BluetoothDispatcherHost::IsServicesDiscoveryCompleteForDevice( | 1318 bool BluetoothDispatcherHost::IsServicesDiscoveryCompleteForDevice( |
1313 const std::string& device_id) { | 1319 const std::string& device_id) { |
1314 return ContainsKey(devices_with_discovered_services_, device_id); | 1320 return ContainsKey(devices_with_discovered_services_, device_id); |
1315 } | 1321 } |
1316 | 1322 |
1317 void BluetoothDispatcherHost::AddToPendingPrimaryServicesRequest( | 1323 void BluetoothDispatcherHost::AddToPendingPrimaryServicesRequest( |
1318 const std::string& device_id, | 1324 const std::string& device_id, |
1319 const PrimaryServicesRequest& request) { | 1325 const PrimaryServicesRequest& request) { |
(...skipping 14 matching lines...) Expand all Loading... |
1334 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1340 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1335 NOTIMPLEMENTED(); | 1341 NOTIMPLEMENTED(); |
1336 } | 1342 } |
1337 | 1343 |
1338 void BluetoothDispatcherHost::ShowNeedLocationLink() { | 1344 void BluetoothDispatcherHost::ShowNeedLocationLink() { |
1339 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1345 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1340 NOTIMPLEMENTED(); | 1346 NOTIMPLEMENTED(); |
1341 } | 1347 } |
1342 | 1348 |
1343 } // namespace content | 1349 } // namespace content |
OLD | NEW |