Device Access

    The Web Bluetooth API can be used to communicate with bluetooth devices. In order to use this API in Electron, developers will need to handle the associated with the device request.

    This example demonstrates an Electron application that automatically selects the first available bluetooth device when the button is clicked.

    • index.html
    • main.js
    • renderer.js
    1. const {app, BrowserWindow} = require('electron')
    2. const path = require('path')
    3. function createWindow () {
    4. const mainWindow = new BrowserWindow({
    5. width: 800,
    6. height: 600
    7. })
    8. mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
    9. event.preventDefault()
    10. if (deviceList && deviceList.length > 0) {
    11. callback(deviceList[0].deviceId)
    12. }
    13. })
    14. mainWindow.loadFile('index.html')
    15. }
    16. app.whenReady().then(() => {
    17. createWindow()
    18. app.on('activate', function () {
    19. if (BrowserWindow.getAllWindows().length === 0) createWindow()
    20. })
    21. })
    22. app.on('window-all-closed', function () {
    23. if (process.platform !== 'darwin') app.quit()
    24. })
    1. async function testIt() {
    2. const device = await navigator.bluetooth.requestDevice({
    3. acceptAllDevices: true
    4. })
    5. document.getElementById('device-name').innerHTML = device.name || `ID: ${device.id}`
    6. }
    7. document.getElementById('clickme').addEventListener('click',testIt)

    Open in Fiddle

    • The can be used to select a HID device when a call to navigator.hid.requestDevice is made. Additionally the hid-device-added and events on the Session can be used to handle devices being plugged in or unplugged during the navigator.hid.requestDevice process.
    • ses.setDevicePermissionHandler(handler) can be used to provide default permissioning to devices without first calling for permission to devices via navigator.hid.requestDevice. 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-hid-device event) and then read from that storage with setDevicePermissionHandler.
    • can be used to disable HID access for specific origins.

    By default Electron employs the same blocklist used by Chromium. If you wish to override this behavior, you can do so by setting the disable-hid-blocklist flag:

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

    • index.html
    • main.js
    • renderer.js
    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    6. <title>WebHID API</title>
    7. </head>
    8. <body>
    9. <h1>WebHID API</h1>
    10. <button id="clickme">Test WebHID</button>
    11. <div id="granted-devices"></div>
    12. <h3>HID devices automatically granted access via <i>select-hid-device</i></h3>
    13. <div id="granted-devices2"></div>
    14. </body>
    15. </html>
    1. const {app, BrowserWindow} = require('electron')
    2. const path = require('path')
    3. function createWindow () {
    4. const mainWindow = new BrowserWindow({
    5. width: 800,
    6. height: 600
    7. })
    8. mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
    9. event.preventDefault()
    10. if (details.deviceList && details.deviceList.length > 0) {
    11. callback(details.deviceList[0].deviceId)
    12. }
    13. })
    14. mainWindow.webContents.session.on('hid-device-added', (event, device) => {
    15. console.log('hid-device-added FIRED WITH', device)
    16. })
    17. mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
    18. console.log('hid-device-removed FIRED WITH', device)
    19. })
    20. mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    21. if (permission === 'hid' && details.securityOrigin === 'file:///') {
    22. return true
    23. }
    24. })
    25. mainWindow.webContents.session.setDevicePermissionHandler((details) => {
    26. if (details.deviceType === 'hid' && details.origin === 'file://') {
    27. return true
    28. }
    29. })
    30. mainWindow.loadFile('index.html')
    31. }
    32. app.whenReady().then(() => {
    33. createWindow()
    34. app.on('activate', function () {
    35. if (BrowserWindow.getAllWindows().length === 0) createWindow()
    36. })
    37. })
    38. app.on('window-all-closed', function () {
    39. if (process.platform !== 'darwin') app.quit()
    40. })

    There are several additional APIs for working with the Web Serial API:

    • The serial-port-added and events on the Session can be used to handle devices being plugged in or unplugged during the navigator.serial.requestPort process.
    • ses.setDevicePermissionHandler(handler) 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.
    • can be used to disable serial access for specific origins.

    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 when the Test Web Serial button is clicked.

    • index.html
    • main.js
    • renderer.js
    1. <!DOCTYPE html>
    2. <html>
    3. <meta charset="UTF-8">
    4. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    5. <title>Web Serial API</title>
    6. <h1>Web Serial API</h1>
    7. <button id="clickme">Test Web Serial API</button>
    8. <p>Matching Arduino Uno device: <strong id="device-name""></strong></p>
    9. <script src="./renderer.js"></script>
    10. </body>
    11. </html>
    1. const {app, BrowserWindow} = require('electron')
    2. const path = require('path')
    3. function createWindow () {
    4. const mainWindow = new BrowserWindow({
    5. width: 800,
    6. height: 600
    7. })
    8. mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
    9. event.preventDefault()
    10. if (portList && portList.length > 0) {
    11. callback(portList[0].portId)
    12. } else {
    13. callback('') //Could not find any matching devices
    14. }
    15. })
    16. mainWindow.webContents.session.on('serial-port-added', (event, port) => {
    17. console.log('serial-port-added FIRED WITH', port)
    18. })
    19. mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
    20. console.log('serial-port-removed FIRED WITH', port)
    21. })
    22. mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    23. if (permission === 'serial' && details.securityOrigin === 'file:///') {
    24. return true
    25. }
    26. })
    27. mainWindow.webContents.session.setDevicePermissionHandler((details) => {
    28. if (details.deviceType === 'serial' && details.origin === 'file://') {
    29. return true
    30. }
    31. })
    32. mainWindow.loadFile('index.html')
    33. mainWindow.webContents.openDevTools()
    34. }
    35. app.whenReady().then(() => {
    36. createWindow()
    37. app.on('activate', function () {
    38. if (BrowserWindow.getAllWindows().length === 0) createWindow()
    39. })
    40. })
    41. app.on('window-all-closed', function () {
    42. if (process.platform !== 'darwin') app.quit()

    Open in Fiddle