new·Earn with mozg — 20% of every monthSend somebody here and take a fifth of every plan payment they make, for as long as they keep paying — not a bounty on the first invoice. Your handle is the link, the window is thirty days, and the commission lands on your balance the second they pay. Free to join: if you have signed in, you already have the link. mozg.sh/earnall news →
mozg.beta
Sign in

Electron · all subjects

session management

110 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

session module overview

The session module manages browser sessions, cookies, cache, proxy settings, and related functionality. It runs in the main process. You can create new Session objects and access the session of existing pages via the WebContents session property or from the session module.

session.fromPartition() method

session.fromPartition(partition[, options]) creates or returns a session from a partition string. The partition parameter is a string; options is an optional object with cache boolean property (default true unless --disable-http-cache switch is used). Returns a Session instance. When there is an existing Session with the same partition, it is returned; otherwise a new Session instance is created with options. If partition starts with 'persist:', the session is persistent and available to all pages with that partition. Without 'persist:' prefix, the page uses an in-memory session. An empty partition returns the app's default session. To create a Session with options, ensure the Session with the partition has never been used before; there is no way to change options of an existing Session object.

session.fromPath() method

session.fromPath(path[, options]) creates or returns a session from an absolute path string. The options parameter is optional and contains cache boolean property (default true unless --disable-http-cache switch is used). Returns a Session instance. When there is an existing Session with the same absolute path, it is returned; otherwise a new Session instance is created with options. The call throws an error if the path is not absolute or if an empty string is provided. To create a Session with options, ensure the Session with the path has never been used before; there is no way to change options of an existing Session object.

session.defaultSession property

session.defaultSession is a Session object representing the default session object of the app, available after app.whenReady is called.

Session class availability

The Session class is not exported from the 'electron' module. It is only available as a return value of other methods in the Electron API.

will-download event

The 'will-download' event is emitted when Electron is about to download an item in webContents. Event parameters are: event Event, item DownloadItem, webContents WebContents. Calling event.preventDefault() will cancel the download and the item will not be available from the next tick of the process.

extension-loaded event

The 'extension-loaded' event is emitted after an extension is loaded. This occurs whenever an extension is added to the 'enabled' set of extensions, including extensions being loaded from Session.loadExtension and extensions being reloaded from a crash or after chrome.runtime.reload() is called. Event parameters are: event Event, extension Extension.

extension-unloaded event

The 'extension-unloaded' event is emitted after an extension is unloaded. This occurs when Session.removeExtension is called. Event parameters are: event Event, extension Extension.

extension-ready event

The 'extension-ready' event is emitted after an extension is loaded and all necessary browser state is initialized to support the start of the extension's background page. Event parameters are: event Event, extension Extension.

file-system-access-restricted event

The 'file-system-access-restricted' event is emitted when file system access is restricted. Event parameters are: event Event, details Object with origin string (the origin that initiated access to the blocked path), isDirectory boolean (whether the path is a directory), path string (the blocked path attempting to be accessed), callback Function with action string parameter. The action can be 'allow' (allow path access despite restricted status), 'deny' (block access request and trigger AbortError), or 'tryAgain' (open a new file picker and allow the user to choose another path).

preconnect event

The 'preconnect' event is emitted when a render process requests preconnection to a URL, generally due to a resource hint. Event parameters are: event Event, preconnectUrl string (the URL being requested for preconnection), allowCredentials boolean (true if the renderer is requesting that the connection include credentials).

spellcheck-dictionary-initialized event

The 'spellcheck-dictionary-initialized' event is emitted when a hunspell dictionary file has been successfully initialized. This occurs after the file has been downloaded. Event parameters are: event Event, languageCode string (the language code of the dictionary file).

spellcheck-dictionary-download-begin event

The 'spellcheck-dictionary-download-begin' event is emitted when a hunspell dictionary file starts downloading. Event parameters are: event Event, languageCode string (the language code of the dictionary file).

spellcheck-dictionary-download-success event

The 'spellcheck-dictionary-download-success' event is emitted when a hunspell dictionary file has been successfully downloaded. Event parameters are: event Event, languageCode string (the language code of the dictionary file).

