Chromium Code Reviews| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 29; // max length of device name in filter. | 54 29; // max length of device name in filter. |
| 55 | 55 |
| 56 // The duration of a Bluetooth Scan in seconds. | 56 // The duration of a Bluetooth Scan in seconds. |
| 57 constexpr int kScanDuration = 10; | 57 constexpr int kScanDuration = 10; |
| 58 constexpr int kTestScanDuration = 0; | 58 constexpr int kTestScanDuration = 0; |
| 59 | 59 |
| 60 void LogRequestDeviceOptions( | 60 void LogRequestDeviceOptions( |
| 61 const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) { | 61 const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) { |
| 62 VLOG(1) << "requestDevice called with the following filters: "; | 62 VLOG(1) << "requestDevice called with the following filters: "; |
| 63 int i = 0; | 63 int i = 0; |
| 64 VLOG(1) << "acceptAllDevices: " << options->accept_all_devices; | |
| 65 | |
| 66 if (options->filters.is_null()) | |
| 67 return; | |
| 68 | |
| 64 for (const auto& filter : options->filters) { | 69 for (const auto& filter : options->filters) { |
| 65 VLOG(1) << "Filter #" << ++i; | 70 VLOG(1) << "Filter #" << ++i; |
| 66 if (!filter->name.is_null()) | 71 if (!filter->name.is_null()) |
| 67 VLOG(1) << "Name: " << filter->name; | 72 VLOG(1) << "Name: " << filter->name; |
| 68 | 73 |
| 69 if (!filter->name_prefix.is_null()) | 74 if (!filter->name_prefix.is_null()) |
| 70 VLOG(1) << "Name Prefix: " << filter->name_prefix; | 75 VLOG(1) << "Name Prefix: " << filter->name_prefix; |
| 71 | 76 |
| 72 if (!filter->services.is_null()) { | 77 if (!filter->services.is_null()) { |
| 73 VLOG(1) << "Services: "; | 78 VLOG(1) << "Services: "; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 94 return true; | 99 return true; |
| 95 if (!filter->name_prefix.is_null() && | 100 if (!filter->name_prefix.is_null() && |
| 96 filter->name_prefix.size() > kMaxLengthForDeviceName) | 101 filter->name_prefix.size() > kMaxLengthForDeviceName) |
| 97 return true; | 102 return true; |
| 98 | 103 |
| 99 return false; | 104 return false; |
| 100 } | 105 } |
| 101 | 106 |
| 102 bool HasEmptyOrInvalidFilter( | 107 bool HasEmptyOrInvalidFilter( |
| 103 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { | 108 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { |
| 109 if (filters.is_null()) { | |
| 110 return true; | |
| 111 } | |
| 112 | |
| 104 return filters.empty() | 113 return filters.empty() |
| 105 ? true | 114 ? true |
| 106 : filters.end() != std::find_if(filters.begin(), filters.end(), | 115 : filters.end() != std::find_if(filters.begin(), filters.end(), |
| 107 IsEmptyOrInvalidFilter); | 116 IsEmptyOrInvalidFilter); |
| 108 } | 117 } |
| 109 | 118 |
| 119 bool IsOptionsInvalid( | |
| 120 const blink::mojom::WebBluetoothRequestDeviceOptionsPtr& options) { | |
| 121 if ((!options->filters.is_null() && options->accept_all_devices) || | |
| 122 (options->filters.is_null() && !options->accept_all_devices)) { | |
|
scheib
2016/11/22 21:22:44
122 is redundant with 125,126 I think. Would this
ortuno
2016/11/23 06:03:08
Nice. Done.
| |
| 123 return true; | |
| 124 } | |
| 125 if (!options->accept_all_devices) { | |
| 126 return HasEmptyOrInvalidFilter(options->filters); | |
| 127 } | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 110 bool MatchesFilter(const std::string* device_name, | 131 bool MatchesFilter(const std::string* device_name, |
| 111 const UUIDSet& device_uuids, | 132 const UUIDSet& device_uuids, |
| 112 const blink::mojom::WebBluetoothScanFilterPtr& filter) { | 133 const blink::mojom::WebBluetoothScanFilterPtr& filter) { |
| 113 if (!filter->name.is_null()) { | 134 if (!filter->name.is_null()) { |
| 114 if (device_name == nullptr) | 135 if (device_name == nullptr) |
| 115 return false; | 136 return false; |
| 116 if (filter->name != *device_name) | 137 if (filter->name != *device_name) |
| 117 return false; | 138 return false; |
| 118 } | 139 } |
| 119 | 140 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 145 if (MatchesFilter(device_name, device_uuids, filter)) { | 166 if (MatchesFilter(device_name, device_uuids, filter)) { |
| 146 return true; | 167 return true; |
| 147 } | 168 } |
| 148 } | 169 } |
| 149 return false; | 170 return false; |
| 150 } | 171 } |
| 151 | 172 |
| 152 std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( | 173 std::unique_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 153 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { | 174 const mojo::Array<blink::mojom::WebBluetoothScanFilterPtr>& filters) { |
| 154 std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services; | 175 std::unordered_set<BluetoothUUID, device::BluetoothUUIDHash> services; |
| 155 for (const auto& filter : filters) { | 176 if (!filters.is_null()) { |
| 156 for (const base::Optional<BluetoothUUID>& service : filter->services) { | 177 for (const auto& filter : filters) { |
| 157 services.insert(service.value()); | 178 for (const base::Optional<BluetoothUUID>& service : filter->services) { |
| 179 services.insert(service.value()); | |
| 180 } | |
| 158 } | 181 } |
| 159 } | 182 } |
| 183 | |
| 160 // There isn't much support for GATT over BR/EDR from neither platforms nor | 184 // There isn't much support for GATT over BR/EDR from neither platforms nor |
| 161 // devices so performing a Dual scan will find devices that the API is not | 185 // devices so performing a Dual scan will find devices that the API is not |
| 162 // able to interact with. To avoid wasting power and confusing users with | 186 // able to interact with. To avoid wasting power and confusing users with |
| 163 // devices they are not able to interact with, we only perform an LE Scan. | 187 // devices they are not able to interact with, we only perform an LE Scan. |
| 164 auto discovery_filter = base::MakeUnique<device::BluetoothDiscoveryFilter>( | 188 auto discovery_filter = base::MakeUnique<device::BluetoothDiscoveryFilter>( |
| 165 device::BLUETOOTH_TRANSPORT_LE); | 189 device::BLUETOOTH_TRANSPORT_LE); |
| 166 for (const BluetoothUUID& service : services) { | 190 for (const BluetoothUUID& service : services) { |
| 167 discovery_filter->AddUUID(service); | 191 discovery_filter->AddUUID(service); |
| 168 } | 192 } |
| 169 return discovery_filter; | 193 return discovery_filter; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 const ErrorCallback& error_callback) { | 268 const ErrorCallback& error_callback) { |
| 245 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 269 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 246 | 270 |
| 247 // GetDevice should only be called once. | 271 // GetDevice should only be called once. |
| 248 DCHECK(success_callback_.is_null()); | 272 DCHECK(success_callback_.is_null()); |
| 249 DCHECK(error_callback_.is_null()); | 273 DCHECK(error_callback_.is_null()); |
| 250 | 274 |
| 251 success_callback_ = success_callback; | 275 success_callback_ = success_callback; |
| 252 error_callback_ = error_callback; | 276 error_callback_ = error_callback; |
| 253 | 277 |
| 254 // The renderer should never send empty filters. | 278 // The renderer should never send invalid options. |
| 255 if (HasEmptyOrInvalidFilter(options->filters)) { | 279 if (IsOptionsInvalid(options)) { |
| 256 web_bluetooth_service_->CrashRendererAndClosePipe( | 280 web_bluetooth_service_->CrashRendererAndClosePipe( |
| 257 bad_message::BDH_EMPTY_OR_INVALID_FILTERS); | 281 bad_message::BDH_INVALID_OPTIONS); |
| 258 return; | 282 return; |
| 259 } | 283 } |
| 260 options_ = std::move(options); | 284 options_ = std::move(options); |
| 261 LogRequestDeviceOptions(options_); | 285 LogRequestDeviceOptions(options_); |
| 262 | 286 |
| 263 // Check blacklist to reject invalid filters and adjust optional_services. | 287 // Check blacklist to reject invalid filters and adjust optional_services. |
| 264 if (BluetoothBlacklist::Get().IsExcluded(options_->filters)) { | 288 if (!options_->filters.is_null() && |
| 289 BluetoothBlacklist::Get().IsExcluded(options_->filters)) { | |
| 265 RecordRequestDeviceOutcome( | 290 RecordRequestDeviceOutcome( |
| 266 UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER); | 291 UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER); |
| 267 PostErrorCallback( | 292 PostErrorCallback( |
| 268 blink::mojom::WebBluetoothResult::REQUEST_DEVICE_WITH_BLACKLISTED_UUID); | 293 blink::mojom::WebBluetoothResult::REQUEST_DEVICE_WITH_BLACKLISTED_UUID); |
| 269 return; | 294 return; |
| 270 } | 295 } |
| 271 BluetoothBlacklist::Get().RemoveExcludedUUIDs(options_.get()); | 296 BluetoothBlacklist::Get().RemoveExcludedUUIDs(options_.get()); |
| 272 | 297 |
| 273 const url::Origin requesting_origin = | 298 const url::Origin requesting_origin = |
| 274 render_frame_host_->GetLastCommittedOrigin(); | 299 render_frame_host_->GetLastCommittedOrigin(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 BluetoothChooser::AdapterPresence::POWERED_OFF); | 380 BluetoothChooser::AdapterPresence::POWERED_OFF); |
| 356 return; | 381 return; |
| 357 } | 382 } |
| 358 | 383 |
| 359 StartDeviceDiscovery(); | 384 StartDeviceDiscovery(); |
| 360 } | 385 } |
| 361 | 386 |
| 362 void BluetoothDeviceChooserController::AddFilteredDevice( | 387 void BluetoothDeviceChooserController::AddFilteredDevice( |
| 363 const device::BluetoothDevice& device) { | 388 const device::BluetoothDevice& device) { |
| 364 base::Optional<std::string> device_name = device.GetName(); | 389 base::Optional<std::string> device_name = device.GetName(); |
| 365 if (chooser_.get() && | 390 if (chooser_.get()) { |
| 366 MatchesFilters(device_name ? &device_name.value() : nullptr, | 391 if (options_->accept_all_devices || |
| 367 device.GetUUIDs(), options_->filters)) { | 392 MatchesFilters(device_name ? &device_name.value() : nullptr, |
| 368 base::Optional<int8_t> rssi = device.GetInquiryRSSI(); | 393 device.GetUUIDs(), options_->filters)) { |
| 369 chooser_->AddOrUpdateDevice( | 394 base::Optional<int8_t> rssi = device.GetInquiryRSSI(); |
| 370 device.GetAddress(), !!device.GetName() /* should_update_name */, | 395 chooser_->AddOrUpdateDevice( |
| 371 device.GetNameForDisplay(), device.IsGattConnected(), | 396 device.GetAddress(), !!device.GetName() /* should_update_name */, |
| 372 web_bluetooth_service_->IsDevicePaired(device.GetAddress()), | 397 device.GetNameForDisplay(), device.IsGattConnected(), |
| 373 rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1); | 398 web_bluetooth_service_->IsDevicePaired(device.GetAddress()), |
| 399 rssi ? CalculateSignalStrengthLevel(rssi.value()) : -1); | |
| 400 } | |
| 374 } | 401 } |
| 375 } | 402 } |
| 376 | 403 |
| 377 void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) { | 404 void BluetoothDeviceChooserController::AdapterPoweredChanged(bool powered) { |
| 378 if (!powered && discovery_session_.get()) { | 405 if (!powered && discovery_session_.get()) { |
| 379 StopDiscoverySession(std::move(discovery_session_)); | 406 StopDiscoverySession(std::move(discovery_session_)); |
| 380 } | 407 } |
| 381 | 408 |
| 382 if (chooser_.get()) { | 409 if (chooser_.get()) { |
| 383 chooser_->SetAdapterPresence( | 410 chooser_->SetAdapterPresence( |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 | 562 |
| 536 void BluetoothDeviceChooserController::PostErrorCallback( | 563 void BluetoothDeviceChooserController::PostErrorCallback( |
| 537 blink::mojom::WebBluetoothResult error) { | 564 blink::mojom::WebBluetoothResult error) { |
| 538 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( | 565 if (!base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 539 FROM_HERE, base::Bind(error_callback_, error))) { | 566 FROM_HERE, base::Bind(error_callback_, error))) { |
| 540 LOG(WARNING) << "No TaskRunner."; | 567 LOG(WARNING) << "No TaskRunner."; |
| 541 } | 568 } |
| 542 } | 569 } |
| 543 | 570 |
| 544 } // namespace content | 571 } // namespace content |
| OLD | NEW |