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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 NO_MATCHING_DEVICES_FOUND = 5, | 51 NO_MATCHING_DEVICES_FOUND = 5, |
52 BLUETOOTH_ADAPTER_NOT_PRESENT = 6, | 52 BLUETOOTH_ADAPTER_NOT_PRESENT = 6, |
53 BLUETOOTH_ADAPTER_OFF = 7, | 53 BLUETOOTH_ADAPTER_OFF = 7, |
54 // NOTE: Add new requestDevice() outcomes immediately above this line. Make | 54 // NOTE: Add new requestDevice() outcomes immediately above this line. Make |
55 // sure to update the enum list in | 55 // sure to update the enum list in |
56 // tools/metrics/histogram/histograms.xml accordingly. | 56 // tools/metrics/histogram/histograms.xml accordingly. |
57 COUNT | 57 COUNT |
58 }; | 58 }; |
59 | 59 |
60 void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) { | 60 void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) { |
61 UMA_HISTOGRAM_ENUMERATION("Bluetooth.RequestDevice.Outcome", | 61 UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.RequestDevice.Outcome", |
62 static_cast<int>(outcome), | 62 static_cast<int>(outcome), |
63 static_cast<int>(UMARequestDeviceOutcome::COUNT)); | 63 static_cast<int>(UMARequestDeviceOutcome::COUNT)); |
64 } | 64 } |
65 | 65 |
66 enum class UMAGATTServices { | |
67 UNKNOWN, | |
68 ALERT_NOTIFICATION, | |
69 AUTOMATION_IO, | |
70 BATTERY_SERVICE, | |
71 BLOOD_PRESSURE, | |
72 BODY_COMPOSITION, | |
73 BOND_MANAGEMENT, | |
74 CONTINUOUS_GLUCOSE_MONITORING, | |
75 CURRENT_TIME, | |
76 CYCLING_POWER, | |
77 CYCLING_SPEED_AND_CADENCE, | |
78 DEVICE_INFORMATION, | |
79 ENVIRONMENTAL_SENSING, | |
80 GENERIC_ACCESS, | |
81 GENERIC_ATTRIBUTE, | |
82 GLUCOSE, | |
83 HEALTH_THERMOMETER, | |
84 HEART_RATE, | |
85 HUMAN_INTERFACE_DEVICE, | |
86 IMMEDIATE_ALERT, | |
87 INDOOR_POSITIONING, | |
88 INTERNET_PROTOCOL_SUPPORT, | |
89 LINK_LOSS, | |
90 LOCATION_AND_NAVIGATION, | |
91 NEXT_DST_CHANGE, | |
92 PHONE_ALERT_STATUS, | |
93 PULSE_OXIMETER, | |
94 REFERENCE_TIME_UPDATE, | |
95 RUNNING_SPEED_AND_CADENCE, | |
96 SCAN_PARAMETERS, | |
97 TX_POWER, | |
98 USER_DATA, | |
99 WEIGHT_SCALE, | |
100 // NOTE: Add new services immediately above this line. Make sure to update the | |
101 // enum list in tools/metrics/histogram/histograms.xml accordingly. | |
102 COUNT | |
103 }; | |
104 | |
105 typedef std::map<BluetoothUUID, UMAGATTServices> BluetoothUUIDToServicesMap; | |
106 | |
107 std::map<BluetoothUUID, UMAGATTServices>* getServiceToEnumMap() { | |
Jeffrey Yasskin
2015/08/05 19:03:49
I don't really like having to maintain yet another
ortuno
2015/08/10 20:05:50
Done.
| |
108 CR_DEFINE_STATIC_LOCAL(BluetoothUUIDToServicesMap, services, ()); | |
109 if (services.empty()) { | |
110 services.insert(std::make_pair(BluetoothUUID("1811"), | |
111 UMAGATTServices::ALERT_NOTIFICATION)); | |
112 services.insert(std::make_pair(BluetoothUUID("180F"), | |
113 UMAGATTServices::BATTERY_SERVICE)); | |
114 services.insert( | |
115 std::make_pair(BluetoothUUID("1810"), UMAGATTServices::BLOOD_PRESSURE)); | |
116 services.insert(std::make_pair(BluetoothUUID("181B"), | |
117 UMAGATTServices::BODY_COMPOSITION)); | |
118 services.insert(std::make_pair(BluetoothUUID("181E"), | |
119 UMAGATTServices::BOND_MANAGEMENT)); | |
120 services.insert(std::make_pair( | |
121 BluetoothUUID("181F"), UMAGATTServices::CONTINUOUS_GLUCOSE_MONITORING)); | |
122 services.insert( | |
123 std::make_pair(BluetoothUUID("1805"), UMAGATTServices::CURRENT_TIME)); | |
124 services.insert( | |
125 std::make_pair(BluetoothUUID("1818"), UMAGATTServices::CYCLING_POWER)); | |
126 services.insert(std::make_pair(BluetoothUUID("1816"), | |
127 UMAGATTServices::CYCLING_SPEED_AND_CADENCE)); | |
128 services.insert(std::make_pair(BluetoothUUID("180A"), | |
129 UMAGATTServices::DEVICE_INFORMATION)); | |
130 services.insert(std::make_pair(BluetoothUUID("181A"), | |
131 UMAGATTServices::ENVIRONMENTAL_SENSING)); | |
132 services.insert( | |
133 std::make_pair(BluetoothUUID("1800"), UMAGATTServices::GENERIC_ACCESS)); | |
134 services.insert(std::make_pair(BluetoothUUID("1801"), | |
135 UMAGATTServices::GENERIC_ATTRIBUTE)); | |
136 services.insert( | |
137 std::make_pair(BluetoothUUID("1808"), UMAGATTServices::GLUCOSE)); | |
138 services.insert(std::make_pair(BluetoothUUID("1809"), | |
139 UMAGATTServices::HEALTH_THERMOMETER)); | |
140 services.insert( | |
141 std::make_pair(BluetoothUUID("180D"), UMAGATTServices::HEART_RATE)); | |
142 services.insert(std::make_pair(BluetoothUUID("1812"), | |
143 UMAGATTServices::HUMAN_INTERFACE_DEVICE)); | |
144 services.insert(std::make_pair(BluetoothUUID("1802"), | |
145 UMAGATTServices::IMMEDIATE_ALERT)); | |
146 services.insert(std::make_pair(BluetoothUUID("1821"), | |
147 UMAGATTServices::INDOOR_POSITIONING)); | |
148 services.insert(std::make_pair(BluetoothUUID("1820"), | |
149 UMAGATTServices::INTERNET_PROTOCOL_SUPPORT)); | |
150 services.insert( | |
151 std::make_pair(BluetoothUUID("1803"), UMAGATTServices::LINK_LOSS)); | |
152 services.insert(std::make_pair(BluetoothUUID("1819"), | |
153 UMAGATTServices::LOCATION_AND_NAVIGATION)); | |
154 services.insert(std::make_pair(BluetoothUUID("1807"), | |
155 UMAGATTServices::NEXT_DST_CHANGE)); | |
156 services.insert(std::make_pair(BluetoothUUID("180E"), | |
157 UMAGATTServices::PHONE_ALERT_STATUS)); | |
158 services.insert(std::make_pair(BluetoothUUID("1806"), | |
159 UMAGATTServices::REFERENCE_TIME_UPDATE)); | |
160 services.insert(std::make_pair(BluetoothUUID("1814"), | |
161 UMAGATTServices::RUNNING_SPEED_AND_CADENCE)); | |
162 services.insert(std::make_pair(BluetoothUUID("1813"), | |
163 UMAGATTServices::SCAN_PARAMETERS)); | |
164 services.insert( | |
165 std::make_pair(BluetoothUUID("1804"), UMAGATTServices::TX_POWER)); | |
166 services.insert( | |
167 std::make_pair(BluetoothUUID("181C"), UMAGATTServices::USER_DATA)); | |
168 services.insert( | |
169 std::make_pair(BluetoothUUID("181D"), UMAGATTServices::WEIGHT_SCALE)); | |
170 } | |
171 return &services; | |
172 } | |
173 | |
174 int GetServiceBucket(const BluetoothUUID& service) { | |
175 std::map<BluetoothUUID, UMAGATTServices>* services = getServiceToEnumMap(); | |
176 auto it = services->find(service); | |
177 if (it == services->end()) | |
178 return static_cast<int>(UMAGATTServices::UNKNOWN); | |
179 return static_cast<int>(it->second); | |
180 } | |
181 | |
182 void RecordRequestDeviceFilters( | |
183 const std::vector<content::BluetoothScanFilter>& filters) { | |
184 UMA_HISTOGRAM_COUNTS("Bluetooth.Web.RequestDevice.Filters.Count", | |
185 filters.size()); | |
186 for (const content::BluetoothScanFilter& filter : filters) { | |
187 for (const BluetoothUUID& service : filter.services) { | |
188 UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.RequestDevice.Filters.Services", | |
189 GetServiceBucket(service), | |
190 static_cast<int>(UMAGATTServices::COUNT)); | |
191 } | |
192 } | |
193 } | |
194 | |
195 void RecordRequestDeviceOptionalServices( | |
196 const std::vector<BluetoothUUID>& optional_services) { | |
197 UMA_HISTOGRAM_COUNTS("Bluetooth.Web.RequestDevice.OptionalServices.Count", | |
198 optional_services.size()); | |
199 for (const BluetoothUUID& service : optional_services) { | |
200 UMA_HISTOGRAM_ENUMERATION( | |
201 "Bluetooth.Web.RequestDevice.OptionalServices.Services", | |
202 GetServiceBucket(service), static_cast<int>(UMAGATTServices::COUNT)); | |
203 } | |
204 } | |
205 | |
66 enum class UMAWebBluetoothFunction { | 206 enum class UMAWebBluetoothFunction { |
67 REQUEST_DEVICE, | 207 REQUEST_DEVICE, |
68 CONNECT_GATT, | 208 CONNECT_GATT, |
69 GET_PRIMARY_SERVICE, | 209 GET_PRIMARY_SERVICE, |
70 GET_CHARACTERISTIC, | 210 GET_CHARACTERISTIC, |
71 CHARACTERISTIC_READ_VALUE, | 211 CHARACTERISTIC_READ_VALUE, |
72 CHARACTERISTIC_WRITE_VALUE, | 212 CHARACTERISTIC_WRITE_VALUE, |
73 // NOTE: Add new actions immediately above this line. Make sure to update the | 213 // NOTE: Add new actions immediately above this line. Make sure to update the |
74 // enum list in tools/metrics/histogram/histograms.xml accordingly. | 214 // enum list in tools/metrics/histogram/histograms.xml accordingly. |
75 COUNT | 215 COUNT |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 } | 404 } |
265 | 405 |
266 void BluetoothDispatcherHost::OnRequestDevice( | 406 void BluetoothDispatcherHost::OnRequestDevice( |
267 int thread_id, | 407 int thread_id, |
268 int request_id, | 408 int request_id, |
269 int frame_routing_id, | 409 int frame_routing_id, |
270 const std::vector<BluetoothScanFilter>& filters, | 410 const std::vector<BluetoothScanFilter>& filters, |
271 const std::vector<BluetoothUUID>& optional_services) { | 411 const std::vector<BluetoothUUID>& optional_services) { |
272 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 412 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
273 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE); | 413 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE); |
414 RecordRequestDeviceFilters(filters); | |
415 RecordRequestDeviceOptionalServices(optional_services); | |
416 | |
417 VLOG(1) << "requestDevice called with the following filters: "; | |
418 for (const BluetoothScanFilter& filter : filters) { | |
419 VLOG(1) << "["; | |
420 for (const BluetoothUUID& service : filter.services) | |
421 VLOG(1) << "\t" << service.value(); | |
422 VLOG(1) << "]"; | |
423 } | |
424 | |
425 VLOG(1) << "requestDevice called with the following optional services: "; | |
426 for (const BluetoothUUID& service : optional_services) | |
427 VLOG(1) << "\t" << service.value(); | |
274 | 428 |
275 RenderFrameHostImpl* render_frame_host = | 429 RenderFrameHostImpl* render_frame_host = |
276 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | 430 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); |
277 | 431 |
278 if (!render_frame_host) { | 432 if (!render_frame_host) { |
279 DLOG(WARNING) | 433 VLOG(1) << "Got a requestDevice IPC without a matching RenderFrameHost: " |
280 << "Got a requestDevice IPC without a matching RenderFrameHost: " | 434 << render_process_id_ << ", " << frame_routing_id; |
281 << render_process_id_ << ", " << frame_routing_id; | |
282 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME); | 435 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME); |
283 Send(new BluetoothMsg_RequestDeviceError( | 436 Send(new BluetoothMsg_RequestDeviceError( |
284 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame)); | 437 thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame)); |
285 } | 438 } |
286 | 439 |
287 // TODO(scheib): Device selection UI: crbug.com/436280 | 440 // TODO(scheib): Device selection UI: crbug.com/436280 |
288 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 441 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
289 if (adapter_.get()) { | 442 if (adapter_.get()) { |
290 if (!request_device_sessions_ | 443 if (!request_device_sessions_ |
291 .insert(std::make_pair( | 444 .insert(std::make_pair( |
(...skipping 22 matching lines...) Expand all Loading... | |
314 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff)); | 467 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff)); |
315 return; | 468 return; |
316 } | 469 } |
317 adapter_->StartDiscoverySessionWithFilter( | 470 adapter_->StartDiscoverySessionWithFilter( |
318 ComputeScanFilter(filters), | 471 ComputeScanFilter(filters), |
319 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 472 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
320 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 473 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
321 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 474 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
322 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 475 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
323 } else { | 476 } else { |
324 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 477 VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice."; |
325 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); | 478 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); |
326 Send(new BluetoothMsg_RequestDeviceError( | 479 Send(new BluetoothMsg_RequestDeviceError( |
327 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); | 480 thread_id, request_id, WebBluetoothError::NoBluetoothAdapter)); |
328 } | 481 } |
329 return; | 482 return; |
330 } | 483 } |
331 | 484 |
332 void BluetoothDispatcherHost::OnConnectGATT( | 485 void BluetoothDispatcherHost::OnConnectGATT( |
333 int thread_id, | 486 int thread_id, |
334 int request_id, | 487 int request_id, |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
598 } | 751 } |
599 | 752 |
600 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 753 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, |
601 int request_id) { | 754 int request_id) { |
602 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 755 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
603 auto session = | 756 auto session = |
604 request_device_sessions_.find(std::make_pair(thread_id, request_id)); | 757 request_device_sessions_.find(std::make_pair(thread_id, request_id)); |
605 CHECK(session != request_device_sessions_.end()); | 758 CHECK(session != request_device_sessions_.end()); |
606 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 759 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
607 for (device::BluetoothDevice* device : devices) { | 760 for (device::BluetoothDevice* device : devices) { |
761 VLOG(1) << "Device: " << device->GetName(); | |
762 VLOG(1) << "UUIDs: "; | |
763 for (BluetoothUUID uuid : device->GetUUIDs()) | |
764 VLOG(1) << "\t" << uuid.canonical_value(); | |
608 if (MatchesFilters(*device, session->second.filters)) { | 765 if (MatchesFilters(*device, session->second.filters)) { |
609 content::BluetoothDevice device_ipc( | 766 content::BluetoothDevice device_ipc( |
610 device->GetAddress(), // instance_id | 767 device->GetAddress(), // instance_id |
611 device->GetName(), // name | 768 device->GetName(), // name |
612 device->GetBluetoothClass(), // device_class | 769 device->GetBluetoothClass(), // device_class |
613 device->GetVendorIDSource(), // vendor_id_source | 770 device->GetVendorIDSource(), // vendor_id_source |
614 device->GetVendorID(), // vendor_id | 771 device->GetVendorID(), // vendor_id |
615 device->GetProductID(), // product_id | 772 device->GetProductID(), // product_id |
616 device->GetDeviceID(), // product_version | 773 device->GetDeviceID(), // product_version |
617 device->IsPaired(), // paired | 774 device->IsPaired(), // paired |
618 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 775 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
619 device->GetUUIDs())); // uuids | 776 device->GetUUIDs())); // uuids |
620 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); | 777 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); |
621 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 778 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
622 device_ipc)); | 779 device_ipc)); |
623 request_device_sessions_.erase(session); | 780 request_device_sessions_.erase(session); |
624 return; | 781 return; |
625 } | 782 } |
626 } | 783 } |
627 RecordRequestDeviceOutcome( | 784 RecordRequestDeviceOutcome( |
628 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); | 785 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); |
786 VLOG(1) << "No matching Bluetooth Devices found"; | |
629 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 787 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
630 WebBluetoothError::NoDevicesFound)); | 788 WebBluetoothError::NoDevicesFound)); |
631 request_device_sessions_.erase(session); | 789 request_device_sessions_.erase(session); |
632 } | 790 } |
633 | 791 |
634 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 792 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
635 int request_id) { | 793 int request_id) { |
636 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 794 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
637 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 795 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
638 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_STOP_FAILED); | 796 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_STOP_FAILED); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
721 | 879 |
722 void BluetoothDispatcherHost::OnWriteValueFailed( | 880 void BluetoothDispatcherHost::OnWriteValueFailed( |
723 int thread_id, | 881 int thread_id, |
724 int request_id, | 882 int request_id, |
725 device::BluetoothGattService::GattErrorCode error_code) { | 883 device::BluetoothGattService::GattErrorCode error_code) { |
726 Send(new BluetoothMsg_WriteCharacteristicValueError( | 884 Send(new BluetoothMsg_WriteCharacteristicValueError( |
727 thread_id, request_id, TranslateGATTError(error_code))); | 885 thread_id, request_id, TranslateGATTError(error_code))); |
728 } | 886 } |
729 | 887 |
730 } // namespace content | 888 } // namespace content |
OLD | NEW |