spellcheck-dictionary-download-failure event

The 'spellcheck-dictionary-download-failure' event is emitted when a hunspell dictionary file download fails. Event parameters are: event Event, languageCode string (the language code of the dictionary file). For details on the failure, collect a netlog and inspect the download request.

select-hid-device event

The 'select-hid-device' event is emitted when a HID device needs to be selected when navigator.hid.requestDevice is called. Event parameters are: event Event, details Object with deviceList HIDDevice[] array and frame WebFrameMain or null (may be null if accessed after the frame has navigated or been destroyed), callback Function with optional deviceId string parameter. Calling callback with deviceId selects that device; passing no arguments cancels the request. Permission can be managed with ses.setPermissionCheckHandler() and ses.setDevicePermissionHandler().

hid-device-added event

The 'hid-device-added' event is emitted after navigator.hid.requestDevice has been called and select-hid-device has fired if a new device becomes available before the callback from select-hid-device is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated with the newly added device. Event parameters are: event Event, details Object with device HIDDevice and frame WebFrameMain or null.

hid-device-removed event

The 'hid-device-removed' event is emitted after navigator.hid.requestDevice has been called and select-hid-device has fired if a device has been removed before the callback from select-hid-device is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated to remove the specified device. Event parameters are: event Event, details Object with device HIDDevice and frame WebFrameMain or null.

hid-device-revoked event

The 'hid-device-revoked' event is emitted after HIDDevice.forget() has been called. This event can be used to help maintain persistent storage of permissions when setDevicePermissionHandler is used. Event parameters are: event Event, details Object with device HIDDevice and optional origin string (the origin that the device has been revoked from).

select-serial-port event

The 'select-serial-port' event is emitted when a serial port needs to be selected when navigator.serial.requestPort is called. Event parameters are: event Event, portList SerialPort[] array, webContents WebContents, callback Function with portId string parameter. Calling callback with portId selects that port; passing an empty string cancels the request. Permission can be managed with ses.setPermissionCheckHandler() using the 'serial' permission.

serial-port-added event

The 'serial-port-added' event is emitted after navigator.serial.requestPort has been called and select-serial-port has fired if a new serial port becomes available before the callback from select-serial-port is called. This event is intended for use when using a UI to ask users to pick a port so that the UI can be updated with the newly added port. Event parameters are: event Event, port SerialPort, webContents WebContents.

serial-port-removed event

The 'serial-port-removed' event is emitted after navigator.serial.requestPort has been called and select-serial-port has fired if a serial port has been removed before the callback from select-serial-port is called. This event is intended for use when using a UI to ask users to pick a port so that the UI can be updated to remove the specified port. Event parameters are: event Event, port SerialPort, webContents WebContents.

serial-port-revoked event

The 'serial-port-revoked' event is emitted after SerialPort.forget() has been called. This event can be used to help maintain persistent storage of permissions when setDevicePermissionHandler is used. Event parameters are: event Event, details Object with port SerialPort, frame WebFrameMain or null (may be null if accessed after the frame has navigated or been destroyed), origin string (the origin that the device has been revoked from).

select-usb-device event

The 'select-usb-device' event is emitted when a USB device needs to be selected when navigator.usb.requestDevice is called. Event parameters are: event Event, details Object with deviceList USBDevice[] array and frame WebFrameMain or null (may be null if accessed after the frame has navigated or been destroyed), callback Function with optional deviceId string parameter. Calling callback with deviceId selects that device; passing no arguments cancels the request. Permission can be managed with ses.setPermissionCheckHandler() and ses.setDevicePermissionHandler().

usb-device-added event

The 'usb-device-added' event is emitted after navigator.usb.requestDevice has been called and select-usb-device has fired if a new device becomes available before the callback from select-usb-device is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated with the newly added device. Event parameters are: event Event, device USBDevice, webContents WebContents.

usb-device-removed event

The 'usb-device-removed' event is emitted after navigator.usb.requestDevice has been called and select-usb-device has fired if a device has been removed before the callback from select-usb-device is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated to remove the specified device. Event parameters are: event Event, device USBDevice, webContents WebContents.

