chore: refactor persisting permission granted to serial ports (#31181)

This commit is contained in:
John Kleinschmidt
2021-10-06 16:18:00 -04:00
committed by GitHub
parent 21c6b33ebe
commit d6de243837
13 changed files with 155 additions and 131 deletions

View File

@@ -60,7 +60,7 @@ bool ElectronSerialDelegate::HasPortPermission(
auto* chooser_context =
SerialChooserContextFactory::GetForBrowserContext(browser_context);
return chooser_context->HasPortPermission(
web_contents->GetMainFrame()->GetLastCommittedOrigin(), port);
web_contents->GetMainFrame()->GetLastCommittedOrigin(), port, frame);
}
device::mojom::SerialPortManager* ElectronSerialDelegate::GetPortManager(

View File

@@ -13,22 +13,25 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "shell/browser/web_contents_permission_helper.h"
namespace electron {
constexpr char kPortNameKey[] = "name";
constexpr char kTokenKey[] = "token";
#if defined(OS_WIN)
constexpr char kDeviceInstanceIdKey[] = "device_instance_id";
const char kDeviceInstanceIdKey[] = "device_instance_id";
#else
constexpr char kVendorIdKey[] = "vendor_id";
constexpr char kProductIdKey[] = "product_id";
constexpr char kSerialNumberKey[] = "serial_number";
const char kVendorIdKey[] = "vendor_id";
const char kProductIdKey[] = "product_id";
const char kSerialNumberKey[] = "serial_number";
#if defined(OS_MAC)
constexpr char kUsbDriverKey[] = "usb_driver";
const char kUsbDriverKey[] = "usb_driver";
#endif // defined(OS_MAC)
#endif // defined(OS_WIN)
#endif // defined(OS_WIN
std::string EncodeToken(const base::UnguessableToken& token) {
const uint64_t data[2] = {token.GetHighForSerialization(),
@@ -83,21 +86,24 @@ base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port) {
return value;
}
SerialChooserContext::SerialChooserContext(
ElectronBrowserContext* browser_context)
: browser_context_(browser_context) {}
SerialChooserContext::SerialChooserContext() = default;
SerialChooserContext::~SerialChooserContext() = default;
void SerialChooserContext::GrantPortPermission(
const url::Origin& origin,
const device::mojom::SerialPortInfo& port) {
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host) {
base::Value value = PortInfoToValue(port);
port_info_.insert({port.token, value.Clone()});
if (CanStorePersistentEntry(port)) {
browser_context_->GrantObjectPermission(origin, std::move(value),
kSerialGrantedDevicesPref);
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
auto* permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
permission_helper->GrantSerialPortPermission(origin, std::move(value),
render_frame_host);
return;
}
@@ -106,7 +112,8 @@ void SerialChooserContext::GrantPortPermission(
bool SerialChooserContext::HasPortPermission(
const url::Origin& origin,
const device::mojom::SerialPortInfo& port) {
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host) {
auto it = ephemeral_ports_.find(origin);
if (it != ephemeral_ports_.end()) {
const std::set<base::UnguessableToken> ports = it->second;
@@ -118,39 +125,13 @@ bool SerialChooserContext::HasPortPermission(
return false;
}
std::vector<std::unique_ptr<base::Value>> object_list =
browser_context_->GetGrantedObjects(origin, kSerialGrantedDevicesPref);
for (const auto& device : object_list) {
#if defined(OS_WIN)
const std::string& device_instance_id =
*device->FindStringKey(kDeviceInstanceIdKey);
if (port.device_instance_id == device_instance_id)
return true;
#else
const int vendor_id = *device->FindIntKey(kVendorIdKey);
const int product_id = *device->FindIntKey(kProductIdKey);
const std::string& serial_number = *device->FindStringKey(kSerialNumberKey);
// Guaranteed by the CanStorePersistentEntry) check above.
DCHECK(port.has_vendor_id);
DCHECK(port.has_product_id);
DCHECK(port.serial_number && !port.serial_number->empty());
if (port.vendor_id != vendor_id || port.product_id != product_id ||
port.serial_number != serial_number) {
continue;
}
#if defined(OS_MAC)
const std::string& usb_driver_name = *device->FindStringKey(kUsbDriverKey);
if (port.usb_driver_name != usb_driver_name) {
continue;
}
#endif // defined(OS_MAC)
return true;
#endif // defined(OS_WIN)
}
return false;
auto* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
auto* permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
base::Value value = PortInfoToValue(port);
return permission_helper->CheckSerialPortPermission(origin, std::move(value),
render_frame_host);
}
// static

View File

@@ -29,19 +29,35 @@ class Value;
namespace electron {
extern const char kHidVendorIdKey[];
extern const char kHidProductIdKey[];
#if defined(OS_WIN)
extern const char kDeviceInstanceIdKey[];
#else
extern const char kVendorIdKey[];
extern const char kProductIdKey[];
extern const char kSerialNumberKey[];
#if defined(OS_MAC)
extern const char kUsbDriverKey[];
#endif // defined(OS_MAC)
#endif // defined(OS_WIN)
class SerialChooserContext : public KeyedService,
public device::mojom::SerialPortManagerClient {
public:
using PortObserver = content::SerialDelegate::Observer;
explicit SerialChooserContext(ElectronBrowserContext* browser_context);
SerialChooserContext();
~SerialChooserContext() override;
// Serial-specific interface for granting and checking permissions.
void GrantPortPermission(const url::Origin& origin,
const device::mojom::SerialPortInfo& port);
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host);
bool HasPortPermission(const url::Origin& origin,
const device::mojom::SerialPortInfo& port);
const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host);
static bool CanStorePersistentEntry(
const device::mojom::SerialPortInfo& port);
@@ -62,8 +78,6 @@ class SerialChooserContext : public KeyedService,
mojo::PendingRemote<device::mojom::SerialPortManager> manager);
void OnPortManagerConnectionError();
ElectronBrowserContext* browser_context_;
// Tracks the set of ports to which an origin has access to.
std::map<url::Origin, std::set<base::UnguessableToken>> ephemeral_ports_;

View File

@@ -19,9 +19,7 @@ SerialChooserContextFactory::~SerialChooserContextFactory() = default;
KeyedService* SerialChooserContextFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
auto* browser_context =
static_cast<electron::ElectronBrowserContext*>(context);
return new SerialChooserContext(browser_context);
return new SerialChooserContext();
}
// static

View File

@@ -67,7 +67,8 @@ SerialChooserController::SerialChooserController(
: WebContentsObserver(web_contents),
filters_(std::move(filters)),
callback_(std::move(callback)),
serial_delegate_(serial_delegate) {
serial_delegate_(serial_delegate),
render_frame_host_id_(render_frame_host->GetGlobalId()) {
origin_ = web_contents->GetMainFrame()->GetLastCommittedOrigin();
chooser_context_ = SerialChooserContextFactory::GetForBrowserContext(
@@ -124,7 +125,8 @@ void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
return ptr->token.ToString() == port_id;
});
if (it != ports_.end()) {
chooser_context_->GrantPortPermission(origin_, *it->get());
auto* rfh = content::RenderFrameHost::FromID(render_frame_host_id_);
chooser_context_->GrantPortPermission(origin_, *it->get(), rfh);
RunCallback(it->Clone());
} else {
RunCallback(/*port=*/nullptr);

View File

@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/serial_chooser.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
@@ -61,6 +62,8 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
base::WeakPtr<ElectronSerialDelegate> serial_delegate_;
content::GlobalRenderFrameHostId render_frame_host_id_;
base::WeakPtrFactory<SerialChooserController> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialChooserController);