refactor: partition HidDelegate observers by browser context (#40215)

This commit is contained in:
Shelley Vohr 2023-10-17 22:54:53 +02:00 committed by GitHub
parent f65d1f3d55
commit 73a42d0b7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 71 deletions

View file

@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/scoped_observation.h"
#include "chrome/common/chrome_features.h"
#include "content/public/browser/web_contents.h"
#include "electron/buildflags/buildflags.h"
@ -36,6 +37,70 @@ electron::HidChooserContext* GetChooserContext(
namespace electron {
// Manages the HidDelegate observers for a single browser context.
class ElectronHidDelegate::ContextObservation
: public HidChooserContext::DeviceObserver {
public:
ContextObservation(ElectronHidDelegate* parent,
content::BrowserContext* browser_context)
: parent_(parent), browser_context_(browser_context) {
auto* chooser_context = GetChooserContext(browser_context_);
device_observation_.Observe(chooser_context);
}
ContextObservation(ContextObservation&) = delete;
ContextObservation& operator=(ContextObservation&) = delete;
~ContextObservation() override = default;
// HidChooserContext::DeviceObserver:
void OnDeviceAdded(const device::mojom::HidDeviceInfo& device_info) override {
for (auto& observer : observer_list_)
observer.OnDeviceAdded(device_info);
}
void OnDeviceRemoved(
const device::mojom::HidDeviceInfo& device_info) override {
for (auto& observer : observer_list_)
observer.OnDeviceRemoved(device_info);
}
void OnDeviceChanged(
const device::mojom::HidDeviceInfo& device_info) override {
for (auto& observer : observer_list_)
observer.OnDeviceChanged(device_info);
}
void OnHidManagerConnectionError() override {
for (auto& observer : observer_list_)
observer.OnHidManagerConnectionError();
}
void OnHidChooserContextShutdown() override {
parent_->observations_.erase(browser_context_);
// Return since `this` is now deleted.
}
void AddObserver(content::HidDelegate::Observer* observer) {
observer_list_.AddObserver(observer);
}
void RemoveObserver(content::HidDelegate::Observer* observer) {
observer_list_.RemoveObserver(observer);
}
private:
// Safe because `parent_` owns `this`.
const raw_ptr<ElectronHidDelegate> parent_;
// Safe because `this` is destroyed when the context is lost.
const raw_ptr<content::BrowserContext> browser_context_;
base::ScopedObservation<HidChooserContext, HidChooserContext::DeviceObserver>
device_observation_{this};
base::ObserverList<content::HidDelegate::Observer> observer_list_;
};
ElectronHidDelegate::ElectronHidDelegate() = default;
ElectronHidDelegate::~ElectronHidDelegate() = default;
@ -45,11 +110,11 @@ std::unique_ptr<content::HidChooser> ElectronHidDelegate::RunChooser(
std::vector<blink::mojom::HidDeviceFilterPtr> filters,
std::vector<blink::mojom::HidDeviceFilterPtr> exclusion_filters,
content::HidChooser::Callback callback) {
DCHECK(render_frame_host);
auto* chooser_context =
GetChooserContext(render_frame_host->GetBrowserContext());
if (!device_observation_.IsObserving())
device_observation_.Observe(chooser_context);
auto* browser_context = render_frame_host->GetBrowserContext();
// Start observing HidChooserContext for permission and device events.
GetContextObserver(browser_context);
DCHECK(base::Contains(observations_, browser_context));
HidChooserController* controller = ControllerForFrame(render_frame_host);
if (controller) {
@ -101,16 +166,14 @@ device::mojom::HidManager* ElectronHidDelegate::GetHidManager(
void ElectronHidDelegate::AddObserver(content::BrowserContext* browser_context,
Observer* observer) {
observer_list_.AddObserver(observer);
auto* chooser_context = GetChooserContext(browser_context);
if (!device_observation_.IsObserving())
device_observation_.Observe(chooser_context);
GetContextObserver(browser_context)->AddObserver(observer);
}
void ElectronHidDelegate::RemoveObserver(
content::BrowserContext* browser_context,
content::HidDelegate::Observer* observer) {
observer_list_.RemoveObserver(observer);
DCHECK(base::Contains(observations_, browser_context));
GetContextObserver(browser_context)->RemoveObserver(observer);
}
const device::mojom::HidDeviceInfo* ElectronHidDelegate::GetDeviceInfo(
@ -140,33 +203,14 @@ bool ElectronHidDelegate::IsServiceWorkerAllowedForOrigin(
return false;
}
void ElectronHidDelegate::OnDeviceAdded(
const device::mojom::HidDeviceInfo& device_info) {
for (auto& observer : observer_list_)
observer.OnDeviceAdded(device_info);
}
void ElectronHidDelegate::OnDeviceRemoved(
const device::mojom::HidDeviceInfo& device_info) {
for (auto& observer : observer_list_)
observer.OnDeviceRemoved(device_info);
}
void ElectronHidDelegate::OnDeviceChanged(
const device::mojom::HidDeviceInfo& device_info) {
for (auto& observer : observer_list_)
observer.OnDeviceChanged(device_info);
}
void ElectronHidDelegate::OnHidManagerConnectionError() {
device_observation_.Reset();
for (auto& observer : observer_list_)
observer.OnHidManagerConnectionError();
}
void ElectronHidDelegate::OnHidChooserContextShutdown() {
device_observation_.Reset();
ElectronHidDelegate::ContextObservation*
ElectronHidDelegate::GetContextObserver(
content::BrowserContext* browser_context) {
if (!base::Contains(observations_, browser_context)) {
observations_.emplace(browser_context, std::make_unique<ContextObservation>(
this, browser_context));
}
return observations_[browser_context].get();
}
HidChooserController* ElectronHidDelegate::ControllerForFrame(