usb-device-revoked event

The 'usb-device-revoked' event is emitted after USBDevice.forget() has been called. This event can be used to help maintain persistent storage of permissions when setDevicePermissionHandler is used. Event parameters are: event Event, details Object with device USBDevice and optional origin string (the origin that the device has been revoked from).

select-webauthn-authenticator event (macOS)

The 'select-webauthn-authenticator' event is emitted on macOS when both touchID and platformPasskeys are configured via app.configureWebAuthn and a WebAuthn request needs to choose which platform authenticator to use. Event parameters are: event Event with relyingPartyId string, authenticators string[] array (possible values are 'touchID' and 'platformPasskeys'), frame WebFrameMain or null; callback Function with optional authenticatorName string parameter. Callback should be called with one of the names from event.authenticators; passing no arguments or a name that does not match cancels the request and the page receives NotAllowedError. The request remains pending until the listener invokes the callback, typically from a try/finally block. If no listener is registered, platformPasskeys is used by default. If only one authenticator is available, this event is not emitted.

select-webauthn-account event

The 'select-webauthn-account' event is emitted when a call to navigator.credentials.get() resolves multiple discoverable WebAuthn credentials and the user must choose one. Event parameters are: event Event, details Object with relyingPartyId string, accounts WebAuthnAccount[] array, frame WebFrameMain or null (may be null if accessed after the frame has navigated or been destroyed); callback Function with optional credentialId string parameter. Callback should be called with the credentialId of the selected account; passing no arguments or a credentialId that does not match cancels the request and the page receives NotAllowedError. The credential request remains pending until the listener invokes the callback, typically from a try/finally block. If no listener is registered for this event, navigator.credentials.get() calls that resolve discoverable Touch ID credentials are cancelled with NotAllowedError, even when only a single credential matches. On macOS, Touch ID platform authenticator surfaces accounts via this event once configured with app.configureWebAuthn.

getCacheSize() method

ses.getCacheSize() returns Promise<Integer> representing the session's current cache size in bytes.

clearCache() method

ses.clearCache() clears the session's HTTP cache. Returns Promise<void> that resolves when the cache clear operation is complete.

clearStorageData() method

