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 |
11 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 11 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
12 | 12 |
13 #include "base/hash.h" | |
14 #include "base/metrics/histogram_macros.h" | |
15 #include "base/metrics/sparse_histogram.h" | |
16 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
17 #include "content/browser/bad_message.h" | 14 #include "content/browser/bad_message.h" |
| 15 #include "content/browser/bluetooth/bluetooth_metrics.h" |
18 #include "content/browser/frame_host/render_frame_host_impl.h" | 16 #include "content/browser/frame_host/render_frame_host_impl.h" |
19 #include "content/common/bluetooth/bluetooth_messages.h" | 17 #include "content/common/bluetooth/bluetooth_messages.h" |
20 #include "device/bluetooth/bluetooth_adapter.h" | 18 #include "device/bluetooth/bluetooth_adapter.h" |
21 #include "device/bluetooth/bluetooth_adapter_factory.h" | 19 #include "device/bluetooth/bluetooth_adapter_factory.h" |
22 #include "device/bluetooth/bluetooth_device.h" | 20 #include "device/bluetooth/bluetooth_device.h" |
23 #include "device/bluetooth/bluetooth_discovery_session.h" | 21 #include "device/bluetooth/bluetooth_discovery_session.h" |
24 #include "device/bluetooth/bluetooth_gatt_characteristic.h" | 22 #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
25 #include "device/bluetooth/bluetooth_gatt_service.h" | 23 #include "device/bluetooth/bluetooth_gatt_service.h" |
26 | 24 |
27 using blink::WebBluetoothError; | 25 using blink::WebBluetoothError; |
28 using device::BluetoothAdapter; | 26 using device::BluetoothAdapter; |
29 using device::BluetoothAdapterFactory; | 27 using device::BluetoothAdapterFactory; |
30 using device::BluetoothGattCharacteristic; | 28 using device::BluetoothGattCharacteristic; |
31 using device::BluetoothGattService; | 29 using device::BluetoothGattService; |
32 using device::BluetoothUUID; | 30 using device::BluetoothUUID; |
33 | 31 |
| 32 namespace content { |
| 33 |
34 namespace { | 34 namespace { |
35 | 35 |
36 // These types of errors aren't as common. We log them to understand | |
37 // how common they are and if we need to investigate more. | |
38 enum class BluetoothGATTError { | |
39 UNKNOWN, | |
40 FAILED, | |
41 IN_PROGRESS, | |
42 NOT_PAIRED, | |
43 // Add errors above this line and update corresponding histograms.xml enum. | |
44 MAX_ERROR, | |
45 }; | |
46 | |
47 enum class UMARequestDeviceOutcome { | |
48 SUCCESS = 0, | |
49 NO_BLUETOOTH_ADAPTER = 1, | |
50 NO_RENDER_FRAME = 2, | |
51 DISCOVERY_START_FAILED = 3, | |
52 DISCOVERY_STOP_FAILED = 4, | |
53 NO_MATCHING_DEVICES_FOUND = 5, | |
54 BLUETOOTH_ADAPTER_NOT_PRESENT = 6, | |
55 BLUETOOTH_ADAPTER_OFF = 7, | |
56 // NOTE: Add new requestDevice() outcomes immediately above this line. Make | |
57 // sure to update the enum list in | |
58 // tools/metrics/histogram/histograms.xml accordingly. | |
59 COUNT | |
60 }; | |
61 | |
62 void RecordRequestDeviceOutcome(UMARequestDeviceOutcome outcome) { | |
63 UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.RequestDevice.Outcome", | |
64 static_cast<int>(outcome), | |
65 static_cast<int>(UMARequestDeviceOutcome::COUNT)); | |
66 } | |
67 // TODO(ortuno): Remove once we have a macro to histogram strings. | |
68 // http://crbug.com/520284 | |
69 int HashUUID(const std::string& uuid) { | |
70 uint32 data = base::SuperFastHash(uuid.data(), uuid.size()); | |
71 | |
72 // Strip off the signed bit because UMA doesn't support negative values, | |
73 // but takes a signed int as input. | |
74 return static_cast<int>(data & 0x7fffffff); | |
75 } | |
76 | |
77 void RecordRequestDeviceFilters( | |
78 const std::vector<content::BluetoothScanFilter>& filters) { | |
79 UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.Filters.Count", | |
80 filters.size()); | |
81 for (const content::BluetoothScanFilter& filter : filters) { | |
82 UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.FilterSize", | |
83 filter.services.size()); | |
84 for (const BluetoothUUID& service : filter.services) { | |
85 // TODO(ortuno): Use a macro to histogram strings. | |
86 // http://crbug.com/520284 | |
87 UMA_HISTOGRAM_SPARSE_SLOWLY( | |
88 "Bluetooth.Web.RequestDevice.Filters.Services", | |
89 HashUUID(service.canonical_value())); | |
90 } | |
91 } | |
92 } | |
93 | |
94 void RecordRequestDeviceOptionalServices( | |
95 const std::vector<BluetoothUUID>& optional_services) { | |
96 UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.OptionalServices.Count", | |
97 optional_services.size()); | |
98 for (const BluetoothUUID& service : optional_services) { | |
99 // TODO(ortuno): Use a macro to histogram strings. | |
100 // http://crbug.com/520284 | |
101 UMA_HISTOGRAM_SPARSE_SLOWLY( | |
102 "Bluetooth.Web.RequestDevice.OptionalServices.Services", | |
103 HashUUID(service.canonical_value())); | |
104 } | |
105 } | |
106 | |
107 void RecordUnionOfServices( | |
108 const std::vector<content::BluetoothScanFilter>& filters, | |
109 const std::vector<BluetoothUUID>& optional_services) { | |
110 std::set<BluetoothUUID> union_of_services(optional_services.begin(), | |
111 optional_services.end()); | |
112 | |
113 for (const content::BluetoothScanFilter& filter : filters) | |
114 union_of_services.insert(filter.services.begin(), filter.services.end()); | |
115 | |
116 UMA_HISTOGRAM_COUNTS_100("Bluetooth.Web.RequestDevice.UnionOfServices.Count", | |
117 union_of_services.size()); | |
118 } | |
119 | |
120 enum class UMAGetPrimaryServiceOutcome { | |
121 SUCCESS, | |
122 NO_DEVICE, | |
123 NOT_FOUND, | |
124 // Note: Add new GetPrimaryService outcomes immediately above this line. Make | |
125 // sure to update the enum list in tools/metrics/histograms/histograms.xml | |
126 // accordingly. | |
127 COUNT | |
128 }; | |
129 | |
130 void RecordGetPrimaryServiceService(const BluetoothUUID& service) { | |
131 UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.GetPrimaryService.Services", | |
132 HashUUID(service.canonical_value())); | |
133 } | |
134 | |
135 void RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome outcome) { | |
136 UMA_HISTOGRAM_ENUMERATION( | |
137 "Bluetooth.Web.GetPrimaryService.Outcome", static_cast<int>(outcome), | |
138 static_cast<int>(UMAGetPrimaryServiceOutcome::COUNT)); | |
139 } | |
140 | |
141 enum class UMAConnectGATTOutcome { | |
142 SUCCESS, | |
143 NO_DEVICE, | |
144 UNKNOWN, | |
145 IN_PROGRESS, | |
146 FAILED, | |
147 AUTH_FAILED, | |
148 AUTH_CANCELED, | |
149 AUTH_REJECTED, | |
150 AUTH_TIMEOUT, | |
151 UNSUPPORTED_DEVICE, | |
152 // Note: Add new ConnectGATT outcomes immediately above this line. Make sure | |
153 // to update the enum list in tools/metrisc/histogram/histograms.xml | |
154 // accordingly. | |
155 COUNT | |
156 }; | |
157 | |
158 void RecordConnectGATTOutcome(UMAConnectGATTOutcome outcome) { | |
159 UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.ConnectGATT.Outcome", | |
160 static_cast<int>(outcome), | |
161 static_cast<int>(UMAConnectGATTOutcome::COUNT)); | |
162 } | |
163 | |
164 void RecordConnectGATTTimeSuccess(const base::TimeDelta& duration) { | |
165 UMA_HISTOGRAM_MEDIUM_TIMES("Bluetooth.Web.ConnectGATT.TimeSuccess", duration); | |
166 } | |
167 | |
168 void RecordConnectGATTTimeFailed(const base::TimeDelta& duration) { | |
169 UMA_HISTOGRAM_MEDIUM_TIMES("Bluetooth.Web.ConnectGATT.TimeFailed", duration); | |
170 } | |
171 | |
172 enum class UMAWebBluetoothFunction { | |
173 REQUEST_DEVICE, | |
174 CONNECT_GATT, | |
175 GET_PRIMARY_SERVICE, | |
176 GET_CHARACTERISTIC, | |
177 CHARACTERISTIC_READ_VALUE, | |
178 CHARACTERISTIC_WRITE_VALUE, | |
179 // NOTE: Add new actions immediately above this line. Make sure to update the | |
180 // enum list in tools/metrics/histogram/histograms.xml accordingly. | |
181 COUNT | |
182 }; | |
183 | |
184 void RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction function) { | |
185 UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.FunctionCall.Count", | |
186 static_cast<int>(function), | |
187 static_cast<int>(UMAWebBluetoothFunction::COUNT)); | |
188 } | |
189 | |
190 // TODO(ortuno): Once we have a chooser for scanning and the right | 36 // TODO(ortuno): Once we have a chooser for scanning and the right |
191 // callback for discovered services we should delete these constants. | 37 // callback for discovered services we should delete these constants. |
192 // https://crbug.com/436280 and https://crbug.com/484504 | 38 // https://crbug.com/436280 and https://crbug.com/484504 |
193 const int kDelayTime = 5; // 5 seconds for scanning and discovering | 39 const int kDelayTime = 5; // 5 seconds for scanning and discovering |
194 const int kTestingDelayTime = 0; // No need to wait during tests | 40 const int kTestingDelayTime = 0; // No need to wait during tests |
195 | 41 |
196 // Defined at | 42 // Defined at |
197 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter | 43 // https://webbluetoothchrome.github.io/web-bluetooth/#dfn-matches-a-filter |
198 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, | 44 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
199 const content::BluetoothScanFilter& filter) { | 45 const content::BluetoothScanFilter& filter) { |
(...skipping 13 matching lines...) Expand all Loading... |
213 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), | 59 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), |
214 device_uuid_list.end()); | 60 device_uuid_list.end()); |
215 for (const content::BluetoothScanFilter& filter : filters) { | 61 for (const content::BluetoothScanFilter& filter : filters) { |
216 if (MatchesFilter(device_uuids, filter)) { | 62 if (MatchesFilter(device_uuids, filter)) { |
217 return true; | 63 return true; |
218 } | 64 } |
219 } | 65 } |
220 return false; | 66 return false; |
221 } | 67 } |
222 | 68 |
223 void AddToHistogram(BluetoothGATTError error) { | |
224 UMA_HISTOGRAM_ENUMERATION("Bluetooth.GATTErrors", static_cast<int>(error), | |
225 static_cast<int>(BluetoothGATTError::MAX_ERROR)); | |
226 } | |
227 | |
228 WebBluetoothError TranslateConnectError( | 69 WebBluetoothError TranslateConnectError( |
229 device::BluetoothDevice::ConnectErrorCode error_code) { | 70 device::BluetoothDevice::ConnectErrorCode error_code) { |
230 switch (error_code) { | 71 switch (error_code) { |
231 case device::BluetoothDevice::ERROR_UNKNOWN: | 72 case device::BluetoothDevice::ERROR_UNKNOWN: |
232 RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNKNOWN); | 73 RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNKNOWN); |
233 return WebBluetoothError::ConnectUnknownError; | 74 return WebBluetoothError::ConnectUnknownError; |
234 case device::BluetoothDevice::ERROR_INPROGRESS: | 75 case device::BluetoothDevice::ERROR_INPROGRESS: |
235 RecordConnectGATTOutcome(UMAConnectGATTOutcome::IN_PROGRESS); | 76 RecordConnectGATTOutcome(UMAConnectGATTOutcome::IN_PROGRESS); |
236 return WebBluetoothError::ConnectAlreadyInProgress; | 77 return WebBluetoothError::ConnectAlreadyInProgress; |
237 case device::BluetoothDevice::ERROR_FAILED: | 78 case device::BluetoothDevice::ERROR_FAILED: |
(...skipping 16 matching lines...) Expand all Loading... |
254 return WebBluetoothError::ConnectUnsupportedDevice; | 95 return WebBluetoothError::ConnectUnsupportedDevice; |
255 } | 96 } |
256 NOTREACHED(); | 97 NOTREACHED(); |
257 return WebBluetoothError::UntranslatedConnectErrorCode; | 98 return WebBluetoothError::UntranslatedConnectErrorCode; |
258 } | 99 } |
259 | 100 |
260 blink::WebBluetoothError TranslateGATTError( | 101 blink::WebBluetoothError TranslateGATTError( |
261 BluetoothGattService::GattErrorCode error_code) { | 102 BluetoothGattService::GattErrorCode error_code) { |
262 switch (error_code) { | 103 switch (error_code) { |
263 case BluetoothGattService::GATT_ERROR_UNKNOWN: | 104 case BluetoothGattService::GATT_ERROR_UNKNOWN: |
264 AddToHistogram(BluetoothGATTError::UNKNOWN); | 105 RecordGATTError(UMAGATTError::UNKNOWN); |
265 return blink::WebBluetoothError::GATTUnknownError; | 106 return blink::WebBluetoothError::GATTUnknownError; |
266 case BluetoothGattService::GATT_ERROR_FAILED: | 107 case BluetoothGattService::GATT_ERROR_FAILED: |
267 AddToHistogram(BluetoothGATTError::FAILED); | 108 RecordGATTError(UMAGATTError::FAILED); |
268 return blink::WebBluetoothError::GATTUnknownFailure; | 109 return blink::WebBluetoothError::GATTUnknownFailure; |
269 case BluetoothGattService::GATT_ERROR_IN_PROGRESS: | 110 case BluetoothGattService::GATT_ERROR_IN_PROGRESS: |
270 AddToHistogram(BluetoothGATTError::IN_PROGRESS); | 111 RecordGATTError(UMAGATTError::IN_PROGRESS); |
271 return blink::WebBluetoothError::GATTOperationInProgress; | 112 return blink::WebBluetoothError::GATTOperationInProgress; |
272 case BluetoothGattService::GATT_ERROR_INVALID_LENGTH: | 113 case BluetoothGattService::GATT_ERROR_INVALID_LENGTH: |
273 return blink::WebBluetoothError::GATTInvalidAttributeLength; | 114 return blink::WebBluetoothError::GATTInvalidAttributeLength; |
274 case BluetoothGattService::GATT_ERROR_NOT_PERMITTED: | 115 case BluetoothGattService::GATT_ERROR_NOT_PERMITTED: |
275 return blink::WebBluetoothError::GATTNotPermitted; | 116 return blink::WebBluetoothError::GATTNotPermitted; |
276 case BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED: | 117 case BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED: |
277 return blink::WebBluetoothError::GATTNotAuthorized; | 118 return blink::WebBluetoothError::GATTNotAuthorized; |
278 case BluetoothGattService::GATT_ERROR_NOT_PAIRED: | 119 case BluetoothGattService::GATT_ERROR_NOT_PAIRED: |
279 AddToHistogram(BluetoothGATTError::NOT_PAIRED); | 120 RecordGATTError(UMAGATTError::NOT_PAIRED); |
280 return blink::WebBluetoothError::GATTNotPaired; | 121 return blink::WebBluetoothError::GATTNotPaired; |
281 case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED: | 122 case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED: |
282 return blink::WebBluetoothError::GATTNotSupported; | 123 return blink::WebBluetoothError::GATTNotSupported; |
283 } | 124 } |
284 NOTREACHED(); | 125 NOTREACHED(); |
285 return blink::WebBluetoothError::GATTUntranslatedErrorCode; | 126 return blink::WebBluetoothError::GATTUntranslatedErrorCode; |
286 } | 127 } |
287 | 128 |
288 } // namespace | 129 } // namespace |
289 | 130 |
290 namespace content { | |
291 | |
292 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id) | 131 BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id) |
293 : BrowserMessageFilter(BluetoothMsgStart), | 132 : BrowserMessageFilter(BluetoothMsgStart), |
294 render_process_id_(render_process_id), | 133 render_process_id_(render_process_id), |
295 weak_ptr_factory_(this) { | 134 weak_ptr_factory_(this) { |
296 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 135 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
297 current_delay_time_ = kDelayTime; | 136 current_delay_time_ = kDelayTime; |
298 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) | 137 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) |
299 BluetoothAdapterFactory::GetAdapter( | 138 BluetoothAdapterFactory::GetAdapter( |
300 base::Bind(&BluetoothDispatcherHost::set_adapter, | 139 base::Bind(&BluetoothDispatcherHost::set_adapter, |
301 weak_ptr_factory_.GetWeakPtr())); | 140 weak_ptr_factory_.GetWeakPtr())); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 } | 217 } |
379 | 218 |
380 void BluetoothDispatcherHost::OnRequestDevice( | 219 void BluetoothDispatcherHost::OnRequestDevice( |
381 int thread_id, | 220 int thread_id, |
382 int request_id, | 221 int request_id, |
383 int frame_routing_id, | 222 int frame_routing_id, |
384 const std::vector<BluetoothScanFilter>& filters, | 223 const std::vector<BluetoothScanFilter>& filters, |
385 const std::vector<BluetoothUUID>& optional_services) { | 224 const std::vector<BluetoothUUID>& optional_services) { |
386 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 225 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
387 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE); | 226 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE); |
388 RecordRequestDeviceFilters(filters); | 227 RecordRequestDeviceArguments(filters, optional_services); |
389 RecordRequestDeviceOptionalServices(optional_services); | |
390 RecordUnionOfServices(filters, optional_services); | |
391 | 228 |
392 VLOG(1) << "requestDevice called with the following filters: "; | 229 VLOG(1) << "requestDevice called with the following filters: "; |
393 for (const BluetoothScanFilter& filter : filters) { | 230 for (const BluetoothScanFilter& filter : filters) { |
394 VLOG(1) << "\t["; | 231 VLOG(1) << "\t["; |
395 for (const BluetoothUUID& service : filter.services) | 232 for (const BluetoothUUID& service : filter.services) |
396 VLOG(1) << "\t\t" << service.value(); | 233 VLOG(1) << "\t\t" << service.value(); |
397 VLOG(1) << "\t]"; | 234 VLOG(1) << "\t]"; |
398 } | 235 } |
399 | 236 |
400 VLOG(1) << "requestDevice called with the following optional services: "; | 237 VLOG(1) << "requestDevice called with the following optional services: "; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); | 273 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); |
437 return; | 274 return; |
438 } | 275 } |
439 // TODO(jyasskin): Once the dialog is available, the dialog should check for | 276 // TODO(jyasskin): Once the dialog is available, the dialog should check for |
440 // the status of the adapter, i.e. check IsPowered() and | 277 // the status of the adapter, i.e. check IsPowered() and |
441 // BluetoothAdapter::Observer::PoweredChanged, and inform the user. But | 278 // BluetoothAdapter::Observer::PoweredChanged, and inform the user. But |
442 // until the dialog is available we log/histogram the status and return | 279 // until the dialog is available we log/histogram the status and return |
443 // with a message. | 280 // with a message. |
444 // https://crbug.com/517237 | 281 // https://crbug.com/517237 |
445 if (!adapter_->IsPowered()) { | 282 if (!adapter_->IsPowered()) { |
446 VLOG(1) << "Bluetooth Adapter is not powered. Can't serve requestDevice."; | |
447 RecordRequestDeviceOutcome( | 283 RecordRequestDeviceOutcome( |
448 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_OFF); | 284 UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_OFF); |
449 Send(new BluetoothMsg_RequestDeviceError( | 285 Send(new BluetoothMsg_RequestDeviceError( |
450 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff)); | 286 thread_id, request_id, WebBluetoothError::BluetoothAdapterOff)); |
451 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); | 287 request_device_sessions_.erase(std::make_pair(thread_id, request_id)); |
452 return; | 288 return; |
453 } | 289 } |
454 adapter_->StartDiscoverySessionWithFilter( | 290 adapter_->StartDiscoverySessionWithFilter( |
455 ComputeScanFilter(filters), | 291 ComputeScanFilter(filters), |
456 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 292 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
(...skipping 17 matching lines...) Expand all Loading... |
474 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 310 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); |
475 const base::TimeTicks start_time = base::TimeTicks::Now(); | 311 const base::TimeTicks start_time = base::TimeTicks::Now(); |
476 | 312 |
477 // TODO(ortuno): Right now it's pointless to check if the domain has access to | 313 // TODO(ortuno): Right now it's pointless to check if the domain has access to |
478 // the device, because any domain can connect to any device. But once | 314 // the device, because any domain can connect to any device. But once |
479 // permissions are implemented we should check that the domain has access to | 315 // permissions are implemented we should check that the domain has access to |
480 // the device. https://crbug.com/484745 | 316 // the device. https://crbug.com/484745 |
481 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 317 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); |
482 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 318 if (device == nullptr) { // See "NETWORK_ERROR Note" above. |
483 RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); | 319 RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); |
484 VLOG(1) << "Bluetooth Device no longer in range."; | |
485 Send(new BluetoothMsg_ConnectGATTError( | 320 Send(new BluetoothMsg_ConnectGATTError( |
486 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 321 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); |
487 return; | 322 return; |
488 } | 323 } |
489 device->CreateGattConnection( | 324 device->CreateGattConnection( |
490 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 325 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
491 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 326 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
492 device_instance_id, start_time), | 327 device_instance_id, start_time), |
493 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 328 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, |
494 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 329 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 } | 574 } |
740 | 575 |
741 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 576 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, |
742 int request_id) { | 577 int request_id) { |
743 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 578 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
744 auto session = | 579 auto session = |
745 request_device_sessions_.find(std::make_pair(thread_id, request_id)); | 580 request_device_sessions_.find(std::make_pair(thread_id, request_id)); |
746 CHECK(session != request_device_sessions_.end()); | 581 CHECK(session != request_device_sessions_.end()); |
747 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 582 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
748 for (device::BluetoothDevice* device : devices) { | 583 for (device::BluetoothDevice* device : devices) { |
749 // Remove VLOG when stable. http://crbug.com/519010 | |
750 VLOG(1) << "Device: " << device->GetName(); | 584 VLOG(1) << "Device: " << device->GetName(); |
751 VLOG(1) << "UUIDs: "; | 585 VLOG(1) << "UUIDs: "; |
752 for (BluetoothUUID uuid : device->GetUUIDs()) | 586 for (BluetoothUUID uuid : device->GetUUIDs()) |
753 VLOG(1) << "\t" << uuid.canonical_value(); | 587 VLOG(1) << "\t" << uuid.canonical_value(); |
754 if (MatchesFilters(*device, session->second.filters)) { | 588 if (MatchesFilters(*device, session->second.filters)) { |
755 content::BluetoothDevice device_ipc( | 589 content::BluetoothDevice device_ipc( |
756 device->GetAddress(), // instance_id | 590 device->GetAddress(), // instance_id |
757 device->GetName(), // name | 591 device->GetName(), // name |
758 device->GetBluetoothClass(), // device_class | 592 device->GetBluetoothClass(), // device_class |
759 device->GetVendorIDSource(), // vendor_id_source | 593 device->GetVendorIDSource(), // vendor_id_source |
760 device->GetVendorID(), // vendor_id | 594 device->GetVendorID(), // vendor_id |
761 device->GetProductID(), // product_id | 595 device->GetProductID(), // product_id |
762 device->GetDeviceID(), // product_version | 596 device->GetDeviceID(), // product_version |
763 device->IsPaired(), // paired | 597 device->IsPaired(), // paired |
764 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 598 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
765 device->GetUUIDs())); // uuids | 599 device->GetUUIDs())); // uuids |
766 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); | 600 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); |
767 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 601 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
768 device_ipc)); | 602 device_ipc)); |
769 request_device_sessions_.erase(session); | 603 request_device_sessions_.erase(session); |
770 return; | 604 return; |
771 } | 605 } |
772 } | 606 } |
773 RecordRequestDeviceOutcome( | 607 RecordRequestDeviceOutcome( |
774 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); | 608 UMARequestDeviceOutcome::NO_MATCHING_DEVICES_FOUND); |
775 VLOG(1) << "No matching Bluetooth Devices found"; | |
776 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 609 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
777 WebBluetoothError::NoDevicesFound)); | 610 WebBluetoothError::NoDevicesFound)); |
778 request_device_sessions_.erase(session); | 611 request_device_sessions_.erase(session); |
779 } | 612 } |
780 | 613 |
781 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 614 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
782 int request_id) { | 615 int request_id) { |
783 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 616 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
784 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 617 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
785 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_STOP_FAILED); | 618 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::DISCOVERY_STOP_FAILED); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 void BluetoothDispatcherHost::OnServicesDiscovered( | 653 void BluetoothDispatcherHost::OnServicesDiscovered( |
821 int thread_id, | 654 int thread_id, |
822 int request_id, | 655 int request_id, |
823 const std::string& device_instance_id, | 656 const std::string& device_instance_id, |
824 const std::string& service_uuid) { | 657 const std::string& service_uuid) { |
825 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 658 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
826 | 659 |
827 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 660 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); |
828 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 661 if (device == nullptr) { // See "NETWORK_ERROR Note" above. |
829 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); | 662 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); |
830 VLOG(1) << "Bluetooth Device is no longer in range."; | |
831 Send(new BluetoothMsg_GetPrimaryServiceError( | 663 Send(new BluetoothMsg_GetPrimaryServiceError( |
832 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 664 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); |
833 return; | 665 return; |
834 } | 666 } |
835 for (BluetoothGattService* service : device->GetGattServices()) { | 667 for (BluetoothGattService* service : device->GetGattServices()) { |
836 if (service->GetUUID().canonical_value() == service_uuid) { | 668 if (service->GetUUID().canonical_value() == service_uuid) { |
837 // TODO(ortuno): Use generated instance ID instead. | 669 // TODO(ortuno): Use generated instance ID instead. |
838 // https://crbug.com/495379 | 670 // https://crbug.com/495379 |
839 const std::string& service_identifier = service->GetIdentifier(); | 671 const std::string& service_identifier = service->GetIdentifier(); |
840 auto insert_result = service_to_device_.insert( | 672 auto insert_result = service_to_device_.insert( |
841 make_pair(service_identifier, device_instance_id)); | 673 make_pair(service_identifier, device_instance_id)); |
842 | 674 |
843 // If a value is already in map, DCHECK it's valid. | 675 // If a value is already in map, DCHECK it's valid. |
844 if (!insert_result.second) | 676 if (!insert_result.second) |
845 DCHECK(insert_result.first->second == device_instance_id); | 677 DCHECK(insert_result.first->second == device_instance_id); |
846 | 678 |
847 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::SUCCESS); | 679 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::SUCCESS); |
848 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, | 680 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, |
849 service_identifier)); | 681 service_identifier)); |
850 return; | 682 return; |
851 } | 683 } |
852 } | 684 } |
853 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NOT_FOUND); | 685 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NOT_FOUND); |
854 VLOG(1) << "No GATT services with UUID: " << service_uuid; | |
855 Send(new BluetoothMsg_GetPrimaryServiceError( | 686 Send(new BluetoothMsg_GetPrimaryServiceError( |
856 thread_id, request_id, WebBluetoothError::ServiceNotFound)); | 687 thread_id, request_id, WebBluetoothError::ServiceNotFound)); |
857 } | 688 } |
858 | 689 |
859 void BluetoothDispatcherHost::OnCharacteristicValueRead( | 690 void BluetoothDispatcherHost::OnCharacteristicValueRead( |
860 int thread_id, | 691 int thread_id, |
861 int request_id, | 692 int request_id, |
862 const std::vector<uint8>& value) { | 693 const std::vector<uint8>& value) { |
863 Send(new BluetoothMsg_ReadCharacteristicValueSuccess(thread_id, request_id, | 694 Send(new BluetoothMsg_ReadCharacteristicValueSuccess(thread_id, request_id, |
864 value)); | 695 value)); |
(...skipping 14 matching lines...) Expand all Loading... |
879 | 710 |
880 void BluetoothDispatcherHost::OnWriteValueFailed( | 711 void BluetoothDispatcherHost::OnWriteValueFailed( |
881 int thread_id, | 712 int thread_id, |
882 int request_id, | 713 int request_id, |
883 device::BluetoothGattService::GattErrorCode error_code) { | 714 device::BluetoothGattService::GattErrorCode error_code) { |
884 Send(new BluetoothMsg_WriteCharacteristicValueError( | 715 Send(new BluetoothMsg_WriteCharacteristicValueError( |
885 thread_id, request_id, TranslateGATTError(error_code))); | 716 thread_id, request_id, TranslateGATTError(error_code))); |
886 } | 717 } |
887 | 718 |
888 } // namespace content | 719 } // namespace content |
OLD | NEW |