| 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://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-connectga
tt | 9 // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-connectga
tt |
| 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/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "content/browser/bad_message.h" | 15 #include "content/browser/bad_message.h" |
| 16 #include "content/common/bluetooth/bluetooth_messages.h" | 16 #include "content/common/bluetooth/bluetooth_messages.h" |
| 17 #include "device/bluetooth/bluetooth_adapter.h" | 17 #include "device/bluetooth/bluetooth_adapter.h" |
| 18 #include "device/bluetooth/bluetooth_adapter_factory.h" | 18 #include "device/bluetooth/bluetooth_adapter_factory.h" |
| 19 #include "device/bluetooth/bluetooth_device.h" | 19 #include "device/bluetooth/bluetooth_device.h" |
| 20 #include "device/bluetooth/bluetooth_discovery_session.h" | 20 #include "device/bluetooth/bluetooth_discovery_session.h" |
| 21 #include "device/bluetooth/bluetooth_gatt_characteristic.h" | 21 #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
| 22 #include "device/bluetooth/bluetooth_gatt_service.h" | 22 #include "device/bluetooth/bluetooth_gatt_service.h" |
| 23 | 23 |
| 24 using device::BluetoothAdapter; | 24 using device::BluetoothAdapter; |
| 25 using device::BluetoothAdapterFactory; | 25 using device::BluetoothAdapterFactory; |
| 26 using device::BluetoothGattCharacteristic; | 26 using device::BluetoothGattCharacteristic; |
| 27 using device::BluetoothGattService; | 27 using device::BluetoothGattService; |
| 28 using device::BluetoothUUID; |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 // These types of errors aren't as common. We log them to understand | 32 // These types of errors aren't as common. We log them to understand |
| 32 // how common they are and if we need to investigate more. | 33 // how common they are and if we need to investigate more. |
| 33 enum class BluetoothGATTError { | 34 enum class BluetoothGATTError { |
| 34 UNKNOWN, | 35 UNKNOWN, |
| 35 FAILED, | 36 FAILED, |
| 36 IN_PROGRESS, | 37 IN_PROGRESS, |
| 37 NOT_PAIRED, | 38 NOT_PAIRED, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 53 | 54 |
| 54 const char kNoDevicesFound[] = "No Bluetooth devices in range."; | 55 const char kNoDevicesFound[] = "No Bluetooth devices in range."; |
| 55 const char kServiceNotFound[] = "Service not found in device"; | 56 const char kServiceNotFound[] = "Service not found in device"; |
| 56 const char kCharacteristicNotFound[] = "Characteristic not found in device."; | 57 const char kCharacteristicNotFound[] = "Characteristic not found in device."; |
| 57 | 58 |
| 58 const char kDeviceNoLongerInRange[] = "Bluetooth Device is no longer in range."; | 59 const char kDeviceNoLongerInRange[] = "Bluetooth Device is no longer in range."; |
| 59 const char kServiceNoLongerExists[] = "GATT Service no longer exists."; | 60 const char kServiceNoLongerExists[] = "GATT Service no longer exists."; |
| 60 const char kCharacteristicNoLongerExits[] = | 61 const char kCharacteristicNoLongerExits[] = |
| 61 "GATT Characteristic no longer exists"; | 62 "GATT Characteristic no longer exists"; |
| 62 | 63 |
| 64 // Defined at |
| 65 // https://webbluetoothcg.github.io/web-bluetooth/#dfn-matches-a-filter |
| 66 bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
| 67 const content::BluetoothScanFilter& filter) { |
| 68 if (filter.services.empty()) |
| 69 return false; |
| 70 for (const BluetoothUUID& service : filter.services) { |
| 71 if (!ContainsKey(device_uuids, service)) { |
| 72 return false; |
| 73 } |
| 74 } |
| 75 return true; |
| 76 } |
| 77 |
| 78 bool MatchesFilters(const device::BluetoothDevice& device, |
| 79 const std::vector<content::BluetoothScanFilter>& filters) { |
| 80 const std::vector<BluetoothUUID>& device_uuid_list = device.GetUUIDs(); |
| 81 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), |
| 82 device_uuid_list.end()); |
| 83 for (const content::BluetoothScanFilter& filter : filters) { |
| 84 if (MatchesFilter(device_uuids, filter)) { |
| 85 return true; |
| 86 } |
| 87 } |
| 88 return false; |
| 89 } |
| 90 |
| 63 void AddToHistogram(BluetoothGATTError error) { | 91 void AddToHistogram(BluetoothGATTError error) { |
| 64 UMA_HISTOGRAM_ENUMERATION("Bluetooth.GATTErrors", static_cast<int>(error), | 92 UMA_HISTOGRAM_ENUMERATION("Bluetooth.GATTErrors", static_cast<int>(error), |
| 65 static_cast<int>(BluetoothGATTError::MAX_ERROR)); | 93 static_cast<int>(BluetoothGATTError::MAX_ERROR)); |
| 66 } | 94 } |
| 67 | 95 |
| 68 std::string GetConnectErrorMessage( | 96 std::string GetConnectErrorMessage( |
| 69 device::BluetoothDevice::ConnectErrorCode error_code) { | 97 device::BluetoothDevice::ConnectErrorCode error_code) { |
| 70 switch (error_code) { | 98 switch (error_code) { |
| 71 case device::BluetoothDevice::ERROR_UNKNOWN: | 99 case device::BluetoothDevice::ERROR_UNKNOWN: |
| 72 return "Unknown error when connecting to the device."; | 100 return "Unknown error when connecting to the device."; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 current_delay_time_ = kTestingDelayTime; | 200 current_delay_time_ = kTestingDelayTime; |
| 173 set_adapter(mock_adapter.Pass()); | 201 set_adapter(mock_adapter.Pass()); |
| 174 } | 202 } |
| 175 | 203 |
| 176 BluetoothDispatcherHost::~BluetoothDispatcherHost() { | 204 BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 205 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 178 // Clear adapter, releasing observer references. | 206 // Clear adapter, releasing observer references. |
| 179 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 207 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| 180 } | 208 } |
| 181 | 209 |
| 210 struct BluetoothDispatcherHost::DiscoverySessionOptions { |
| 211 DiscoverySessionOptions(const std::vector<BluetoothScanFilter>& filters, |
| 212 const std::vector<BluetoothUUID>& optional_services) |
| 213 : filters(filters), optional_services(optional_services) {} |
| 214 |
| 215 std::vector<BluetoothScanFilter> filters; |
| 216 std::vector<BluetoothUUID> optional_services; |
| 217 }; |
| 218 |
| 182 void BluetoothDispatcherHost::set_adapter( | 219 void BluetoothDispatcherHost::set_adapter( |
| 183 scoped_refptr<device::BluetoothAdapter> adapter) { | 220 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 184 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 221 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 185 if (adapter_.get()) | 222 if (adapter_.get()) |
| 186 adapter_->RemoveObserver(this); | 223 adapter_->RemoveObserver(this); |
| 187 adapter_ = adapter; | 224 adapter_ = adapter; |
| 188 if (adapter_.get()) | 225 if (adapter_.get()) |
| 189 adapter_->AddObserver(this); | 226 adapter_->AddObserver(this); |
| 190 } | 227 } |
| 191 | 228 |
| 192 void BluetoothDispatcherHost::OnRequestDevice(int thread_id, int request_id) { | 229 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 230 const std::vector<BluetoothScanFilter>& filters) { |
| 231 std::set<BluetoothUUID> services; |
| 232 for (const BluetoothScanFilter& filter : filters) { |
| 233 services.insert(filter.services.begin(), filter.services.end()); |
| 234 } |
| 235 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( |
| 236 new device::BluetoothDiscoveryFilter( |
| 237 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); |
| 238 for (const BluetoothUUID& service : services) { |
| 239 discovery_filter->AddUUID(service); |
| 240 } |
| 241 return discovery_filter.Pass(); |
| 242 } |
| 243 |
| 244 void BluetoothDispatcherHost::OnRequestDevice( |
| 245 int thread_id, |
| 246 int request_id, |
| 247 const std::vector<BluetoothScanFilter>& filters, |
| 248 const std::vector<BluetoothUUID>& optional_services) { |
| 193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 249 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 194 // TODO(scheib): Filter devices by services: crbug.com/440594 | |
| 195 // TODO(scheib): Device selection UI: crbug.com/436280 | 250 // TODO(scheib): Device selection UI: crbug.com/436280 |
| 196 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 251 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
| 197 if (adapter_.get()) { | 252 if (adapter_.get()) { |
| 198 adapter_->StartDiscoverySession( | 253 adapter_->StartDiscoverySessionWithFilter( |
| 254 ComputeScanFilter(filters), |
| 199 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 255 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
| 200 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 256 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 257 base::Passed(make_scoped_ptr(new DiscoverySessionOptions( |
| 258 filters, optional_services)))), |
| 201 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 259 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
| 202 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 260 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 203 } else { | 261 } else { |
| 204 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 262 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; |
| 205 Send(new BluetoothMsg_RequestDeviceError( | 263 Send(new BluetoothMsg_RequestDeviceError( |
| 206 thread_id, request_id, BluetoothError::NOT_FOUND, kNoBluetoothAdapter)); | 264 thread_id, request_id, BluetoothError::NOT_FOUND, kNoBluetoothAdapter)); |
| 207 } | 265 } |
| 208 return; | 266 return; |
| 209 } | 267 } |
| 210 | 268 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 characteristic->ReadRemoteCharacteristic( | 428 characteristic->ReadRemoteCharacteristic( |
| 371 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 429 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, |
| 372 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 430 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
| 373 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 431 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, |
| 374 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 432 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 375 } | 433 } |
| 376 | 434 |
| 377 void BluetoothDispatcherHost::OnDiscoverySessionStarted( | 435 void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
| 378 int thread_id, | 436 int thread_id, |
| 379 int request_id, | 437 int request_id, |
| 438 scoped_ptr<DiscoverySessionOptions> options, |
| 380 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 439 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 381 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 440 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 382 BrowserThread::PostDelayedTask( | 441 BrowserThread::PostDelayedTask( |
| 383 BrowserThread::UI, FROM_HERE, | 442 BrowserThread::UI, FROM_HERE, |
| 384 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, | 443 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, |
| 385 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 444 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 386 base::Passed(&discovery_session)), | 445 base::Passed(&options), base::Passed(&discovery_session)), |
| 387 base::TimeDelta::FromSeconds(current_delay_time_)); | 446 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 388 } | 447 } |
| 389 | 448 |
| 390 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, | 449 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, |
| 391 int request_id) { | 450 int request_id) { |
| 392 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 451 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 393 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; | 452 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; |
| 394 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 453 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 395 BluetoothError::NOT_FOUND, | 454 BluetoothError::NOT_FOUND, |
| 396 kDiscoverySessionStartFailed)); | 455 kDiscoverySessionStartFailed)); |
| 397 } | 456 } |
| 398 | 457 |
| 399 void BluetoothDispatcherHost::StopDiscoverySession( | 458 void BluetoothDispatcherHost::StopDiscoverySession( |
| 400 int thread_id, | 459 int thread_id, |
| 401 int request_id, | 460 int request_id, |
| 461 scoped_ptr<DiscoverySessionOptions> options, |
| 402 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 462 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 403 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 463 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 404 discovery_session->Stop( | 464 discovery_session->Stop( |
| 405 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, | 465 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, |
| 406 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 466 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 467 base::Passed(&options)), |
| 407 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, | 468 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, |
| 408 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 469 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 409 } | 470 } |
| 410 | 471 |
| 411 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 472 void BluetoothDispatcherHost::OnDiscoverySessionStopped( |
| 412 int request_id) { | 473 int thread_id, |
| 474 int request_id, |
| 475 scoped_ptr<DiscoverySessionOptions> options) { |
| 413 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 476 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 414 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 477 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| 415 if (devices.begin() == devices.end()) { | 478 for (device::BluetoothDevice* device : devices) { |
| 416 Send(new BluetoothMsg_RequestDeviceError( | 479 if (MatchesFilters(*device, options->filters)) { |
| 417 thread_id, request_id, BluetoothError::NOT_FOUND, kNoDevicesFound)); | 480 content::BluetoothDevice device_ipc( |
| 418 } else { | 481 device->GetAddress(), // instance_id |
| 419 device::BluetoothDevice* device = *devices.begin(); | 482 device->GetName(), // name |
| 420 content::BluetoothDevice device_ipc( | 483 device->GetBluetoothClass(), // device_class |
| 421 device->GetAddress(), // instance_id | 484 device->GetVendorIDSource(), // vendor_id_source |
| 422 device->GetName(), // name | 485 device->GetVendorID(), // vendor_id |
| 423 device->GetBluetoothClass(), // device_class | 486 device->GetProductID(), // product_id |
| 424 device->GetVendorIDSource(), // vendor_id_source | 487 device->GetDeviceID(), // product_version |
| 425 device->GetVendorID(), // vendor_id | 488 device->IsPaired(), // paired |
| 426 device->GetProductID(), // product_id | 489 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| 427 device->GetDeviceID(), // product_version | 490 device->GetUUIDs())); // uuids |
| 428 device->IsPaired(), // paired | 491 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
| 429 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 492 device_ipc)); |
| 430 device->GetUUIDs())); // uuids | 493 return; |
| 431 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 494 } |
| 432 device_ipc)); | |
| 433 } | 495 } |
| 496 Send(new BluetoothMsg_RequestDeviceError( |
| 497 thread_id, request_id, BluetoothError::NOT_FOUND, kNoDevicesFound)); |
| 434 } | 498 } |
| 435 | 499 |
| 436 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 500 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
| 437 int request_id) { | 501 int request_id) { |
| 438 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 502 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 439 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 503 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
| 440 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 504 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 441 BluetoothError::NOT_FOUND, | 505 BluetoothError::NOT_FOUND, |
| 442 kDiscoverySessionStopFailed)); | 506 kDiscoverySessionStopFailed)); |
| 443 } | 507 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 void BluetoothDispatcherHost::OnCharacteristicReadValueError( | 576 void BluetoothDispatcherHost::OnCharacteristicReadValueError( |
| 513 int thread_id, | 577 int thread_id, |
| 514 int request_id, | 578 int request_id, |
| 515 device::BluetoothGattService::GattErrorCode error_code) { | 579 device::BluetoothGattService::GattErrorCode error_code) { |
| 516 std::pair<BluetoothError, std::string> error = TranslateGATTError(error_code); | 580 std::pair<BluetoothError, std::string> error = TranslateGATTError(error_code); |
| 517 Send(new BluetoothMsg_ReadCharacteristicValueError( | 581 Send(new BluetoothMsg_ReadCharacteristicValueError( |
| 518 thread_id, request_id, error.first, error.second)); | 582 thread_id, request_id, error.first, error.second)); |
| 519 } | 583 } |
| 520 | 584 |
| 521 } // namespace content | 585 } // namespace content |
| OLD | NEW |