ses.clearStorageData([options]) clears storage data. The options parameter is optional and is an Object with origin string (optional, should follow window.location.origin's representation scheme://host:port) and storages string[] (optional, types of storages to clear: cookies, filesystem, indexdb, localstorage, shadercache, serviceworkers, cachestorage; if not specified, all storage types are cleared). Returns Promise<void> that resolves when the storage data has been cleared.

flushStorageData() method

ses.flushStorageData() writes any unwritten DOMStorage data to disk.

setProxy() method

ses.setProxy(config) sets the proxy settings. The config parameter is a ProxyConfig structure. Returns Promise<void> that resolves when the proxy setting process is complete. You may need to call ses.closeAllConnections() to close currently in-flight connections to prevent pooled sockets using previous proxy from being reused by future requests.

resolveHost() method

ses.resolveHost(host, [options]) resolves a hostname. Parameters: host string (hostname to resolve), options Object (optional) with queryType string (requested DNS query type: 'A' fetch only A records, 'AAAA' fetch only AAAA records; if unspecified, resolver will pick A or AAAA based on IPv4/IPv6 settings), source string (the source to use for resolved addresses; default allows resolver to pick appropriate source; values: 'any' default resolver picks appropriate source, 'system' results from system/OS only, 'dns' results only from DNS queries, 'mdns' results only from Multicast DNS queries, 'localOnly' no external sources, results from fast local sources only), cacheUsage string (what DNS cache entries can be used: 'allowed' default results may come from host cache if non-stale, 'staleAllowed' results may come from host cache even if stale, 'disallowed' results will not come from host cache), secureDnsPolicy string (controls resolver's Secure DNS behavior: 'allow' default, 'disable'). Returns Promise<ResolvedHost> resolving with the resolved IP addresses for the host.

resolveProxy() method

ses.resolveProxy(url) returns Promise<string> that resolves with the proxy information for the given URL.

forceReloadProxyConfig() method

ses.forceReloadProxyConfig() returns Promise<void> that resolves when all internal states of proxy service are reset and the latest proxy configuration is reapplied if already available. The pac script will be fetched from pacScript again if the proxy mode is pac_script.

setDownloadPath() method

ses.setDownloadPath(path) sets the download saving directory. The path parameter is a string specifying the download location. By default, the download directory will be the Downloads folder under the respective app folder.

enableNetworkEmulation() method

ses.enableNetworkEmulation(options) emulates network with given configuration for the session. The options parameter is an Object with offline boolean (optional, whether to emulate network outage, defaults to false), latency Double (optional, RTT in ms, defaults to 0 which disables latency throttling), downloadThroughput Double (optional, download rate in Bps, defaults to 0 which disables download throttling), uploadThroughput Double (optional, upload rate in Bps, defaults to 0 which disables upload throttling).

preconnect() method

ses.preconnect(options) preconnects the given number of sockets to an origin. The options parameter is an Object with url string (URL for preconnect; only the origin is relevant for opening the socket) and numSockets number (optional, number of sockets to preconnect, must be between 1 and 6, defaults to 1).

closeAllConnections() method

ses.closeAllConnections() closes all connections. Returns Promise<void> that resolves when all connections are closed. Note: It will terminate or fail all requests currently in flight.

fetch() method

ses.fetch(input[, init]) sends a request, similarly to how fetch() works in the renderer, using Chromium's network stack. Parameters: input string or GlobalRequest, init optional RequestInit object with additional bypassCustomProtocolHandlers boolean property. Returns Promise<GlobalResponse>. By default, requests made with net.fetch can be made to custom protocols, file:, and will trigger webRequest handlers if present. When bypassCustomProtocolHandlers option is set in RequestInit, custom protocol handlers will not be called for this request, allowing forwarding an intercepted request to the built-in handler; webRequest handlers will still be triggered. Limitations: net.fetch() does not support data: or blob: schemes; the integrity option value is ignored; the .type and .url values of the returned Response object are incorrect.

disableNetworkEmulation() method

ses.disableNetworkEmulation() disables any network emulation already active for the session and resets to the original network configuration.

setCertificateVerifyProc() method

ses.setCertificateVerifyProc(proc) sets the certificate verify proc for session. The proc parameter is a Function or null. When called, proc is invoked with proc(request, callback) whenever a server certificate verification is requested. The request Object has hostname string, certificate Certificate, validatedCertificate Certificate, isIssuedByKnownRoot boolean (true if Chromium recognises the root CA as standard root, otherwise the certificate was probably generated by MITM proxy with locally installed root), verificationResult string (OK if certificate is trusted, otherwise an error like CERT_REVOKED), errorCode Integer. The callback Function is invoked with verificationResult Integer (certificate error codes from Chromium; special codes: 0 indicates success and disables Certificate Transparency verification, -2 indicates failure, -3 uses verification result from chromium). Calling callback(0) accepts the certificate, calling callback(-2) rejects it. Calling setCertificateVerifyProc(null) reverts to default certificate verify proc. The result of this procedure is cached by the network service.

setPermissionRequestHandler() method

ses.setPermissionRequestHandler(handler) sets the handler which responds to permission requests for the session. The handler parameter is a Function or null. Handler signature: handler(webContents, permission, callback, details). The webContents is WebContents requesting the permission; if request comes from subframe, use requestingUrl to check request origin. The permission string is the type of requested permission. The callback Function is invoked with permissionGranted boolean (true to allow, false to deny). The details parameter is a PermissionRequest, FilesystemPermissionRequest, MediaAccessPermissionRequest, or OpenExternalPermissionRequest structure with additional information. Calling callback(true) allows the permission; callback(false) denies it. To clear the handler, call setPermissionRequestHandler(null). You must also implement setPermissionCheckHandler to get complete permission handling. Most web APIs do a permission check and then make a permission request if the check is denied.

setPermissionCheckHandler() method

ses.setPermissionCheckHandler(handler) sets the handler which responds to permission checks for the session. The handler parameter is a Function<boolean> or null. Handler signature: handler(webContents, permission, requestingOrigin, details) returning boolean. The webContents is WebContents or null checking the permission; if request comes from subframe use requestingUrl to check request origin; all cross origin sub frames making permission checks pass null webContents, while certain other permission checks like notifications pass null. The permission string is the type of permission check. The requestingOrigin string is the origin URL of the permission check. The details Object has embeddingOrigin string (optional, origin of the frame embedding the frame that made the permission check, only set for cross-origin sub frames), securityOrigin string (optional, security origin of the media check), mediaType string (optional, type of media access: video, audio, unknown), requestingUrl string (optional, last URL the requesting frame loaded, not provided for cross-origin sub frames), isMainFrame boolean (whether the frame making the request is the main frame), filePath string (optional, path of fileSystem request), isDirectory boolean (optional, whether fileSystem request is a directory), fileAccessType string (optional, access type of fileSystem request: writable or readable). Returning true allows the permission, false rejects it. You must also implement setPermissionRequestHandler for complete permission handling. To clear the handler, call setPermissionCheckHandler(null).

Permission check types for setPermissionCheckHandler

Permission check types for setPermissionCheckHandler include: ar, automatic-fullscreen, background-fetch, background-sync, captured-surface-control, clipboard-read, clipboard-sanitized-write, deprecated-sync-clipboard-read, display-capture, fileSystem, fullscreen, geolocation, geolocation-approximate, hand-tracking, hid, idle-detection, keyboardLock, local-fonts, local-network, local-network-access, loopback-network, media, mediaKeySystem, midi, midiSysex, nfc, notifications, openExternal, payment-handler, periodic-background-sync, persistent-storage, pointerLock, screen-wake-lock, sensors, serial, smart-card, speaker-selection, storage-access, system-wake-lock, top-level-storage-access, usb, vr, web-app-installation, web-printing, window-management, unknown.

setDisplayMediaRequestHandler() method

ses.setDisplayMediaRequestHandler(handler[, opts]) sets the handler called when web content requests access to display media via navigator.mediaDevices.getDisplayMedia API. The handler parameter is a Function or null. Handler signature: handler(request, callback). The request Object has frame WebFrameMain or null (frame requesting access, may be null if accessed after frame navigated or destroyed), securityOrigin String (origin of page making the request), videoRequested Boolean (true if web content requested video stream), audioRequested Boolean (true if web content requested audio stream), userGesture Boolean (whether user gesture was active when request triggered). The callback Function is invoked with streams Object containing video Object or WebFrameMain (optional) with id String (stream id, usually from DesktopCapturerSource) and name String (stream name, usually from DesktopCapturerSource), audio String or WebFrameMain (optional, if string: loopback or loopbackWithMute for system audio on Windows only; if WebFrameMain: capture audio from that frame), enableLocalEcho Boolean (optional, if audio is WebFrameMain and true, local playback not muted; default false). The opts parameter is optional Object (macOS Experimental) with useSystemPicker Boolean (true if available native system picker should be used; default false; macOS 15+ only). Passing null resets the handler to default state. Use desktopCapturer API to choose which stream(s) to grant access to.

setDevicePermissionHandler() method

ses.setDevicePermissionHandler(handler) sets the handler for device permissions. The handler parameter is a Function<boolean> or null. Handler signature: handler(details) returning boolean. The details Object has deviceType string (type of device: hid, serial, or usb), origin string (origin URL of the device permission check), device property (HIDDevice, SerialPort, or USBDevice depending on deviceType).

Example: Access session from WebContents

To access the session of a BrowserWindow, use win.webContents.session. To get the user agent: const ses = win.webContents.session; console.log(ses.getUserAgent());

Example: Create session from partition

To create a session from a partition: const { session } = require('electron'); const ses = session.fromPartition('persist:name'); console.log(ses.getUserAgent());

Example: Handle will-download event

const { session } = require('electron'); session.defaultSession.on('will-download', (event, item, webContents) => { event.preventDefault(); require('got')(item.getURL()).then((response) => { require('node:fs').writeFileSync('/somewhere', response.body); }); });

Example: Handle file-system-access-restricted event

const { app, dialog, BrowserWindow, session } = require('electron'); async function createWindow () { const mainWindow = new BrowserWindow(); await mainWindow.loadURL('https://buzzfeed.com'); session.defaultSession.on('file-system-access-restricted', async (e, details, callback) => { const { origin, path } = details; const { response } = await dialog.showMessageBox({ message: `Are you sure you want ${origin} to open restricted path ${path}?`, title: 'File System Access Restricted', buttons: ['Choose a different folder', 'Allow', 'Cancel'], cancelId: 2 }); if (response === 0) { callback('tryAgain'); } else if (response === 1) { callback('allow'); } else { callback('deny'); } }); mainWindow.webContents.executeJavaScript(`window.showDirectoryPicker({ id: 'electron-demo', mode: 'readwrite', startIn: 'downloads', }).catch(e => { console.log(e); })`, true); } app.whenReady().then(() => { createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); }); app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit(); });

