メインコンテンツへ飛ぶ

デバイスアクセス

Chromium ベースのブラウザのように、Electron はウェブ API を介してデバイスハードウェアへのアクセスを提供します。 ほとんどの場合これらの API はブラウザと同じように動作しますが、いくつかの違いを考慮しなければなりません。 Electronとブラウザの主な違いは、デバイスアクセスが要求されたときに起きることです。 ブラウザでは、ユーザーにポップアップが表示され、ユーザーは個々のデバイスにアクセスを許可できます。 Electron API では、デバイスを自動選択したり開発者が作成したインターフェースを介してユーザーにデバイス選択を促したりするために、開発者が利用できる API を提供しています。

ウェブ Bluetooth API

ウェブ Bluetooth API は、Bluetooth デバイスとの通信に利用できます。 In order to use this API in Electron, developers will need to handle the select-bluetooth-device event on the webContents associated with the device request.

Additionally, ses.setBluetoothPairingHandler(handler) can be used to handle pairing to bluetooth devices on Windows or Linux when additional validation such as a pin is needed.

サンプル

この例では、Test Bluetooth ボタンがクリックされたときに最初に利用可能な Bluetooth デバイスを自動的に選択する、Electron のアプリケーションを示しています。

const { app, BrowserWindow, ipcMain } = require('electron/main')
const path = require('node:path')

let bluetoothPinCallback
let selectBluetoothCallback

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault()
selectBluetoothCallback = callback
const result = deviceList.find((device) => {
return device.deviceName === 'test'
})
if (result) {
callback(result.deviceId)
} else {
// The device wasn't found so we need to either wait longer (eg until the
// device is turned on) or until the user cancels the request
}
})

ipcMain.on('cancel-bluetooth-request', (event) => {
selectBluetoothCallback('')
})

// Listen for a message from the renderer to get the response for the Bluetooth pairing.
ipcMain.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response)
})

mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback
// Send a message to the renderer to prompt the user to confirm the pairing.
mainWindow.webContents.send('bluetooth-pairing-request', details)
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

WebHID API

WebHID API は、キーボードやゲームパッドなどの HID デバイスのアクセスに利用できます。 Electron は、WebHID API と連携するためにいくつかの API を提供しています。

  • The select-hid-device event on the Session can be used to select a HID device when a call to navigator.hid.requestDevice is made. Additionally the hid-device-added and hid-device-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-hid-device event. 注意: これらのイベントは、 select-hid-device からのコールバックが呼び出されるまででのみ発生します。 これらは、一般的な HID デバイスのリスナーとして使用されることを意図していません。
  • ses.setDevicePermissionHandler(handler) は、先に navigator.hid.requestDevice を介して許可の呼び出しをせずとも、デバイスへのデフォルトの権限を提供するために利用できます。 また、Electron のデフォルトの動作では、付与されたデバイスの権限を対応する WebContents が有効の間だけ保存します。 より長期間の保存が必要な場合、開発者は付与されたデバイスのパーミッションを保存し (select-hid-device イベントを処理するときなど)、setDevicePermissionHandler でそのストレージから読み出しできます。
  • ses.setPermissionCheckHandler(handler) を使うと、特定オリジンの HID アクセスを無効にできます。

ブロックリスト

By default Electron employs the same blocklist used by Chromium. この動作を無効にしたい場合は、以下のように disable-hid-blocklist フラグで設定できます。

app.commandLine.appendSwitch('disable-hid-blocklist')

サンプル

This example demonstrates an Electron application that automatically selects HID devices through ses.setDevicePermissionHandler(handler) and through select-hid-device event on the Session when the Test WebHID button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
// Add events to handle devices being added or removed before the callback on
// `select-hid-device` is called.
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
console.log('hid-device-added FIRED WITH', device)
// Optionally update details.deviceList
})

mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
console.log('hid-device-removed FIRED WITH', device)
// Optionally update details.deviceList
})

event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
callback(details.deviceList[0].deviceId)
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'hid' && details.securityOrigin === 'file:///') {
return true
}
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'hid' && details.origin === 'file://') {
return true
}
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

Web シリアル API

Web シリアル API を使用すると、シリアルポートや USB、Bluetooth で接続されたシリアルデバイスにアクセスできます。 In order to use this API in Electron, developers will need to handle the select-serial-port event on the Session associated with the serial port request.

