electron/docs/tutorial/devices.md
John Kleinschmidt 6aece4a83d
feat: add support for WebHID (#30213)
* feat: add support for WebHID

* Apply suggestions from code review

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* Address review feedback

* Address review feedback

* chore: clear granted_devices on navigation

Also added test to verify devices get cleared

* fixup testing for device clear

* make sure navigator.hid.getDevices is run on correct frame

* clear granted devices on RenderFrameHost deletion/change

* manage device permissions per RenderFrameHost

This change makes sure we don't clear device permission prematurely due to child frame navigation

* Update shell/browser/api/electron_api_web_contents.cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* apply review feedback from @zcbenz

* Match upstream ObjectMap

This change matches what ObjectPermissionContextBase uses to cache object permissions: https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/object_permission_context_base.h;l=52;drc=8f95b5eab2797a3e26bba299f3b0df85bfc98bf5;bpv=1;bpt=0

The main reason for this was to resolve this crash on Win x64:
ok 2 WebContentsView doesn't crash when GCed during allocation
Received fatal exception EXCEPTION_ACCESS_VIOLATION
Backtrace:
        gin::WrappableBase::SecondWeakCallback [0x00007FF6F2AFA005+133] (o:\gin\wrappable.cc:53)
        v8::internal::GlobalHandles::InvokeSecondPassPhantomCallbacks [0x00007FF6F028F9AB+171] (o:\v8\src\handles\global-handles.cc:1400)
        v8::internal::GlobalHandles::InvokeSecondPassPhantomCallbacksFromTask [0x00007FF6F028F867+391] (o:\v8\src\handles\global-handles.cc:1387)
        node::PerIsolatePlatformData::RunForegroundTask [0x00007FF6F3B4D065+317] (o:\third_party\electron_node\src\node_platform.cc:415)
        node::PerIsolatePlatformData::FlushForegroundTasksInternal [0x00007FF6F3B4C424+776] (o:\third_party\electron_node\src\node_platform.cc:479)
        uv_run [0x00007FF6F2DDD07C+492] (o:\third_party\electron_node\deps\uv\src\win\core.c:609)
        electron::NodeBindings::UvRunOnce [0x00007FF6EEE1E036+294] (o:\electron\shell\common\node_bindings.cc:631)
        base::TaskAnnotator::RunTask [0x00007FF6F2318A19+457] (o:\base\task\common\task_annotator.cc:178)
        base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl [0x00007FF6F2E6F553+963] (o:\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:361)
        base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork [0x00007FF6F2E6EC69+137] (o:\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:266)
        base::MessagePumpForUI::DoRunLoop [0x00007FF6F235AA58+216] (o:\base\message_loop\message_pump_win.cc:221)
        base::MessagePumpWin::Run [0x00007FF6F235A01A+106] (o:\base\message_loop\message_pump_win.cc:79)
        base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run [0x00007FF6F2E702DA+682] (o:\base\task\sequence_manager\thread_controller_with_message_pump_impl.cc:470)
        base::RunLoop::Run [0x00007FF6F22F95BA+842] (o:\base\run_loop.cc:136)
        content::BrowserMainLoop::RunMainMessageLoop [0x00007FF6F14423CC+208] (o:\content\browser\browser_main_loop.cc:990)
        content::BrowserMainRunnerImpl::Run [0x00007FF6F144402F+143] (o:\content\browser\browser_main_runner_impl.cc:153)
        content::BrowserMain [0x00007FF6F143F911+257] (o:\content\browser\browser_main.cc:49)
        content::RunBrowserProcessMain [0x00007FF6EFFA7D18+112] (o:\content\app\content_main_runner_impl.cc:608)
        content::ContentMainRunnerImpl::RunBrowser [0x00007FF6EFFA8CF4+1220] (o:\content\app\content_main_runner_impl.cc:1104)
        content::ContentMainRunnerImpl::Run [0x00007FF6EFFA87C9+393] (o:\content\app\content_main_runner_impl.cc:971)
        content::RunContentProcess [0x00007FF6EFFA73BD+733] (o:\content\app\content_main.cc:394)
        content::ContentMain [0x00007FF6EFFA79E1+54] (o:\content\app\content_main.cc:422)
        wWinMain [0x00007FF6EECA1535+889] (o:\electron\shell\app\electron_main.cc:291)
        __scrt_common_main_seh [0x00007FF6F6F88482+262] (d:\A01\_work\6\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
        BaseThreadInitThunk [0x00007FFEC0087034+20]
        RtlUserThreadStart [0x00007FFEC1F02651+33]
✗ Electron tests failed with code 0xc0000005.

Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2021-09-23 20:00:11 +09:00

4.5 KiB

Device Access

Like Chromium based browsers, Electron provides access to device hardware through web APIs. For the most part these APIs work like they do in a browser, but there are some differences that need to be taken into account. The primary difference between Electron and browsers is what happens when device access is requested. In a browser, users are presented with a popup where they can grant access to an individual device. In Electron APIs are provided which can be used by a developer to either automatically pick a device or prompt users to pick a device via a developer created interface.

Web Bluetooth API

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 select-bluetooth-device event on the webContents associated with the device request.

Example

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


WebHID API

The WebHID API can be used to access HID devices such as keyboards and gamepads. Electron provides several APIs for working with the WebHID 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 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.
  • ses.setPermissionCheckHandler(handler) can be used to disable HID access for specific origins.

Blocklist

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:

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

Example

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.


Web Serial API

The Web Serial API can be used to access serial devices that are connected via serial port, USB, or 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.

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

Example

This example demonstrates an Electron application that automatically selects 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.