From 10c556935fb276ce7d1ebcb526882b986956d91e Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:23:31 +0000 Subject: [PATCH 1/2] feat(serial): allow Bluetooth ports to be requested by service class ID Co-authored-by: Shelley Vohr --- .../serial/electron_serial_delegate.cc | 10 ++- .../browser/serial/electron_serial_delegate.h | 1 + .../serial/serial_chooser_controller.cc | 74 +++++++++++++++---- .../serial/serial_chooser_controller.h | 4 +- 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/shell/browser/serial/electron_serial_delegate.cc b/shell/browser/serial/electron_serial_delegate.cc index f82c81dbfd5d3..e7b9e551fe1d5 100644 --- a/shell/browser/serial/electron_serial_delegate.cc +++ b/shell/browser/serial/electron_serial_delegate.cc @@ -35,7 +35,9 @@ std::unique_ptr ElectronSerialDelegate::RunChooser( if (controller) { DeleteControllerForFrame(frame); } - AddControllerForFrame(frame, std::move(filters), std::move(callback)); + AddControllerForFrame(frame, std::move(filters), + std::move(allowed_bluetooth_service_class_ids), + std::move(callback)); // Return a nullptr because the return value isn't used for anything, eg // there is no mechanism to cancel navigator.serial.requestPort(). The return @@ -106,12 +108,14 @@ SerialChooserController* ElectronSerialDelegate::ControllerForFrame( SerialChooserController* ElectronSerialDelegate::AddControllerForFrame( content::RenderFrameHost* render_frame_host, std::vector filters, + std::vector allowed_bluetooth_service_class_ids, content::SerialChooser::Callback callback) { auto* web_contents = content::WebContents::FromRenderFrameHost(render_frame_host); auto controller = std::make_unique( - render_frame_host, std::move(filters), std::move(callback), web_contents, - weak_factory_.GetWeakPtr()); + render_frame_host, std::move(filters), + std::move(allowed_bluetooth_service_class_ids), std::move(callback), + web_contents, weak_factory_.GetWeakPtr()); controller_map_.insert( std::make_pair(render_frame_host, std::move(controller))); return ControllerForFrame(render_frame_host); diff --git a/shell/browser/serial/electron_serial_delegate.h b/shell/browser/serial/electron_serial_delegate.h index 5b7f38591af5c..72af94d5c2f01 100644 --- a/shell/browser/serial/electron_serial_delegate.h +++ b/shell/browser/serial/electron_serial_delegate.h @@ -65,6 +65,7 @@ class ElectronSerialDelegate : public content::SerialDelegate, SerialChooserController* AddControllerForFrame( content::RenderFrameHost* render_frame_host, std::vector filters, + std::vector allowed_bluetooth_service_class_ids, content::SerialChooser::Callback callback); base::ScopedObservation { namespace electron { +namespace { + +using ::device::mojom::SerialPortType; + +bool FilterMatchesPort(const blink::mojom::SerialPortFilter& filter, + const device::mojom::SerialPortInfo& port) { + if (filter.bluetooth_service_class_id) { + if (!port.bluetooth_service_class_id) { + return false; + } + return device::BluetoothUUID(*port.bluetooth_service_class_id) == + device::BluetoothUUID(*filter.bluetooth_service_class_id); + } + if (!filter.has_vendor_id) { + return true; + } + if (!port.has_vendor_id || port.vendor_id != filter.vendor_id) { + return false; + } + if (!filter.has_product_id) { + return true; + } + return port.has_product_id && port.product_id == filter.product_id; +} + +bool BluetoothPortIsAllowed( + const std::vector<::device::BluetoothUUID>& allowed_ids, + const device::mojom::SerialPortInfo& port) { + if (!port.bluetooth_service_class_id) { + return true; + } + // Serial Port Profile is allowed by default. + if (*port.bluetooth_service_class_id == device::GetSerialPortProfileUUID()) { + return true; + } + return base::Contains(allowed_ids, port.bluetooth_service_class_id.value()); +} + +} // namespace + SerialChooserController::SerialChooserController( content::RenderFrameHost* render_frame_host, std::vector filters, + std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids, content::SerialChooser::Callback callback, content::WebContents* web_contents, base::WeakPtr serial_delegate) : WebContentsObserver(web_contents), filters_(std::move(filters)), + allowed_bluetooth_service_class_ids_( + std::move(allowed_bluetooth_service_class_ids)), callback_(std::move(callback)), serial_delegate_(serial_delegate), render_frame_host_id_(render_frame_host->GetGlobalId()) { @@ -93,10 +139,11 @@ api::Session* SerialChooserController::GetSession() { void SerialChooserController::OnPortAdded( const device::mojom::SerialPortInfo& port) { - if (!FilterMatchesAny(port)) + if (!DisplayDevice(port)) return; ports_.push_back(port.Clone()); + api::Session* session = GetSession(); if (session) { session->Emit("serial-port-added", port.Clone(), web_contents()); @@ -105,9 +152,8 @@ void SerialChooserController::OnPortAdded( void SerialChooserController::OnPortRemoved( const device::mojom::SerialPortInfo& port) { - const auto it = std::find_if( - ports_.begin(), ports_.end(), - [&port](const auto& ptr) { return ptr->token == port.token; }); + const auto it = base::ranges::find(ports_, port.token, + &device::mojom::SerialPortInfo::token); if (it != ports_.end()) { api::Session* session = GetSession(); if (session) { @@ -152,7 +198,7 @@ void SerialChooserController::OnGetDevices( }); for (auto& port : ports) { - if (FilterMatchesAny(*port)) + if (DisplayDevice(*port)) ports_.push_back(std::move(port)); } @@ -169,21 +215,17 @@ void SerialChooserController::OnGetDevices( } } -bool SerialChooserController::FilterMatchesAny( +bool SerialChooserController::DisplayDevice( const device::mojom::SerialPortInfo& port) const { - if (filters_.empty()) - return true; + if (filters_.empty()) { + return BluetoothPortIsAllowed(allowed_bluetooth_service_class_ids_, port); + } for (const auto& filter : filters_) { - if (filter->has_vendor_id && - (!port.has_vendor_id || filter->vendor_id != port.vendor_id)) { - continue; - } - if (filter->has_product_id && - (!port.has_product_id || filter->product_id != port.product_id)) { - continue; + if (FilterMatchesPort(*filter, port) && + BluetoothPortIsAllowed(allowed_bluetooth_service_class_ids_, port)) { + return true; } - return true; } return false; diff --git a/shell/browser/serial/serial_chooser_controller.h b/shell/browser/serial/serial_chooser_controller.h index 2fe16bf255b2a..82aff0927f857 100644 --- a/shell/browser/serial/serial_chooser_controller.h +++ b/shell/browser/serial/serial_chooser_controller.h @@ -34,6 +34,7 @@ class SerialChooserController final : public SerialChooserContext::PortObserver, SerialChooserController( content::RenderFrameHost* render_frame_host, std::vector filters, + std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids, content::SerialChooser::Callback callback, content::WebContents* web_contents, base::WeakPtr serial_delegate); @@ -53,11 +54,12 @@ class SerialChooserController final : public SerialChooserContext::PortObserver, private: api::Session* GetSession(); void OnGetDevices(std::vector ports); - bool FilterMatchesAny(const device::mojom::SerialPortInfo& port) const; + bool DisplayDevice(const device::mojom::SerialPortInfo& port) const; void RunCallback(device::mojom::SerialPortInfoPtr port); void OnDeviceChosen(const std::string& port_id); std::vector filters_; + std::vector<::device::BluetoothUUID> allowed_bluetooth_service_class_ids_; content::SerialChooser::Callback callback_; url::Origin origin_; From 8b741d3728769d303c7a22e9b5684423e62d0506 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:23:35 +0000 Subject: [PATCH 2/2] fix: bluetooth dependency Co-authored-by: Shelley Vohr --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index 7dba8dbe784bc..7cf148de275ef 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -473,6 +473,7 @@ source_set("electron_lib") { "//net:extras", "//net:net_resources", "//printing/buildflags", + "//services/device/public/cpp/bluetooth:bluetooth", "//services/device/public/cpp/geolocation", "//services/device/public/cpp/hid", "//services/device/public/mojom",