Web シリアル API の利用にあたって更にいくつかの API があります。

  • The serial-port-added and serial-port-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-serial-port event. 注意: これらのイベントは、 select-serial-port からのコールバックが呼び出されるまででのみ発生します。 これらは、一般的なシリアルポートのリスナーとして使用されることを意図していません。
  • ses.setDevicePermissionHandler(handler) は、最初に navigator.serial.requestPort を介してデバイス許可を呼び出さずとも、デフォルト許可の提供に使用できます。 また、Electron のデフォルトの動作では、付与されたデバイスの権限を対応する WebContents が有効の間だけ保存します。 より長期間の保存が必要な場合、開発者は付与されたデバイスのパーミッションを保存し (select-serial-port イベントを処理するときなど)、setDevicePermissionHandler でそのストレージから読み出しできます。
  • ses.setPermissionCheckHandler(handler) を使うと、特定オリジンのシリアルアクセスを無効にできます。

ブロックリスト

By default Electron employs the same blocklist used by Chromium. この動作を無効にしたい場合は、以下のように disable-serial-blocklist フラグで設定できます。

app.commandLine.appendSwitch('disable-serial-blocklist')

サンプル

This example demonstrates an Electron application that automatically selects serial devices through ses.setDevicePermissionHandler(handler) as well as demonstrating selecting the first available Arduino Uno serial device (if connected) through select-serial-port event on the Session when the Test Web Serial button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
// Add listeners to handle ports being added or removed before the callback for `select-serial-port`
// is called.
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
console.log('serial-port-added FIRED WITH', port)
// Optionally update portList to add the new port
})

mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
console.log('serial-port-removed FIRED WITH', port)
// Optionally update portList to remove the port
})

event.preventDefault()
if (portList && portList.length > 0) {
callback(portList[0].portId)
} else {
// eslint-disable-next-line n/no-callback-literal
callback('') // Could not find any matching devices
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'serial' && details.securityOrigin === 'file:///') {
return true
}

return false
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'serial' && details.origin === 'file://') {
return true
}

return false
})

mainWindow.loadFile('index.html')

mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

WebUSB API

WebUSB API は、USB デバイスへのアクセスに利用できます。 Electron は、WebUSB API と連携するためにいくつかの API を提供しています。

  • The select-usb-device event on the Session can be used to select a USB device when a call to navigator.usb.requestDevice is made. Additionally the usb-device-added and usb-device-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-usb-device event. 注意: これら 2 つのイベントは、 select-usb-device からのコールバックが呼び出されるまででのみ発生します。 これらは、一般的な USB デバイスのリスナーとして使用されることを意図していません。
  • The usb-device-revoked event on the Session can be used to respond when device.forget() is called on a USB device.
  • ses.setDevicePermissionHandler(handler) は、最初に navigator.usb.requestDevice を介してデバイス許可を呼び出さずとも、デフォルト許可の提供に使用できます。 また、Electron のデフォルトの動作では、付与されたデバイスの権限を対応する WebContents が有効の間だけ保存します。 より長期間の保存が必要な場合、開発者は許可されたデバイスのパーミッションを (例えば select-usb-device イベントのハンドリングで) 保存し、setDevicePermissionHandler でそのストレージから読み出せます。
  • ses.setPermissionCheckHandler(handler) can be used to disable USB access for specific origins.
  • `ses.setUSBProtectedClassesHandler can be used to allow usage of protected USB classes that are not available by default.

ブロックリスト

By default Electron employs the same blocklist used by Chromium. この動作を無効にしたい場合は、以下のように disable-usb-blocklist フラグで設定できます。

app.commandLine.appendSwitch('disable-usb-blocklist')

サンプル

This example demonstrates an Electron application that automatically selects USB devices (if they are attached) through ses.setDevicePermissionHandler(handler) and through select-usb-device event on the Session when the Test WebUSB button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

let grantedDeviceThroughPermHandler

mainWindow.webContents.session.on('select-usb-device', (event, details, callback) => {
// Add events to handle devices being added or removed before the callback on
// `select-usb-device` is called.
mainWindow.webContents.session.on('usb-device-added', (event, device) => {
console.log('usb-device-added FIRED WITH', device)
// Optionally update details.deviceList
})

mainWindow.webContents.session.on('usb-device-removed', (event, device) => {
console.log('usb-device-removed FIRED WITH', device)
// Optionally update details.deviceList
})

event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
const deviceToReturn = details.deviceList.find((device) => {
return !grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)
})
if (deviceToReturn) {
callback(deviceToReturn.deviceId)
} else {
callback()
}
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'usb' && details.securityOrigin === 'file:///') {
return true
}
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'usb' && details.origin === 'file://') {
if (!grantedDeviceThroughPermHandler) {
grantedDeviceThroughPermHandler = details.device
return true
} else {
return false
}
}
})

mainWindow.webContents.session.setUSBProtectedClassesHandler((details) => {
return details.protectedClasses.filter((usbClass) => {
// Exclude classes except for audio classes
return usbClass.indexOf('audio') === -1
})
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})