| 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 current_delay_time_ = kTestingDelayTime; | 173 current_delay_time_ = kTestingDelayTime; |
| 173 set_adapter(mock_adapter.Pass()); | 174 set_adapter(mock_adapter.Pass()); |
| 174 } | 175 } |
| 175 | 176 |
| 176 BluetoothDispatcherHost::~BluetoothDispatcherHost() { | 177 BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 178 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 178 // Clear adapter, releasing observer references. | 179 // Clear adapter, releasing observer references. |
| 179 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 180 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| 180 } | 181 } |
| 181 | 182 |
| 183 struct BluetoothDispatcherHost::DiscoverySessionOptions { |
| 184 DiscoverySessionOptions(const std::vector<BluetoothScanFilter>& filters, |
| 185 const std::vector<BluetoothUUID>& optional_services) |
| 186 : filters(filters), optional_services(optional_services) {} |
| 187 |
| 188 std::vector<BluetoothScanFilter> filters; |
| 189 std::vector<BluetoothUUID> optional_services; |
| 190 }; |
| 191 |
| 182 void BluetoothDispatcherHost::set_adapter( | 192 void BluetoothDispatcherHost::set_adapter( |
| 183 scoped_refptr<device::BluetoothAdapter> adapter) { | 193 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 184 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 194 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 185 if (adapter_.get()) | 195 if (adapter_.get()) |
| 186 adapter_->RemoveObserver(this); | 196 adapter_->RemoveObserver(this); |
| 187 adapter_ = adapter; | 197 adapter_ = adapter; |
| 188 if (adapter_.get()) | 198 if (adapter_.get()) |
| 189 adapter_->AddObserver(this); | 199 adapter_->AddObserver(this); |
| 190 } | 200 } |
| 191 | 201 |
| 192 void BluetoothDispatcherHost::OnRequestDevice(int thread_id, int request_id) { | 202 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 203 const std::vector<BluetoothScanFilter>& filters) { |
| 204 std::set<BluetoothUUID> services; |
| 205 for (const BluetoothScanFilter& filter : filters) { |
| 206 services.insert(filter.services.begin(), filter.services.end()); |
| 207 } |
| 208 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( |
| 209 new device::BluetoothDiscoveryFilter( |
| 210 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); |
| 211 for (const BluetoothUUID& service : services) { |
| 212 discovery_filter->AddUUID(service); |
| 213 } |
| 214 return discovery_filter.Pass(); |
| 215 } |
| 216 |
| 217 void BluetoothDispatcherHost::OnRequestDevice( |
| 218 int thread_id, |
| 219 int request_id, |
| 220 const std::vector<BluetoothScanFilter>& filters, |
| 221 const std::vector<BluetoothUUID>& optional_services) { |
| 193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 222 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 | 223 // TODO(scheib): Device selection UI: crbug.com/436280 |
| 196 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 224 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
| 197 if (adapter_.get()) { | 225 if (adapter_.get()) { |
| 198 adapter_->StartDiscoverySession( | 226 adapter_->StartDiscoverySessionWithFilter( |
| 227 ComputeScanFilter(filters), |
| 199 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 228 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
| 200 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 229 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 230 base::Passed(make_scoped_ptr(new DiscoverySessionOptions( |
| 231 filters, optional_services)))), |
| 201 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 232 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
| 202 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 233 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 203 } else { | 234 } else { |
| 204 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 235 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; |
| 205 Send(new BluetoothMsg_RequestDeviceError( | 236 Send(new BluetoothMsg_RequestDeviceError( |
| 206 thread_id, request_id, BluetoothError::NOT_FOUND, kNoBluetoothAdapter)); | 237 thread_id, request_id, BluetoothError::NOT_FOUND, kNoBluetoothAdapter)); |
| 207 } | 238 } |
| 208 return; | 239 return; |
| 209 } | 240 } |
| 210 | 241 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 characteristic->ReadRemoteCharacteristic( | 401 characteristic->ReadRemoteCharacteristic( |
| 371 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 402 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, |
| 372 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 403 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
| 373 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 404 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, |
| 374 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 405 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 375 } | 406 } |
| 376 | 407 |
| 377 void BluetoothDispatcherHost::OnDiscoverySessionStarted( | 408 void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
| 378 int thread_id, | 409 int thread_id, |
| 379 int request_id, | 410 int request_id, |
| 411 scoped_ptr<DiscoverySessionOptions> options, |
| 380 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 412 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 381 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 413 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 382 BrowserThread::PostDelayedTask( | 414 BrowserThread::PostDelayedTask( |
| 383 BrowserThread::UI, FROM_HERE, | 415 BrowserThread::UI, FROM_HERE, |
| 384 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, | 416 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, |
| 385 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 417 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 386 base::Passed(&discovery_session)), | 418 base::Passed(&options), base::Passed(&discovery_session)), |
| 387 base::TimeDelta::FromSeconds(current_delay_time_)); | 419 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 388 } | 420 } |
| 389 | 421 |
| 390 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, | 422 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, |
| 391 int request_id) { | 423 int request_id) { |
| 392 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 424 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 393 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; | 425 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; |
| 394 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 426 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 395 BluetoothError::NOT_FOUND, | 427 BluetoothError::NOT_FOUND, |
| 396 kDiscoverySessionStartFailed)); | 428 kDiscoverySessionStartFailed)); |
| 397 } | 429 } |
| 398 | 430 |
| 399 void BluetoothDispatcherHost::StopDiscoverySession( | 431 void BluetoothDispatcherHost::StopDiscoverySession( |
| 400 int thread_id, | 432 int thread_id, |
| 401 int request_id, | 433 int request_id, |
| 434 scoped_ptr<DiscoverySessionOptions> options, |
| 402 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 435 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 403 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 436 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 404 discovery_session->Stop( | 437 discovery_session->Stop( |
| 405 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, | 438 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, |
| 406 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 439 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 440 base::Passed(&options)), |
| 407 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, | 441 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, |
| 408 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 442 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 409 } | 443 } |
| 410 | 444 |
| 411 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 445 // Defined at |
| 412 int request_id) { | 446 // https://webbluetoothcg.github.io/web-bluetooth/#dfn-matches-a-filter |
| 447 static bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
| 448 const BluetoothScanFilter& filter) { |
| 449 if (filter.services.empty()) |
| 450 return false; |
| 451 for (const BluetoothUUID& service : filter.services) { |
| 452 if (!ContainsKey(device_uuids, service)) { |
| 453 return false; |
| 454 } |
| 455 } |
| 456 return true; |
| 457 } |
| 458 |
| 459 static bool MatchesFilters(const device::BluetoothDevice& device, |
| 460 const std::vector<BluetoothScanFilter>& filters) { |
| 461 const std::vector<BluetoothUUID>& device_uuid_list = device.GetUUIDs(); |
| 462 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), |
| 463 device_uuid_list.end()); |
| 464 for (const BluetoothScanFilter& filter : filters) { |
| 465 if (MatchesFilter(device_uuids, filter)) { |
| 466 return true; |
| 467 } |
| 468 } |
| 469 return false; |
| 470 } |
| 471 void BluetoothDispatcherHost::OnDiscoverySessionStopped( |
| 472 int thread_id, |
| 473 int request_id, |
| 474 scoped_ptr<DiscoverySessionOptions> options) { |
| 413 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 475 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 414 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 476 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| 415 if (devices.begin() == devices.end()) { | 477 for (device::BluetoothDevice* device : devices) { |
| 416 Send(new BluetoothMsg_RequestDeviceError( | 478 if (MatchesFilters(*device, options->filters)) { |
| 417 thread_id, request_id, BluetoothError::NOT_FOUND, kNoDevicesFound)); | 479 content::BluetoothDevice device_ipc( |
| 418 } else { | 480 device->GetAddress(), // instance_id |
| 419 device::BluetoothDevice* device = *devices.begin(); | 481 device->GetName(), // name |
| 420 content::BluetoothDevice device_ipc( | 482 device->GetBluetoothClass(), // device_class |
| 421 device->GetAddress(), // instance_id | 483 device->GetVendorIDSource(), // vendor_id_source |
| 422 device->GetName(), // name | 484 device->GetVendorID(), // vendor_id |
| 423 device->GetBluetoothClass(), // device_class | 485 device->GetProductID(), // product_id |
| 424 device->GetVendorIDSource(), // vendor_id_source | 486 device->GetDeviceID(), // product_version |
| 425 device->GetVendorID(), // vendor_id | 487 device->IsPaired(), // paired |
| 426 device->GetProductID(), // product_id | 488 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| 427 device->GetDeviceID(), // product_version | 489 device->GetUUIDs())); // uuids |
| 428 device->IsPaired(), // paired | 490 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
| 429 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 491 device_ipc)); |
| 430 device->GetUUIDs())); // uuids | 492 return; |
| 431 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 493 } |
| 432 device_ipc)); | |
| 433 } | 494 } |
| 495 Send(new BluetoothMsg_RequestDeviceError( |
| 496 thread_id, request_id, BluetoothError::NOT_FOUND, kNoDevicesFound)); |
| 434 } | 497 } |
| 435 | 498 |
| 436 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 499 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
| 437 int request_id) { | 500 int request_id) { |
| 438 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 501 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 439 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 502 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
| 440 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 503 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 441 BluetoothError::NOT_FOUND, | 504 BluetoothError::NOT_FOUND, |
| 442 kDiscoverySessionStopFailed)); | 505 kDiscoverySessionStopFailed)); |
| 443 } | 506 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 void BluetoothDispatcherHost::OnCharacteristicReadValueError( | 575 void BluetoothDispatcherHost::OnCharacteristicReadValueError( |
| 513 int thread_id, | 576 int thread_id, |
| 514 int request_id, | 577 int request_id, |
| 515 device::BluetoothGattService::GattErrorCode error_code) { | 578 device::BluetoothGattService::GattErrorCode error_code) { |
| 516 std::pair<BluetoothError, std::string> error = TranslateGATTError(error_code); | 579 std::pair<BluetoothError, std::string> error = TranslateGATTError(error_code); |
| 517 Send(new BluetoothMsg_ReadCharacteristicValueError( | 580 Send(new BluetoothMsg_ReadCharacteristicValueError( |
| 518 thread_id, request_id, error.first, error.second)); | 581 thread_id, request_id, error.first, error.second)); |
| 519 } | 582 } |
| 520 | 583 |
| 521 } // namespace content | 584 } // namespace content |
| OLD | NEW |