| 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 |