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 // NETWORK_ERROR Note: | 5 // NETWORK_ERROR Note: |
6 // When a device can't be found in the BluetoothAdapter, that generally | 6 // When a device can't be found in the BluetoothAdapter, that generally |
7 // indicates that it's gone out of range. We reject with a NetworkError in that | 7 // indicates that it's gone out of range. We reject with a NetworkError in that |
8 // case. | 8 // case. |
9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne
ctgatt | 9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne
ctgatt |
10 | 10 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 MAX_ERROR, | 45 MAX_ERROR, |
46 }; | 46 }; |
47 | 47 |
48 enum class UMARequestDeviceOutcome { | 48 enum class UMARequestDeviceOutcome { |
49 SUCCESS = 0, | 49 SUCCESS = 0, |
50 NO_BLUETOOTH_ADAPTER = 1, | 50 NO_BLUETOOTH_ADAPTER = 1, |
51 NO_RENDER_FRAME = 2, | 51 NO_RENDER_FRAME = 2, |
52 DISCOVERY_START_FAILED = 3, | 52 DISCOVERY_START_FAILED = 3, |
53 DISCOVERY_STOP_FAILED = 4, | 53 DISCOVERY_STOP_FAILED = 4, |
54 NO_MATCHING_DEVICES_FOUND = 5, | 54 NO_MATCHING_DEVICES_FOUND = 5, |
| 55 BLUETOOTH_ADAPTER_OFF = 6, |
55 // NOTE: Add new requestDevice() outcomes immediately above this line. Make | 56 // NOTE: Add new requestDevice() outcomes immediately above this line. Make |
56 // sure to update the enum list in | 57 // sure to update the enum list in |
57 // tools/metrics/histogram/histograms.xml accordingly. | 58 // tools/metrics/histogram/histograms.xml accordingly. |
58 COUNT | 59 COUNT |
59 }; | 60 }; |
60 | 61 |
| 62 enum class UMAGATTServices { |
| 63 UNKNOWN, |
| 64 ALERT_NOTIFICATION, |
| 65 AUTOMATION_IO, |
| 66 BATTERY_SERVICE, |
| 67 BLOOD_PRESSURE, |
| 68 BODY_COMPOSITION, |
| 69 BOND_MANAGEMENT, |
| 70 CONTINUOUS_GLUCOSE_MONITORING, |
| 71 CURRENT_TIME, |
| 72 CYCLING_POWER, |
| 73 CYCLING_SPEED_AND_CADENCE, |
| 74 DEVICE_INFORMATION, |
| 75 ENVIRONMENTAL_SENSING, |
| 76 GENERIC_ACCESS, |
| 77 GENERIC_ATTRIBUTE, |
| 78 GLUCOSE, |
| 79 HEALTH_THERMOMETER, |
| 80 HEART_RATE, |
| 81 HUMAN_INTERFACE_DEVICE, |
| 82 IMMEDIATE_ALERT, |
| 83 INDOOR_POSITIONING, |
| 84 INTERNET_PROTOCOL_SUPPORT, |
| 85 LINK_LOSS, |
| 86 LOCATION_AND_NAVIGATION, |
| 87 NEXT_DST_CHANGE, |
| 88 PHONE_ALERT_STATUS, |
| 89 PULSE_OXIMETER, |
| 90 REFERENCE_TIME_UPDATE, |
| 91 RUNNING_SPEED_AND_CADENCE, |
| 92 SCAN_PARAMETERS, |
| 93 TX_POWER, |
| 94 USER_DATA, |
| 95 WEIGHT_SCALE, |
| 96 // NOTE: Add new services immediately above this line. Make sure to update the |
| 97 // enum list in tools/metrics/histogram/histograms.xml accordingly. |
| 98 COUNT |
| 99 }; |
| 100 |
| 101 typedef std::map<BluetoothUUID, UMAGATTServices> BluetoothUUIDToServicesMap; |
| 102 |
| 103 std::map<BluetoothUUID, UMAGATTServices>* getServiceToEnumMap() { |
| 104 CR_DEFINE_STATIC_LOCAL(BluetoothUUIDToServicesMap, services, ()); |
| 105 if (services.empty()) { |
| 106 services.insert(std::make_pair(BluetoothUUID("1811"), |
| 107 UMAGATTServices::ALERT_NOTIFICATION)); |
| 108 services.insert(std::make_pair(BluetoothUUID("180F"), |
| 109 UMAGATTServices::BATTERY_SERVICE)); |
| 110 services.insert( |
| 111 std::make_pair(BluetoothUUID("1810"), UMAGATTServices::BLOOD_PRESSURE)); |
| 112 services.insert(std::make_pair(BluetoothUUID("181B"), |
| 113 UMAGATTServices::BODY_COMPOSITION)); |
| 114 services.insert(std::make_pair(BluetoothUUID("181E"), |
| 115 UMAGATTServices::BOND_MANAGEMENT)); |
| 116 services.insert(std::make_pair( |
| 117 BluetoothUUID("181F"), UMAGATTServices::CONTINUOUS_GLUCOSE_MONITORING)); |
| 118 services.insert( |
| 119 std::make_pair(BluetoothUUID("1805"), UMAGATTServices::CURRENT_TIME)); |
| 120 services.insert( |
| 121 std::make_pair(BluetoothUUID("1818"), UMAGATTServices::CYCLING_POWER)); |
| 122 services.insert(std::make_pair(BluetoothUUID("1816"), |
| 123 UMAGATTServices::CYCLING_SPEED_AND_CADENCE)); |
| 124 services.insert(std::make_pair(BluetoothUUID("180A"), |
| 125 UMAGATTServices::DEVICE_INFORMATION)); |
| 126 services.insert(std::make_pair(BluetoothUUID("181A"), |
| 127 UMAGATTServices::ENVIRONMENTAL_SENSING)); |
| 128 services.insert( |
| 129 std::make_pair(BluetoothUUID("1800"), UMAGATTServices::GENERIC_ACCESS)); |
| 130 services.insert(std::make_pair(BluetoothUUID("1801"), |
| 131 UMAGATTServices::GENERIC_ATTRIBUTE)); |
| 132 services.insert( |
| 133 std::make_pair(BluetoothUUID("1808"), UMAGATTServices::GLUCOSE)); |
| 134 services.insert(std::make_pair(BluetoothUUID("1809"), |
| 135 UMAGATTServices::HEALTH_THERMOMETER)); |
| 136 services.insert( |
| 137 std::make_pair(BluetoothUUID("180D"), UMAGATTServices::HEART_RATE)); |
| 138 services.insert(std::make_pair(BluetoothUUID("1812"), |
| 139 UMAGATTServices::HUMAN_INTERFACE_DEVICE)); |
| 140 services.insert(std::make_pair(BluetoothUUID("1802"), |
| 141 UMAGATTServices::IMMEDIATE_ALERT)); |
| 142 services.insert(std::make_pair(BluetoothUUID("1821"), |
| 143 UMAGATTServices::INDOOR_POSITIONING)); |
| 144 services.insert(std::make_pair(BluetoothUUID("1820"), |
| 145 UMAGATTServices::INTERNET_PROTOCOL_SUPPORT)); |
| 146 services.insert( |
| 147 std::make_pair(BluetoothUUID("1803"), UMAGATTServices::LINK_LOSS)); |
| 148 services.insert(std::make_pair(BluetoothUUID("1819"), |
| 149 UMAGATTServices::LOCATION_AND_NAVIGATION)); |
| 150 services.insert(std::make_pair(BluetoothUUID("1807"), |
| 151 UMAGATTServices::NEXT_DST_CHANGE)); |
| 152 services.insert(std::make_pair(BluetoothUUID("180E"), |
| 153 UMAGATTServices::PHONE_ALERT_STATUS)); |
| 154 services.insert(std::make_pair(BluetoothUUID("1806"), |
| 155 UMAGATTServices::REFERENCE_TIME_UPDATE)); |
| 156 services.insert(std::make_pair(BluetoothUUID("1814"), |
| 157 UMAGATTServices::RUNNING_SPEED_AND_CADENCE)); |
| 158 services.insert(std::make_pair(BluetoothUUID("1813"), |
| 159 UMAGATTServices::SCAN_PARAMETERS)); |
| 160 services.insert( |
| 161 std::make_pair(BluetoothUUID("1804"), UMAGATTServices::TX_POWER)); |
| 162 services.insert( |
| 163 std::make_pair(BluetoothUUID("181C"), UMAGATTServices::USER_DATA)); |
| 164 services.insert( |
| 165 std::make_pair(BluetoothUUID("181D"), UMAGATTServices::WEIGHT_SCALE)); |
| 166 } |
| 167 return &services; |
| 168 } |
| 169 |
| 170 int GetServiceBucket(const BluetoothUUID& service) { |
| 171 std::map<BluetoothUUID, UMAGATTServices>* services = getServiceToEnumMap(); |
| 172 |
| 173 auto it = services->find(service); |
| 174 if (it == services->end()) |
| 175 return static_cast<int>(UMAGATTServices::UNKNOWN); |
| 176 return static_cast<int>(it->second); |
| 177 } |
| 178 |
61 void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) { | 179 void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) { |
62 UMA_HISTOGRAM_ENUMERATION("Bluetooth.RequestDevice.Outcome", | 180 UMA_HISTOGRAM_ENUMERATION("WebBluetooth.RequestDevice.Outcome", |
63 static_cast<int>(outcome), | 181 static_cast<int>(outcome), |
64 static_cast<int>(UMARequestDeviceOutcome::COUNT)); | 182 static_cast<int>(UMARequestDeviceOutcome::COUNT)); |
65 } | 183 } |
66 | 184 |
| 185 void RecordRequestDeviceFilters( |
| 186 const std::vector<content::BluetoothScanFilter>& filters) { |
| 187 UMA_HISTOGRAM_COUNTS("WebBluetooth.RequestDevice.Filters.Count", |
| 188 filters.size()); |
| 189 for (const content::BluetoothScanFilter& filter : filters) { |
| 190 for (const BluetoothUUID& service : filter.services) { |
| 191 UMA_HISTOGRAM_ENUMERATION("WebBluetooth.RequestDevice.Filters.Services", |
| 192 GetServiceBucket(service), |
| 193 static_cast<int>(UMAGATTServices::COUNT)); |
| 194 } |
| 195 } |
| 196 } |
| 197 |
| 198 void RecordRequestDeviceOptionalServices( |
| 199 const std::vector<BluetoothUUID>& optional_services) { |
| 200 UMA_HISTOGRAM_COUNTS("WebBluetooth.RequestDevice.OptionalServices.Count", |
| 201 optional_services.size()); |
| 202 for (const BluetoothUUID& service : optional_services) { |
| 203 UMA_HISTOGRAM_ENUMERATION( |
| 204 "WebBluetooth.RequestDevice.OptionalServices.Services", |
| 205 static_cast<int>(GetServiceBucket(service)), |
| 206 static_cast<int>(UMAGATTServices::COUNT)); |
| 207 } |
| 208 } |
| 209 |
67 // TODO(ortuno): Once we have a chooser for scanning and the right | 210 // TODO(ortuno): Once we have a chooser for scanning and the right |
68 // callback for discovered services we should delete these constants. | 211 // callback for discovered services we should delete these constants. |
69 // https://crbug.com/436280 and https://crbug.com/484504 | 212 // https://crbug.com/436280 and https://crbug.com/484504 |
70 const int kDelayTime = 5; // 5 seconds for scanning and discovering | 213 const int kDelayTime = 5; // 5 seconds for scanning and discovering |
71 const int kTestingDelayTime = 0; // No need to wait during tests | 214 const int kTestingDelayTime = 0; // No need to wait during tests |
72 | 215 |
73 // Defined at | 216 // Defined at |
74 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter | 217 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter |
75 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, | 218 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
76 const content::BluetoothScanFilter& filter) { | 219 const content::BluetoothScanFilter& filter) { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 } | 390 } |
248 | 391 |
249 void BluetoothDispatcherHost::OnRequestDevice( | 392 void BluetoothDispatcherHost::OnRequestDevice( |
250 int thread_id, | 393 int thread_id, |
251 int request_id, | 394 int request_id, |
252 int frame_routing_id, | 395 int frame_routing_id, |
253 const std::vector<BluetoothScanFilter>& filters, | 396 const std::vector<BluetoothScanFilter>& filters, |
254 const std::vector<BluetoothUUID>& optional_services) { | 397 const std::vector<BluetoothUUID>& optional_services) { |
255 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 398 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
256 RecordAction(UserMetricsAction("WebBluetooth_RequestDevice")); | 399 RecordAction(UserMetricsAction("WebBluetooth_RequestDevice")); |
| 400 RecordRequestDeviceFilters(filters); |
| 401 RecordRequestDeviceOptionalServices(optional_services); |
| 402 |
| 403 VLOG(1) << "requestDevice called with the following filters: "; |
| 404 for (const BluetoothScanFilter& filter : filters) { |
| 405 VLOG(1) << "["; |
| 406 for (const BluetoothUUID& service : filter.services) |
| 407 VLOG(1) << service.value(); |
| 408 VLOG(1) << "]"; |
| 409 } |
| 410 |
| 411 VLOG(1) << "requestDevice called with the following optional services: "; |
| 412 for (const BluetoothUUID& service : optional_services) |
| 413 VLOG(1) << service.value(); |
257 | 414 |
258 RenderFrameHostImpl* render_frame_host = | 415 RenderFrameHostImpl* render_frame_host = |
259 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | 416 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); |
260 | 417 |
261 if (!render_frame_host) { | 418 if (!render_frame_host) { |
262 DLOG(WARNING) | 419 VLOG(1) << "Got a requestDevice IPC without a matching RenderFrameHost: " |
263 << "Got a requestDevice IPC without a matching RenderFrameHost: " | 420 << render_process_id_ << ", " << frame_routing_id; |
264 << render_process_id_ << ", " << frame_routing_id; | |
265 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME); | 421 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME); |
266 Send(new BluetoothMsg_RequestDeviceError( | 422 Send(new BluetoothMsg_RequestDeviceError( |
267 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame)); | 423 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame)); |
268 } | 424 } |
269 | 425 |
270 // TODO(scheib): Device selection UI: crbug.com/436280 | 426 // TODO(scheib): Device selection UI: crbug.com/436280 |
271 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 427 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
272 if (adapter_.get()) { | 428 if (adapter_.get()) { |
273 if (!request_device_sessions_ | 429 if (!request_device_sessions_ |
274 .insert(std::make_pair( | 430 .insert(std::make_pair( |
275 std::make_pair(thread_id, request_id), | 431 std::make_pair(thread_id, request_id), |
276 RequestDeviceSession(filters, optional_services))) | 432 RequestDeviceSession(filters, optional_services))) |
277 .second) { | 433 .second) { |
278 LOG(ERROR) << "2 requestDevice() calls with the same thread_id (" | 434 LOG(ERROR) << "2 requestDevice() calls with the same thread_id (" |
279 << thread_id << ") and request_id (" << request_id | 435 << thread_id << ") and request_id (" << request_id |
280 << ") shouldn't arrive at the same BluetoothDispatcherHost."; | 436 << ") shouldn't arrive at the same BluetoothDispatcherHost."; |
281 bad_message::ReceivedBadMessage( | 437 bad_message::ReceivedBadMessage( |
282 this, bad_message::BDH_DUPLICATE_REQUEST_DEVICE_ID); | 438 this, bad_message::BDH_DUPLICATE_REQUEST_DEVICE_ID); |
283 } | 439 } |
| 440 |
| 441 if (!adapter_->IsPresent()) { |
| 442 VLOG(1) << "BluetoothAdapter not present. Can't serve requestDevice."; |
| 443 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); |
| 444 Send(new BluetoothMsg_RequestDeviceError( |
| 445 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); |
| 446 return; |
| 447 } |
| 448 if (!adapter_->IsPowered()) { |
| 449 VLOG(1) << "BluetoothAdapter is not powered. Can't serve requestDevice."; |
| 450 RecordRequestDeviceOutcome( |
| 451 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_OFF); |
| 452 Send(new BluetoothMsg_RequestDeviceError( |
| 453 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff)); |
| 454 return; |
| 455 } |
284 adapter_->StartDiscoverySessionWithFilter( | 456 adapter_->StartDiscoverySessionWithFilter( |
285 ComputeScanFilter(filters), | 457 ComputeScanFilter(filters), |
286 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 458 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
287 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 459 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
288 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 460 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
289 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 461 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
290 } else { | 462 } else { |
291 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 463 VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice."; |
292 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); | 464 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); |
293 Send(new BluetoothMsg_RequestDeviceError( | 465 Send(new BluetoothMsg_RequestDeviceError( |
294 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); | 466 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); |
295 } | 467 } |
296 return; | 468 return; |
297 } | 469 } |
298 | 470 |
299 void BluetoothDispatcherHost::OnConnectGATT( | 471 void BluetoothDispatcherHost::OnConnectGATT( |
300 int thread_id, | 472 int thread_id, |
301 int request_id, | 473 int request_id, |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 device->IsPaired(), // paired | 754 device->IsPaired(), // paired |
583 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 755 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
584 device->GetUUIDs())); // uuids | 756 device->GetUUIDs())); // uuids |
585 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); | 757 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); |
586 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 758 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
587 device_ipc)); | 759 device_ipc)); |
588 request_device_sessions_.erase(session); | 760 request_device_sessions_.erase(session); |
589 return; | 761 return; |
590 } | 762 } |
591 } | 763 } |
| 764 VLOG(1) << "No matching Bluetooth Devices found"; |
592 RecordRequestDeviceOutcome( | 765 RecordRequestDeviceOutcome( |
593 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); | 766 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); |
594 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 767 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
595 WebBluetoothError::NoDevicesFound)); | 768 WebBluetoothError::NoDevicesFound)); |
596 request_device_sessions_.erase(session); | 769 request_device_sessions_.erase(session); |
597 } | 770 } |
598 | 771 |
599 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 772 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
600 int request_id) { | 773 int request_id) { |
601 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 774 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 | 859 |
687 void BluetoothDispatcherHost::OnWriteValueFailed( | 860 void BluetoothDispatcherHost::OnWriteValueFailed( |
688 int thread_id, | 861 int thread_id, |
689 int request_id, | 862 int request_id, |
690 device::BluetoothGattService::GattErrorCode error_code) { | 863 device::BluetoothGattService::GattErrorCode error_code) { |
691 Send(new BluetoothMsg_WriteCharacteristicValueError( | 864 Send(new BluetoothMsg_WriteCharacteristicValueError( |
692 thread_id, request_id, TranslateGATTError(error_code))); | 865 thread_id, request_id, TranslateGATTError(error_code))); |
693 } | 866 } |
694 | 867 |
695 } // namespace content | 868 } // namespace content |
OLD | NEW |