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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 155 additions and 131 deletions

View file

@ -297,6 +297,35 @@ app.whenReady().then(() => {
width: 800, width: 800,
height: 600 height: 600
}) })
win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'serial') {
// Add logic here to determine if permission should be given to allow serial selection
return true
}
return false
})
// Optionally, retrieve previously persisted devices from a persistent store
const grantedDevices = fetchGrantedDevices()
win.webContents.session.setDevicePermissionHandler((details) => {
if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'serial') {
if (details.device.vendorId === 123 && details.device.productId === 345) {
// Always allow this type of device (this allows skipping the call to `navigator.serial.requestPort` first)
return true
}
// Search through the list of devices that have previously been granted permission
return grantedDevices.some((grantedDevice) => {
return grantedDevice.vendorId === details.device.vendorId &&
grantedDevice.productId === details.device.productId &&
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
})
}
return false
})
win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => { win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
event.preventDefault() event.preventDefault()
const selectedPort = portList.find((device) => { const selectedPort = portList.find((device) => {
@ -647,9 +676,9 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
* `handler` Function\<Boolean> | null * `handler` Function\<Boolean> | null
* `details` Object * `details` Object
* `deviceType` String - The type of device that permission is being requested on, can be `hid`. * `deviceType` String - The type of device that permission is being requested on, can be `hid` or `serial`.
* `origin` String - The origin URL of the device permission check. * `origin` String - The origin URL of the device permission check.
* `device` [HIDDevice](structures/hid-device.md) - the device that permission is being requested for. * `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md)- the device that permission is being requested for.
* `frame` [WebFrameMain](web-frame-main.md) - WebFrameMain checking the device permission. * `frame` [WebFrameMain](web-frame-main.md) - WebFrameMain checking the device permission.
Sets the handler which can be used to respond to device permission checks for the `session`. Sets the handler which can be used to respond to device permission checks for the `session`.
@ -674,6 +703,8 @@ app.whenReady().then(() => {
if (permission === 'hid') { if (permission === 'hid') {
// Add logic here to determine if permission should be given to allow HID selection // Add logic here to determine if permission should be given to allow HID selection
return true return true
} else if (permission === 'serial') {
// Add logic here to determine if permission should be given to allow serial port selection
} }
return false return false
}) })
@ -694,6 +725,11 @@ app.whenReady().then(() => {
grantedDevice.productId === details.device.productId && grantedDevice.productId === details.device.productId &&
grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
}) })
} else if (details.deviceType === 'serial') {
if (details.device.vendorId === 123 && details.device.productId === 345) {
// Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
return true
}
} }
return false return false
}) })

View file

@ -84,13 +84,22 @@ There are several additional APIs for working with the Web Serial API:
and [`serial-port-removed`](../api/session.md#event-serial-port-removed) events and [`serial-port-removed`](../api/session.md#event-serial-port-removed) events
on the Session can be used to handle devices being plugged in or unplugged during the on the Session can be used to handle devices being plugged in or unplugged during the
`navigator.serial.requestPort` process. `navigator.serial.requestPort` process.
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
can be used to provide default permissioning to devices without first calling
for permission to devices via `navigator.serial.requestPort`. Additionally,
the default behavior of Electron is to store granted device permision through
the lifetime of the corresponding WebContents. If longer term storage is
needed, a developer can store granted device permissions (eg when handling
the `select-serial-port` event) and then read from that storage with
`setDevicePermissionHandler`.
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler) * [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
can be used to disable serial access for specific origins. can be used to disable serial access for specific origins.
### Example ### Example
This example demonstrates an Electron application that automatically selects This example demonstrates an Electron application that automatically selects
the first available Arduino Uno serial device (if connected) through serial devices through [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
as well as demonstrating selecting the first available Arduino Uno serial device (if connected) through
[`select-serial-port` event on the Session](../api/session.md#event-select-serial-port) [`select-serial-port` event on the Session](../api/session.md#event-select-serial-port)
when the `Test Web Serial` button is clicked. when the `Test Web Serial` button is clicked.

View file

@ -8,8 +8,6 @@
#include <utility> #include <utility>
#include <vector>
#include "base/barrier_closure.h" #include "base/barrier_closure.h"
#include "base/base_paths.h" #include "base/base_paths.h"
#include "base/command_line.h" #include "base/command_line.h"
@ -95,9 +93,6 @@ std::string MakePartitionName(const std::string& input) {
} // namespace } // namespace
const char kSerialGrantedDevicesPref[] =
"profile.content_settings.exceptions.serial-chooser-data";
// static // static
ElectronBrowserContext::BrowserContextMap& ElectronBrowserContext::BrowserContextMap&
ElectronBrowserContext::browser_context_map() { ElectronBrowserContext::browser_context_map() {
@ -194,7 +189,6 @@ void ElectronBrowserContext::InitPrefs() {
registry->RegisterFilePathPref(prefs::kDownloadDefaultDirectory, registry->RegisterFilePathPref(prefs::kDownloadDefaultDirectory,
download_dir); download_dir);
registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths); registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths);
registry->RegisterDictionaryPref(kSerialGrantedDevicesPref);
InspectableWebContents::RegisterPrefs(registry.get()); InspectableWebContents::RegisterPrefs(registry.get());
MediaDeviceIDSalt::RegisterPrefs(registry.get()); MediaDeviceIDSalt::RegisterPrefs(registry.get());
ZoomLevelDelegate::RegisterPrefs(registry.get()); ZoomLevelDelegate::RegisterPrefs(registry.get());
@ -420,54 +414,6 @@ void ElectronBrowserContext::SetSSLConfigClient(
ssl_config_client_ = std::move(client); ssl_config_client_ = std::move(client);
} }
void ElectronBrowserContext::GrantObjectPermission(
const url::Origin& origin,
base::Value object,
const std::string& pref_key) {
std::string origin_string = origin.Serialize();
DictionaryPrefUpdate update(prefs(), pref_key);
base::Value* const current_objects = update.Get();
if (!current_objects || !current_objects->is_dict()) {
base::ListValue objects_for_origin;
objects_for_origin.Append(std::move(object));
base::DictionaryValue objects_by_origin;
objects_by_origin.SetPath(origin_string, std::move(objects_for_origin));
prefs()->Set(pref_key, std::move(objects_by_origin));
} else {
base::Value* const objects_mutable =
current_objects->FindListKey(origin_string);
if (objects_mutable) {
base::Value::ListStorage objects = std::move(*objects_mutable).TakeList();
objects.push_back(std::move(object));
*objects_mutable = base::Value(std::move(objects));
} else {
base::Value new_objects(base::Value::Type::LIST);
new_objects.Append(std::move(object));
current_objects->SetKey(origin_string, std::move(new_objects));
}
}
}
std::vector<std::unique_ptr<base::Value>>
ElectronBrowserContext::GetGrantedObjects(const url::Origin& origin,
const std::string& pref_key) {
auto* current_objects = prefs()->Get(pref_key);
if (!current_objects || !current_objects->is_dict()) {
return {};
}
const base::Value* objects_for_origin =
current_objects->FindPath(origin.Serialize());
if (!objects_for_origin)
return {};
std::vector<std::unique_ptr<base::Value>> results;
for (const auto& object : objects_for_origin->GetList())
results.push_back(std::make_unique<base::Value>(object.Clone()));
return results;
}
// static // static
ElectronBrowserContext* ElectronBrowserContext::From( ElectronBrowserContext* ElectronBrowserContext::From(
const std::string& partition, const std::string& partition,

View file

@ -8,7 +8,6 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/predictors/preconnect_manager.h" #include "chrome/browser/predictors/preconnect_manager.h"
@ -47,9 +46,6 @@ class ResolveProxyHelper;
class WebViewManager; class WebViewManager;
class ProtocolRegistry; class ProtocolRegistry;
// Preference keys for device apis
extern const char kSerialGrantedDevicesPref[];
class ElectronBrowserContext : public content::BrowserContext { class ElectronBrowserContext : public content::BrowserContext {
public: public:
// partition_id => browser_context // partition_id => browser_context
@ -146,19 +142,6 @@ class ElectronBrowserContext : public content::BrowserContext {
network::mojom::SSLConfigPtr GetSSLConfig(); network::mojom::SSLConfigPtr GetSSLConfig();
void SetSSLConfigClient(mojo::Remote<network::mojom::SSLConfigClient> client); void SetSSLConfigClient(mojo::Remote<network::mojom::SSLConfigClient> client);
// Grants |origin| access to |object| by writing it into the browser context.
// To be used in place of ObjectPermissionContextBase::GrantObjectPermission.
void GrantObjectPermission(const url::Origin& origin,
base::Value object,
const std::string& pref_key);
// Returns the list of objects that |origin| has been granted permission to
// access. To be used in place of
// ObjectPermissionContextBase::GetGrantedObjects.
std::vector<std::unique_ptr<base::Value>> GetGrantedObjects(
const url::Origin& origin,
const std::string& pref_key);
~ElectronBrowserContext() override; ~ElectronBrowserContext() override;
private: private:

View file

@ -22,6 +22,7 @@
#include "shell/browser/electron_browser_client.h" #include "shell/browser/electron_browser_client.h"
#include "shell/browser/electron_browser_main_parts.h" #include "shell/browser/electron_browser_main_parts.h"
#include "shell/browser/hid/hid_chooser_context.h" #include "shell/browser/hid/hid_chooser_context.h"
#include "shell/browser/serial/serial_chooser_context.h"
#include "shell/browser/web_contents_permission_helper.h" #include "shell/browser/web_contents_permission_helper.h"
#include "shell/browser/web_contents_preferences.h" #include "shell/browser/web_contents_preferences.h"
#include "shell/common/gin_converters/content_converter.h" #include "shell/common/gin_converters/content_converter.h"
@ -328,6 +329,31 @@ bool ElectronPermissionManager::CheckDevicePermission(
if (serial_number && device_serial_number && if (serial_number && device_serial_number &&
*device_serial_number == *serial_number) *device_serial_number == *serial_number)
return true; return true;
} else if (permission ==
static_cast<content::PermissionType>(
WebContentsPermissionHelper::PermissionType::SERIAL)) {
#if defined(OS_WIN)
if (device->FindStringKey(kDeviceInstanceIdKey) ==
granted_device.FindStringKey(kDeviceInstanceIdKey))
return true;
#else
if (device->FindIntKey(kVendorIdKey) !=
granted_device.FindIntKey(kVendorIdKey) ||
device->FindIntKey(kProductIdKey) !=
granted_device.FindIntKey(kProductIdKey) ||
*device->FindStringKey(kSerialNumberKey) !=
*granted_device.FindStringKey(kSerialNumberKey)) {
continue;
}
#if defined(OS_MAC)
if (*device->FindStringKey(kUsbDriverKey) !=
*granted_device.FindStringKey(kUsbDriverKey)) {
continue;
}
#endif // defined(OS_MAC)
return true;
#endif // defined(OS_WIN)
} }
} }
} }

View file

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

View file

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

View file

@ -29,19 +29,35 @@ class Value;
namespace electron { 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, class SerialChooserContext : public KeyedService,
public device::mojom::SerialPortManagerClient { public device::mojom::SerialPortManagerClient {
public: public:
using PortObserver = content::SerialDelegate::Observer; using PortObserver = content::SerialDelegate::Observer;
explicit SerialChooserContext(ElectronBrowserContext* browser_context); SerialChooserContext();
~SerialChooserContext() override; ~SerialChooserContext() override;
// 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,
content::RenderFrameHost* render_frame_host);
bool HasPortPermission(const url::Origin& origin, bool HasPortPermission(const url::Origin& origin,
const device::mojom::SerialPortInfo& port); const device::mojom::SerialPortInfo& port,
content::RenderFrameHost* render_frame_host);
static bool CanStorePersistentEntry( static bool CanStorePersistentEntry(
const device::mojom::SerialPortInfo& port); const device::mojom::SerialPortInfo& port);
@ -62,8 +78,6 @@ class SerialChooserContext : public KeyedService,
mojo::PendingRemote<device::mojom::SerialPortManager> manager); mojo::PendingRemote<device::mojom::SerialPortManager> manager);
void OnPortManagerConnectionError(); void OnPortManagerConnectionError();
ElectronBrowserContext* browser_context_;
// Tracks the set of ports to which an origin has access to. // Tracks the set of ports to which an origin has access to.
std::map<url::Origin, std::set<base::UnguessableToken>> ephemeral_ports_; std::map<url::Origin, std::set<base::UnguessableToken>> ephemeral_ports_;

View file

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

View file

@ -67,7 +67,8 @@ SerialChooserController::SerialChooserController(
: WebContentsObserver(web_contents), : WebContentsObserver(web_contents),
filters_(std::move(filters)), filters_(std::move(filters)),
callback_(std::move(callback)), 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(); origin_ = web_contents->GetMainFrame()->GetLastCommittedOrigin();
chooser_context_ = SerialChooserContextFactory::GetForBrowserContext( chooser_context_ = SerialChooserContextFactory::GetForBrowserContext(
@ -124,7 +125,8 @@ void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
return ptr->token.ToString() == port_id; return ptr->token.ToString() == port_id;
}); });
if (it != ports_.end()) { 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()); RunCallback(it->Clone());
} else { } else {
RunCallback(/*port=*/nullptr); RunCallback(/*port=*/nullptr);

View file

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

View file

@ -190,6 +190,24 @@ bool WebContentsPermissionHelper::CheckSerialAccessPermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), &details); static_cast<content::PermissionType>(PermissionType::SERIAL), &details);
} }
bool WebContentsPermissionHelper::CheckSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const {
return CheckDevicePermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), origin,
&device, render_frame_host);
}
void WebContentsPermissionHelper::GrantSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const {
return GrantDevicePermission(
static_cast<content::PermissionType>(PermissionType::SERIAL), origin,
&device, render_frame_host);
}
bool WebContentsPermissionHelper::CheckHIDAccessPermission( bool WebContentsPermissionHelper::CheckHIDAccessPermission(
const url::Origin& embedding_origin) const { const url::Origin& embedding_origin) const {
base::DictionaryValue details; base::DictionaryValue details;

View file

@ -42,6 +42,14 @@ class WebContentsPermissionHelper
bool CheckMediaAccessPermission(const GURL& security_origin, bool CheckMediaAccessPermission(const GURL& security_origin,
blink::mojom::MediaStreamType type) const; blink::mojom::MediaStreamType type) const;
bool CheckSerialAccessPermission(const url::Origin& embedding_origin) const; bool CheckSerialAccessPermission(const url::Origin& embedding_origin) const;
bool CheckSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const;
void GrantSerialPortPermission(
const url::Origin& origin,
base::Value device,
content::RenderFrameHost* render_frame_host) const;
bool CheckHIDAccessPermission(const url::Origin& embedding_origin) const; bool CheckHIDAccessPermission(const url::Origin& embedding_origin) const;
bool CheckHIDDevicePermission( bool CheckHIDDevicePermission(
const url::Origin& origin, const url::Origin& origin,