Example: Enable network emulation

const win = new BrowserWindow(); // To emulate a GPRS connection with 50kbps throughput and 500 ms latency: win.webContents.session.enableNetworkEmulation({ latency: 500, downloadThroughput: 6400, uploadThroughput: 6400 }); // To emulate a network outage: win.webContents.session.enableNetworkEmulation({ offline: true });

Example: Set certificate verify proc

const { BrowserWindow } = require('electron'); const win = new BrowserWindow(); win.webContents.session.setCertificateVerifyProc((request, callback) => { const { hostname } = request; if (hostname === 'github.com') { callback(0); } else { callback(-2); } });

Example: Set permission request handler

const { session } = require('electron'); session.fromPartition('some-partition').setPermissionRequestHandler((webContents, permission, callback) => { if (webContents.getURL() === 'some-host' && permission === 'notifications') { return callback(false); // denied. } callback(true); });

Example: Handle media and display-capture permissions separately

const { session } = require('electron'); session.defaultSession.setPermissionRequestHandler((webContents, permission, callback, details) => { if (permission === 'media') { // Camera / microphone. details.mediaTypes lists which was requested. return callback(true); } if (permission === 'display-capture') { // Screen, window or tab capture. return callback(new URL(details.requestingUrl).origin === 'https://meet.example.com'); } callback(false); });

Example: Select HID device

const { app, BrowserWindow } = require('electron'); let win = null; app.whenReady().then(() => { win = new BrowserWindow(); win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => { if (permission === 'hid') { return true; } return false; }); const grantedDevices = fetchGrantedDevices(); win.webContents.session.setDevicePermissionHandler((details) => { if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'hid') { if (details.device.vendorId === 123 && details.device.productId === 345) { return true; } 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-hid-device', (event, details, callback) => { event.preventDefault(); const selectedDevice = details.deviceList.find((device) => { return device.vendorId === 9025 && device.productId === 67; }); callback(selectedDevice?.deviceId); }); });

Example: Select serial port

const { app, BrowserWindow } = require('electron'); let win = null; app.whenReady().then(() => { win = new BrowserWindow({ width: 800, height: 600 }); win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => { if (permission === 'serial') { return true; } return false; }); 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) { return true; } 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) => { event.preventDefault(); const selectedPort = portList.find((device) => { return device.vendorId === '9025' && device.productId === '67'; }); if (!selectedPort) { callback(''); } else { callback(selectedPort.portId); } }); });

Example: Select USB device

const { app, BrowserWindow } = require('electron'); let win = null; app.whenReady().then(() => { win = new BrowserWindow(); win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => { if (permission === 'usb') { return true; } return false; }); const grantedDevices = fetchGrantedDevices(); win.webContents.session.setDevicePermissionHandler((details) => { if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'usb') { if (details.device.vendorId === 123 && details.device.productId === 345) { return true; } 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-usb-device', (event, details, callback) => { event.preventDefault(); const selectedDevice = details.deviceList.find((device) => { return device.vendorId === 9025 && device.productId === 67; }); if (selectedDevice) { grantedDevices.push(selectedDevice); updateGrantedDevices(grantedDevices); } callback(selectedDevice?.deviceId); }); });

Give your agent this brain