fix: properly fire serial-port-added and serial-port-removed events (#34958)
Based on 2309652: [webhid] Notify chooser context observers on shutdown | https://chromium-review.googlesource.com/c/chromium/src/+/2309652
This commit is contained in:
parent
aeba6ca973
commit
648c9934c0
6 changed files with 71 additions and 21 deletions
|
@ -71,15 +71,15 @@ device::mojom::SerialPortManager* ElectronSerialDelegate::GetPortManager(
|
||||||
|
|
||||||
void ElectronSerialDelegate::AddObserver(content::RenderFrameHost* frame,
|
void ElectronSerialDelegate::AddObserver(content::RenderFrameHost* frame,
|
||||||
Observer* observer) {
|
Observer* observer) {
|
||||||
return GetChooserContext(frame)->AddPortObserver(observer);
|
observer_list_.AddObserver(observer);
|
||||||
|
auto* chooser_context = GetChooserContext(frame);
|
||||||
|
if (!port_observation_.IsObserving())
|
||||||
|
port_observation_.Observe(chooser_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronSerialDelegate::RemoveObserver(content::RenderFrameHost* frame,
|
void ElectronSerialDelegate::RemoveObserver(content::RenderFrameHost* frame,
|
||||||
Observer* observer) {
|
Observer* observer) {
|
||||||
SerialChooserContext* serial_chooser_context = GetChooserContext(frame);
|
observer_list_.RemoveObserver(observer);
|
||||||
if (serial_chooser_context) {
|
|
||||||
return serial_chooser_context->RemovePortObserver(observer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronSerialDelegate::RevokePortPermissionWebInitiated(
|
void ElectronSerialDelegate::RevokePortPermissionWebInitiated(
|
||||||
|
@ -120,4 +120,27 @@ void ElectronSerialDelegate::DeleteControllerForFrame(
|
||||||
controller_map_.erase(render_frame_host);
|
controller_map_.erase(render_frame_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SerialChooserContext::PortObserver:
|
||||||
|
void ElectronSerialDelegate::OnPortAdded(
|
||||||
|
const device::mojom::SerialPortInfo& port) {
|
||||||
|
for (auto& observer : observer_list_)
|
||||||
|
observer.OnPortAdded(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronSerialDelegate::OnPortRemoved(
|
||||||
|
const device::mojom::SerialPortInfo& port) {
|
||||||
|
for (auto& observer : observer_list_)
|
||||||
|
observer.OnPortRemoved(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronSerialDelegate::OnPortManagerConnectionError() {
|
||||||
|
port_observation_.Reset();
|
||||||
|
for (auto& observer : observer_list_)
|
||||||
|
observer.OnPortManagerConnectionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronSerialDelegate::OnSerialChooserContextShutdown() {
|
||||||
|
port_observation_.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -11,13 +11,15 @@
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "content/public/browser/serial_delegate.h"
|
#include "content/public/browser/serial_delegate.h"
|
||||||
|
#include "shell/browser/serial/serial_chooser_context.h"
|
||||||
#include "shell/browser/serial/serial_chooser_controller.h"
|
#include "shell/browser/serial/serial_chooser_controller.h"
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
class SerialChooserController;
|
class SerialChooserController;
|
||||||
|
|
||||||
class ElectronSerialDelegate : public content::SerialDelegate {
|
class ElectronSerialDelegate : public content::SerialDelegate,
|
||||||
|
public SerialChooserContext::PortObserver {
|
||||||
public:
|
public:
|
||||||
ElectronSerialDelegate();
|
ElectronSerialDelegate();
|
||||||
~ElectronSerialDelegate() override;
|
~ElectronSerialDelegate() override;
|
||||||
|
@ -48,6 +50,13 @@ class ElectronSerialDelegate : public content::SerialDelegate {
|
||||||
|
|
||||||
void DeleteControllerForFrame(content::RenderFrameHost* render_frame_host);
|
void DeleteControllerForFrame(content::RenderFrameHost* render_frame_host);
|
||||||
|
|
||||||
|
// SerialChooserContext::PortObserver:
|
||||||
|
void OnPortAdded(const device::mojom::SerialPortInfo& port) override;
|
||||||
|
void OnPortRemoved(const device::mojom::SerialPortInfo& port) override;
|
||||||
|
void OnPortManagerConnectionError() override;
|
||||||
|
void OnPermissionRevoked(const url::Origin& origin) override {}
|
||||||
|
void OnSerialChooserContextShutdown() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SerialChooserController* ControllerForFrame(
|
SerialChooserController* ControllerForFrame(
|
||||||
content::RenderFrameHost* render_frame_host);
|
content::RenderFrameHost* render_frame_host);
|
||||||
|
@ -56,6 +65,13 @@ class ElectronSerialDelegate : public content::SerialDelegate {
|
||||||
std::vector<blink::mojom::SerialPortFilterPtr> filters,
|
std::vector<blink::mojom::SerialPortFilterPtr> filters,
|
||||||
content::SerialChooser::Callback callback);
|
content::SerialChooser::Callback callback);
|
||||||
|
|
||||||
|
base::ScopedObservation<SerialChooserContext,
|
||||||
|
SerialChooserContext::PortObserver,
|
||||||
|
&SerialChooserContext::AddPortObserver,
|
||||||
|
&SerialChooserContext::RemovePortObserver>
|
||||||
|
port_observation_{this};
|
||||||
|
base::ObserverList<content::SerialDelegate::Observer> observer_list_;
|
||||||
|
|
||||||
std::unordered_map<content::RenderFrameHost*,
|
std::unordered_map<content::RenderFrameHost*,
|
||||||
std::unique_ptr<SerialChooserController>>
|
std::unique_ptr<SerialChooserController>>
|
||||||
controller_map_;
|
controller_map_;
|
||||||
|
|
|
@ -90,11 +90,13 @@ base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port) {
|
||||||
SerialChooserContext::SerialChooserContext(ElectronBrowserContext* context)
|
SerialChooserContext::SerialChooserContext(ElectronBrowserContext* context)
|
||||||
: browser_context_(context) {}
|
: browser_context_(context) {}
|
||||||
|
|
||||||
SerialChooserContext::~SerialChooserContext() = default;
|
SerialChooserContext::~SerialChooserContext() {
|
||||||
|
// Notify observers that the chooser context is about to be destroyed.
|
||||||
void SerialChooserContext::OnPermissionRevoked(const url::Origin& origin) {
|
// Observers must remove themselves from the observer lists.
|
||||||
for (auto& observer : port_observer_list_)
|
for (auto& observer : port_observer_list_) {
|
||||||
observer.OnPermissionRevoked(origin);
|
observer.OnSerialChooserContextShutdown();
|
||||||
|
DCHECK(!port_observer_list_.HasObserver(&observer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialChooserContext::GrantPortPermission(
|
void SerialChooserContext::GrantPortPermission(
|
||||||
|
@ -127,8 +129,6 @@ void SerialChooserContext::RevokePortPermissionWebInitiated(
|
||||||
auto it = port_info_.find(token);
|
auto it = port_info_.find(token);
|
||||||
if (it == port_info_.end())
|
if (it == port_info_.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
return OnPermissionRevoked(origin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -46,7 +46,12 @@ extern const char kUsbDriverKey[];
|
||||||
class SerialChooserContext : public KeyedService,
|
class SerialChooserContext : public KeyedService,
|
||||||
public device::mojom::SerialPortManagerClient {
|
public device::mojom::SerialPortManagerClient {
|
||||||
public:
|
public:
|
||||||
using PortObserver = content::SerialDelegate::Observer;
|
class PortObserver : public content::SerialDelegate::Observer {
|
||||||
|
public:
|
||||||
|
// Called when the SerialChooserContext is shutting down. Observers must
|
||||||
|
// remove themselves before returning.
|
||||||
|
virtual void OnSerialChooserContextShutdown() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
explicit SerialChooserContext(ElectronBrowserContext* context);
|
explicit SerialChooserContext(ElectronBrowserContext* context);
|
||||||
~SerialChooserContext() override;
|
~SerialChooserContext() override;
|
||||||
|
@ -55,9 +60,6 @@ class SerialChooserContext : public KeyedService,
|
||||||
SerialChooserContext(const SerialChooserContext&) = delete;
|
SerialChooserContext(const SerialChooserContext&) = delete;
|
||||||
SerialChooserContext& operator=(const SerialChooserContext&) = delete;
|
SerialChooserContext& operator=(const SerialChooserContext&) = delete;
|
||||||
|
|
||||||
// ObjectPermissionContextBase::PermissionObserver:
|
|
||||||
void OnPermissionRevoked(const url::Origin& origin);
|
|
||||||
|
|
||||||
// Serial-specific interface for granting and checking permissions.
|
// Serial-specific interface for granting and checking permissions.
|
||||||
void GrantPortPermission(const url::Origin& origin,
|
void GrantPortPermission(const url::Origin& origin,
|
||||||
const device::mojom::SerialPortInfo& port,
|
const device::mojom::SerialPortInfo& port,
|
||||||
|
|
|
@ -77,13 +77,11 @@ SerialChooserController::SerialChooserController(
|
||||||
DCHECK(chooser_context_);
|
DCHECK(chooser_context_);
|
||||||
chooser_context_->GetPortManager()->GetDevices(base::BindOnce(
|
chooser_context_->GetPortManager()->GetDevices(base::BindOnce(
|
||||||
&SerialChooserController::OnGetDevices, weak_factory_.GetWeakPtr()));
|
&SerialChooserController::OnGetDevices, weak_factory_.GetWeakPtr()));
|
||||||
|
observation_.Observe(chooser_context_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialChooserController::~SerialChooserController() {
|
SerialChooserController::~SerialChooserController() {
|
||||||
RunCallback(/*port=*/nullptr);
|
RunCallback(/*port=*/nullptr);
|
||||||
if (chooser_context_) {
|
|
||||||
chooser_context_->RemovePortObserver(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api::Session* SerialChooserController::GetSession() {
|
api::Session* SerialChooserController::GetSession() {
|
||||||
|
@ -117,7 +115,11 @@ void SerialChooserController::OnPortRemoved(
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialChooserController::OnPortManagerConnectionError() {
|
void SerialChooserController::OnPortManagerConnectionError() {
|
||||||
// TODO(nornagon/jkleinsc): report event
|
observation_.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialChooserController::OnSerialChooserContextShutdown() {
|
||||||
|
observation_.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
|
void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
|
||||||
|
|
|
@ -48,6 +48,7 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
|
||||||
void OnPortRemoved(const device::mojom::SerialPortInfo& port) override;
|
void OnPortRemoved(const device::mojom::SerialPortInfo& port) override;
|
||||||
void OnPortManagerConnectionError() override;
|
void OnPortManagerConnectionError() override;
|
||||||
void OnPermissionRevoked(const url::Origin& origin) override {}
|
void OnPermissionRevoked(const url::Origin& origin) override {}
|
||||||
|
void OnSerialChooserContextShutdown() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
api::Session* GetSession();
|
api::Session* GetSession();
|
||||||
|
@ -62,6 +63,12 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
|
||||||
|
|
||||||
base::WeakPtr<SerialChooserContext> chooser_context_;
|
base::WeakPtr<SerialChooserContext> chooser_context_;
|
||||||
|
|
||||||
|
base::ScopedObservation<SerialChooserContext,
|
||||||
|
SerialChooserContext::PortObserver,
|
||||||
|
&SerialChooserContext::AddPortObserver,
|
||||||
|
&SerialChooserContext::RemovePortObserver>
|
||||||
|
observation_{this};
|
||||||
|
|
||||||
std::vector<device::mojom::SerialPortInfoPtr> ports_;
|
std::vector<device::mojom::SerialPortInfoPtr> ports_;
|
||||||
|
|
||||||
base::WeakPtr<ElectronSerialDelegate> serial_delegate_;
|
base::WeakPtr<ElectronSerialDelegate> serial_delegate_;
|
||||||
|
|
Loading…
Reference in a new issue