| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #include "content/browser/bluetooth/bluetooth_device_chooser_controller.h" | 5 #include "content/browser/bluetooth/bluetooth_device_chooser_controller.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <unordered_set> | 9 #include <unordered_set> |
| 10 | 10 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 // The duration of a Bluetooth Scan in seconds. | 57 // The duration of a Bluetooth Scan in seconds. |
| 58 constexpr int kScanDuration = 60; | 58 constexpr int kScanDuration = 60; |
| 59 constexpr int kTestScanDuration = 0; | 59 constexpr int kTestScanDuration = 0; |
| 60 | 60 |
| 61 void LogRequestDeviceOptions( | 61 void LogRequestDeviceOptions( |
| 62 const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) { | 62 const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) { |
| 63 VLOG(1) << "requestDevice called with the following filters: "; | 63 VLOG(1) << "requestDevice called with the following filters: "; |
| 64 int i = 0; | 64 int i = 0; |
| 65 for (const auto& filter : options->filters) { | 65 for (const auto& filter : options->filters) { |
| 66 VLOG(1) << "Filter #" << ++i; | 66 VLOG(1) << "Filter #" << ++i; |
| 67 if (!filter->name.is_null()) | 67 if (filter->name) |
| 68 VLOG(1) << "Name: " << filter->name; | 68 VLOG(1) << "Name: " << filter->name.value(); |
| 69 | 69 |
| 70 if (!filter->name_prefix.is_null()) | 70 if (filter->name_prefix) |
| 71 VLOG(1) << "Name Prefix: " << filter->name_prefix; | 71 VLOG(1) << "Name Prefix: " << filter->name_prefix.value(); |
| 72 | 72 |
| 73 if (!filter->services.is_null()) { | 73 if (filter->services) { |
| 74 VLOG(1) << "Services: "; | 74 VLOG(1) << "Services: "; |
| 75 VLOG(1) << "\t["; | 75 VLOG(1) << "\t["; |
| 76 for (const auto& service : filter->services) | 76 for (const auto& service : filter->services.value()) |
| 77 VLOG(1) << "\t\t" << service->canonical_value(); | 77 VLOG(1) << "\t\t" << service.canonical_value(); |
| 78 VLOG(1) << "\t]"; | 78 VLOG(1) << "\t]"; |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 bool IsEmptyOrInvalidFilter( | 83 bool IsEmptyOrInvalidFilter( |
| 84 const blink::mojom::WebBluetoothScanFilterPtr& filter) { | 84 const blink::mojom::WebBluetoothScanFilterPtr& filter) { |
| 85 // At least one member needs to be present. | 85 // At least one member needs to be present. |
| 86 if (filter->name.is_null() && filter->name_prefix.is_null() && | 86 if (!filter->name && !filter->name_prefix && !filter->services) |
| 87 filter->services.is_null()) | |
| 88 return true; | 87 return true; |
| 89 | 88 |
| 90 // The renderer will never send a name or a name_prefix longer than | 89 // The renderer will never send a name or a name_prefix longer than |
| 91 // kMaxLengthForDeviceName. | 90 // kMaxLengthForDeviceName. |
| 92 if (!filter->name.is_null() && filter->name.size() > kMaxLengthForDeviceName) | 91 if (filter->name && filter->name->size() > kMaxLengthForDeviceName) |
| 93 return true; | 92 return true; |
| 94 if (!filter->name_prefix.is_null() && filter->name_prefix.size() == 0) | 93 if (filter->name_prefix && filter->name_prefix->size() == 0) |
| 95 return true; | 94 return true; |
| 96 if (!filter->name_prefix.is_null() && | 95 if (filter->name_prefix && |
| 97 filter->name_prefix.size() > kMaxLengthForDeviceName) | 96 filter->name_prefix->size() > kMaxLengthForDeviceName) |
| 98 return true; | 97 return true; |
| 99 | 98 |
| 100 return false; | 99 return false; |
| 101 } | 100 } |
| 102 | 101 |
| 103 bool HasEmptyOrInvalidFilter( | 102 bool HasEmptyOrInvalidFilter( |
| 104 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { | 103 const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) { |
| 105 return filters.empty() | 104 return filters.empty() |
| 106 ? true | 105 ? true |
| 107 : filters.end() != std::find_if(filters.begin(), filters.end(), | 106 : filters.end() != std::find_if(filters.begin(), filters.end(), |
| 108 IsEmptyOrInvalidFilter); | 107 IsEmptyOrInvalidFilter); |
| 109 } | 108 } |
| 110 | 109 |
| 111 bool MatchesFilter(const std::string* device_name, | 110 bool MatchesFilter(const std::string* device_name, |
| 112 const UUIDSet& device_uuids, | 111 const UUIDSet& device_uuids, |
| 113 const blink::mojom::WebBluetoothScanFilterPtr& filter) { | 112 const blink::mojom::WebBluetoothScanFilterPtr& filter) { |
| 114 if (!filter->name.is_null()) { | 113 if (filter->name) { |
| 115 if (device_name == nullptr) | 114 if (device_name == nullptr) |
| 116 return false; | 115 return false; |
| 117 if (filter->name != *device_name) | 116 if (filter->name.value() != *device_name) |
| 118 return false; | 117 return false; |
| 119 } | 118 } |
| 120 | 119 |
| 121 if (!filter->name_prefix.is_null() && filter->name_prefix.size()) { | 120 if (filter->name_prefix && filter->name_prefix->size()) { |
| 122 if (device_name == nullptr) | 121 if (device_name == nullptr) |
| 123 return false; | 122 return false; |
| 124 if (!base::StartsWith(*device_name, filter->name_prefix.get(), | 123 if (!base::StartsWith(*device_name, filter->name_prefix.value(), |
| 125 base::CompareCase::SENSITIVE)) | 124 base::CompareCase::SENSITIVE)) |
| 126 return false; | 125 return false; |
| 127 } | 126 } |
| 128 | 127 |
| 129 if (!filter->services.is_null()) { | 128 if (filter->services) { |
| 130 for (const base::Optional<BluetoothUUID>& service : filter->services) { | 129 for (const auto& service : filter->services.value()) { |
| 131 if (!base::ContainsKey(device_uuids, service.value())) { | 130 if (!base::ContainsKey(device_uuids, service)) |
| 132 return false; | 131 return false; |
| 133 } | |
| 134 } | 132 } |
| 135 } | 133 } |
| 136 | 134 |
| 137 return true; | 135 return true; |
| 138 } | 136 } |
| 139 | 137 |
| 140 bool MatchesFilters( | 138 bool MatchesFilters( |
| 141 const std::string* device_name, | 139 const std::string* device_name, |
| 142 const UUIDSet& device_uuids, | 140 const UUIDSet& device_uuids, |
| 143 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { | 141 const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) { |
| 144 DCHECK(!HasEmptyOrInvalidFilter(filters)); | 142 DCHECK(!HasEmptyOrInvalidFilter(filters)); |
| 145 for (const auto& filter : filters) { | 143 for (const auto& filter : filters) { |
| 146 if (MatchesFilter(device_name, device_uuids, filter)) { | 144 if (MatchesFilter(device_name, device_uuids, filter)) |
| 147 return true; | 145 return true; |
| 148 } | |
| 149 } | 146 } |
| 150 return false; | 147 return false; |
| 151 } | 148 } |
| 152 | 149 |
| 153 std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( | 150 std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 154 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { | 151 const std::vector<blink::mojom::WebBluetoothScanFilterPtr>& filters) { |
| 155 std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services; | 152 std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services; |
| 156 for (const auto& filter : filters) { | 153 for (const auto& filter : filters) { |
| 157 for (const base::Optional<BluetoothUUID>& service : filter->services) { | 154 if (!filter->services) |
| 158 services.insert(service.value()); | 155 continue; |
| 159 } | 156 for (const auto& service : filter->services.value()) |
| 157 services.insert(service); |
| 160 } | 158 } |
| 161 // There isn't much support for GATT over BR/EDR from neither platforms nor | 159 // There isn't much support for GATT over BR/EDR from neither platforms nor |
| 162 // devices so performing a Dual scan will find devices that the API is not | 160 // devices so performing a Dual scan will find devices that the API is not |
| 163 // able to interact with. To avoid wasting power and confusing users with | 161 // able to interact with. To avoid wasting power and confusing users with |
| 164 // devices they are not able to interact with, we only perform an LE Scan. | 162 // devices they are not able to interact with, we only perform an LE Scan. |
| 165 auto discovery_filter = base::MakeUnique<device::BluetoothDiscoveryFilter>( | 163 auto discovery_filter = base::MakeUnique<device::BluetoothDiscoveryFilter>( |
| 166 device::BLUETOOTH_TRANSPORT_LE); | 164 device::BLUETOOTH_TRANSPORT_LE); |
| 167 for (const BluetoothUUID& service : services) { | 165 for (const BluetoothUUID& service : services) |
| 168 discovery_filter->AddUUID(service); | 166 discovery_filter->AddUUID(service); |
| 169 } | |
| 170 return discovery_filter; | 167 return discovery_filter; |
| 171 } | 168 } |
| 172 | 169 |
| 173 void StopDiscoverySession( | 170 void StopDiscoverySession( |
| 174 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { | 171 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 175 // Nothing goes wrong if the discovery session fails to stop, and we don't | 172 // Nothing goes wrong if the discovery session fails to stop, and we don't |
| 176 // need to wait for it before letting the user's script proceed, so we ignore | 173 // need to wait for it before letting the user's script proceed, so we ignore |
| 177 // the results here. | 174 // the results here. |
| 178 discovery_session->Stop(base::Bind(&base::DoNothing), | 175 discovery_session->Stop(base::Bind(&base::DoNothing), |
| 179 base::Bind(&base::DoNothing)); | 176 base::Bind(&base::DoNothing)); |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 base::Optional<int8_t> rssi = device.GetInquiryRSSI(); | 373 base::Optional<int8_t> rssi = device.GetInquiryRSSI(); |
| 377 chooser_->AddOrUpdateDevice( | 374 chooser_->AddOrUpdateDevice( |
| 378 device.GetAddress(), !!device.GetName() /* should_update_name */, | 375 device.GetAddress(), !!device.GetName() /* should_update_name */, |
| 379 device.GetNameForDisplay(), device.IsGattConnected(), | 376 device.GetNameForDisplay(), device.IsGattConnected(), |
| 380 web_bluetooth_service_->IsDevicePaired(device.GetAddress()), | 377 web_bluetooth_service_->IsDevicePaired(device.GetAddress()), |
| 381 rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1); | 378 rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1); |
| 382 } | 379 } |
| 383 } | 380 } |
| 384 | 381 |
| 385 void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) { | 382 void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) { |
| 386 if (!powered && discovery_session_.get()) { | 383 if (!powered && discovery_session_.get()) |
| 387 StopDiscoverySession(std::move(discovery_session_)); | 384 StopDiscoverySession(std::move(discovery_session_)); |
| 388 } | |
| 389 | 385 |
| 390 if (chooser_.get()) { | 386 if (chooser_.get()) { |
| 391 chooser_->SetAdapterPresence( | 387 chooser_->SetAdapterPresence( |
| 392 powered ? BluetoothChooser::AdapterPresence::POWERED_ON | 388 powered ? BluetoothChooser::AdapterPresence::POWERED_ON |
| 393 : BluetoothChooser::AdapterPresence::POWERED_OFF); | 389 : BluetoothChooser::AdapterPresence::POWERED_OFF); |
| 394 if (powered) { | 390 if (powered) { |
| 395 OnBluetoothChooserEvent(BluetoothChooser::Event::RESCAN, | 391 OnBluetoothChooserEvent(BluetoothChooser::Event::RESCAN, |
| 396 "" /* device_address */); | 392 "" /* device_address */); |
| 397 } | 393 } |
| 398 } | 394 } |
| 399 | 395 |
| 400 if (!powered) { | 396 if (!powered) |
| 401 discovery_session_timer_.Stop(); | 397 discovery_session_timer_.Stop(); |
| 402 } | |
| 403 } | 398 } |
| 404 | 399 |
| 405 int BluetoothDeviceChooserController::CalculateSignalStrengthLevel( | 400 int BluetoothDeviceChooserController::CalculateSignalStrengthLevel( |
| 406 int8_t rssi) { | 401 int8_t rssi) { |
| 407 RecordRSSISignalStrength(rssi); | 402 RecordRSSISignalStrength(rssi); |
| 408 | 403 |
| 409 if (rssi <= kMinRSSI) { | 404 if (rssi <= kMinRSSI) { |
| 410 RecordRSSISignalStrengthLevel( | 405 RecordRSSISignalStrengthLevel( |
| 411 UMARSSISignalStrengthLevel::LESS_THAN_OR_EQUAL_TO_MIN_RSSI); | 406 UMARSSISignalStrengthLevel::LESS_THAN_OR_EQUAL_TO_MIN_RSSI); |
| 412 return 0; | 407 return 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 425 RecordRSSISignalStrengthLevel(kRSSISignalStrengthEnumTable[level]); | 420 RecordRSSISignalStrengthLevel(kRSSISignalStrengthEnumTable[level]); |
| 426 return level; | 421 return level; |
| 427 } | 422 } |
| 428 | 423 |
| 429 void BluetoothDeviceChooserController::SetTestScanDurationForTesting() { | 424 void BluetoothDeviceChooserController::SetTestScanDurationForTesting() { |
| 430 BluetoothDeviceChooserController::use_test_scan_duration_ = true; | 425 BluetoothDeviceChooserController::use_test_scan_duration_ = true; |
| 431 } | 426 } |
| 432 | 427 |
| 433 void BluetoothDeviceChooserController::PopulateConnectedDevices() { | 428 void BluetoothDeviceChooserController::PopulateConnectedDevices() { |
| 434 for (const device::BluetoothDevice* device : adapter_->GetDevices()) { | 429 for (const device::BluetoothDevice* device : adapter_->GetDevices()) { |
| 435 if (device->IsGattConnected()) { | 430 if (device->IsGattConnected()) |
| 436 AddFilteredDevice(*device); | 431 AddFilteredDevice(*device); |
| 437 } | |
| 438 } | 432 } |
| 439 } | 433 } |
| 440 | 434 |
| 441 void BluetoothDeviceChooserController::StartDeviceDiscovery() { | 435 void BluetoothDeviceChooserController::StartDeviceDiscovery() { |
| 442 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 436 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 443 | 437 |
| 444 if (discovery_session_.get() && discovery_session_->IsActive()) { | 438 if (discovery_session_.get() && discovery_session_->IsActive()) { |
| 445 // Already running; just increase the timeout. | 439 // Already running; just increase the timeout. |
| 446 discovery_session_timer_.Reset(); | 440 discovery_session_timer_.Reset(); |
| 447 return; | 441 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 463 void BluetoothDeviceChooserController::StopDeviceDiscovery() { | 457 void BluetoothDeviceChooserController::StopDeviceDiscovery() { |
| 464 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 458 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 465 | 459 |
| 466 if (scanning_start_time_) { | 460 if (scanning_start_time_) { |
| 467 RecordScanningDuration(base::TimeTicks::Now() - | 461 RecordScanningDuration(base::TimeTicks::Now() - |
| 468 scanning_start_time_.value()); | 462 scanning_start_time_.value()); |
| 469 scanning_start_time_.reset(); | 463 scanning_start_time_.reset(); |
| 470 } | 464 } |
| 471 | 465 |
| 472 StopDiscoverySession(std::move(discovery_session_)); | 466 StopDiscoverySession(std::move(discovery_session_)); |
| 473 if (chooser_) { | 467 if (chooser_) |
| 474 chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::IDLE); | 468 chooser_->ShowDiscoveryState(BluetoothChooser::DiscoveryState::IDLE); |
| 475 } | |
| 476 } | 469 } |
| 477 | 470 |
| 478 void BluetoothDeviceChooserController::OnStartDiscoverySessionSuccess( | 471 void BluetoothDeviceChooserController::OnStartDiscoverySessionSuccess( |
| 479 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { | 472 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 480 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 473 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 481 VLOG(1) << "Started discovery session."; | 474 VLOG(1) << "Started discovery session."; |
| 482 if (chooser_.get()) { | 475 if (chooser_.get()) { |
| 483 discovery_session_ = std::move(discovery_session); | 476 discovery_session_ = std::move(discovery_session); |
| 484 discovery_session_timer_.Reset(); | 477 discovery_session_timer_.Reset(); |
| 485 } else { | 478 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 | 548 |
| 556 void BluetoothDeviceChooserController::PostErrorCallback( | 549 void BluetoothDeviceChooserController::PostErrorCallback( |
| 557 blink::mojom::WebBluetoothResult error) { | 550 blink::mojom::WebBluetoothResult error) { |
| 558 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( | 551 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 559 FROM_HERE, base::Bind(error_callback_, error))) { | 552 FROM_HERE, base::Bind(error_callback_, error))) { |
| 560 LOG(WARNING) << "No TaskRunner."; | 553 LOG(WARNING) << "No TaskRunner."; |
| 561 } | 554 } |
| 562 } | 555 } |
| 563 | 556 |
| 564 } // namespace content | 557 } // namespace content |
| OLD | NEW |