From 51babe4592837986beade5aa139c5cba6be2e3d7 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:30:34 -0600 Subject: [PATCH] refactor: bluetooth in serial chooser when exclusively wireless serial ports are expected (#45743) * refactor: bluetooth in serial chooser when exclusively wireless serial ports are expected https://chromium-review.googlesource.com/c/chromium/src/+/5737296 Co-authored-by: Shelley Vohr * chore: review feedback Co-authored-by: Shelley Vohr --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr --- .../serial/serial_chooser_controller.cc | 63 ++++++++++++++++++- .../serial/serial_chooser_controller.h | 19 +++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/shell/browser/serial/serial_chooser_controller.cc b/shell/browser/serial/serial_chooser_controller.cc index 4677481982c8..a87186780655 100644 --- a/shell/browser/serial/serial_chooser_controller.cc +++ b/shell/browser/serial/serial_chooser_controller.cc @@ -10,6 +10,8 @@ #include "base/containers/contains.h" #include "base/functional/bind.h" #include "content/public/browser/web_contents.h" +#include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "services/device/public/cpp/bluetooth/bluetooth_utils.h" #include "services/device/public/mojom/serial.mojom.h" @@ -65,6 +67,8 @@ namespace electron { namespace { +using ::device::BluetoothAdapter; +using ::device::BluetoothAdapterFactory; using ::device::mojom::SerialPortType; bool FilterMatchesPort(const blink::mojom::SerialPortFilter& filter, @@ -124,8 +128,11 @@ SerialChooserController::SerialChooserController( web_contents_->GetBrowserContext()) ->AsWeakPtr(); DCHECK(chooser_context_); - chooser_context_->GetPortManager()->GetDevices(base::BindOnce( - &SerialChooserController::OnGetDevices, weak_factory_.GetWeakPtr())); + + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&SerialChooserController::GetDevices, + weak_factory_.GetWeakPtr())); + observation_.Observe(chooser_context_.get()); } @@ -140,6 +147,29 @@ api::Session* SerialChooserController::GetSession() { return api::Session::FromBrowserContext(web_contents_->GetBrowserContext()); } +void SerialChooserController::GetDevices() { + if (IsWirelessSerialPortOnly()) { + if (!adapter_) { + BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce( + &SerialChooserController::OnGetAdapter, weak_factory_.GetWeakPtr(), + base::BindOnce(&SerialChooserController::GetDevices, + weak_factory_.GetWeakPtr()))); + return; + } + } + + chooser_context_->GetPortManager()->GetDevices(base::BindOnce( + &SerialChooserController::OnGetDevices, weak_factory_.GetWeakPtr())); +} + +void SerialChooserController::AdapterPoweredChanged(BluetoothAdapter* adapter, + bool powered) { + // TODO(codebytere): maybe emit an event here? + if (powered) { + GetDevices(); + } +} + void SerialChooserController::OnPortAdded( const device::mojom::SerialPortInfo& port) { if (!DisplayDevice(port)) @@ -196,6 +226,7 @@ void SerialChooserController::OnGetDevices( return port1->path.BaseName() < port2->path.BaseName(); }); + ports_.clear(); for (auto& port : ports) { if (DisplayDevice(*port)) ports_.push_back(std::move(port)); @@ -235,5 +266,33 @@ void SerialChooserController::RunCallback( std::move(callback_).Run(std::move(port)); } } +void SerialChooserController::OnGetAdapter( + base::OnceClosure callback, + scoped_refptr adapter) { + CHECK(adapter); + adapter_ = std::move(adapter); + adapter_observation_.Observe(adapter_.get()); + std::move(callback).Run(); +} + +bool SerialChooserController::IsWirelessSerialPortOnly() const { + if (allowed_bluetooth_service_class_ids_.empty()) { + return false; + } + + // The system's wired and wireless serial ports can be shown if there is no + // filter. + if (filters_.empty()) { + return false; + } + + // Check if all the filters are meant for serial port from Bluetooth device. + for (const auto& filter : filters_) { + if (!filter->bluetooth_service_class_id) { + return false; + } + } + return true; +} } // namespace electron diff --git a/shell/browser/serial/serial_chooser_controller.h b/shell/browser/serial/serial_chooser_controller.h index 603fa45154f7..e88db05bb80e 100644 --- a/shell/browser/serial/serial_chooser_controller.h +++ b/shell/browser/serial/serial_chooser_controller.h @@ -12,6 +12,7 @@ #include "base/scoped_observation.h" #include "content/public/browser/global_routing_id.h" #include "content/public/browser/serial_chooser.h" +#include "device/bluetooth/bluetooth_adapter.h" #include "services/device/public/mojom/serial.mojom-forward.h" #include "shell/browser/serial/serial_chooser_context.h" #include "third_party/blink/public/mojom/serial/serial.mojom-forward.h" @@ -31,7 +32,8 @@ class ElectronSerialDelegate; // SerialChooserController provides data for the Serial API permission prompt. class SerialChooserController final - : private SerialChooserContext::PortObserver { + : private SerialChooserContext::PortObserver, + private device::BluetoothAdapter::Observer { public: SerialChooserController( content::RenderFrameHost* render_frame_host, @@ -55,12 +57,21 @@ class SerialChooserController final void OnPermissionRevoked(const url::Origin& origin) override {} void OnSerialChooserContextShutdown() override; + // BluetoothAdapter::Observer + void AdapterPoweredChanged(device::BluetoothAdapter* adapter, + bool powered) override; + private: api::Session* GetSession(); + void GetDevices(); void OnGetDevices(std::vector ports); bool DisplayDevice(const device::mojom::SerialPortInfo& port) const; void RunCallback(device::mojom::SerialPortInfoPtr port); void OnDeviceChosen(const std::string& port_id); + void OnGetAdapter(base::OnceClosure callback, + scoped_refptr adapter); + // Whether it will only show ports from bluetooth devices. + [[nodiscard]] bool IsWirelessSerialPortOnly() const; base::WeakPtr web_contents_; @@ -77,8 +88,12 @@ class SerialChooserController final std::vector ports_; - base::WeakPtr serial_delegate_; + scoped_refptr adapter_; + base::ScopedObservation + adapter_observation_{this}; + base::WeakPtr serial_delegate_; content::GlobalRenderFrameHostId render_frame_host_id_; base::WeakPtrFactory weak_factory_{this};