Skip to content

feat: add allowedWebHIDDevices#32

Merged
ianshade merged 2 commits into
mainfrom
feat/webhid-auto-approval
May 26, 2026
Merged

feat: add allowedWebHIDDevices#32
ianshade merged 2 commits into
mainfrom
feat/webhid-auto-approval

Conversation

@ianshade

Copy link
Copy Markdown
Contributor

About the Contributor

This pull request is posted on behalf of TV 2 Norge.

Type of Contribution

This is a:

Feature

Current Behavior

No way to use webhid devices with Sofie Chef

New Behavior

New ConfigWindow property called allowedWebHIDDevices is added. It allows to define webhid devices to be automatically approved in specific windows. A device in this array will not require explicit user approval when the page displayed in the window tries to access it.

Testing Instructions

  • Connect a webhid-capable device and find a webpage that supports said device
  • Add said page as a window to the config
  • Find your vendor and device ids and configure allowedWebHIDDevices as documented
  • Save the config and verify if the device is immediately operational in the newly opened window

Other Information

Status

  • PR is ready to be reviewed.
  • The functionality has been tested by the author.
  • Relevant unit tests has been added / updated.
  • Relevant documentation (code comments, system documentation) has been added / updated.

this allows specified webhid devices to be automatically approved in specific windows, in order to work without asking the user for permission
@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add allowedWebHIDDevices' directly and clearly summarizes the main feature being added, matching the primary changeset objective.
Description check ✅ Passed The description comprehensively explains the feature purpose, behavior, testing instructions, and background context related to the WebHID functionality being added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/webhid-auto-approval

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ianshade ianshade changed the title feat(EAV-499): add allowedWebHIDDevices feat: add allowedWebHIDDevices Apr 24, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/helpers/WindowHelper.ts (1)

473-485: Usage filter behavior when collections is empty.

If a device is reported with an empty collections array while the config specifies a usagePage/usage filter, .some() returns false and the device is denied. This is the safe default, but for robustness consider logging this case — it's the most common reason a configured device silently fails to auto-approve (hot-plug timing, driver quirks).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/helpers/WindowHelper.ts` around lines 473 - 485, When a device has an
empty collections array but the config specifies a usagePage/usage filter,
_matchesUsageFilter currently returns false silently; add a guarded log when
device.collections.length === 0 and (allowedDevice.usagePage !== undefined ||
allowedDevice.usage !== undefined) to record why the device was denied. Inside
_matchesUsageFilter, before calling device.collections.some(...), emit a
debug/warn log including identifying fields from device (e.g., vendorId,
productId, productName) and the allowedDevice usagePage/usage so hot-plug/driver
timing issues are visible, but keep the existing boolean return behavior
unchanged.
src/helpers/AllWindowsManager.ts (1)

60-62: Origin-based window resolution is ambiguous when multiple windows share an origin.

getWindowForOrigin returns the first matching window by iteration order. This is fine in the common case, but if two configured windows both load the same origin, the wrong window's allowlist may be consulted in setDevicePermissionHandler.

Note: The details object in setDevicePermissionHandler does not include a frame property—only deviceType, origin, and device are available. Frame-based lookup is possible in the select-hid-device event handler (which does receive details.frame), but not in setDevicePermissionHandler. Any fix would require alternative approaches beyond frame-based lookup.

Not urgent for the current single-page-per-window usage pattern, but worth documenting the assumption.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/helpers/AllWindowsManager.ts` around lines 60 - 62, getWindowForOrigin
currently returns the first WindowHelper that matches an origin which is
ambiguous when multiple windows share the same origin; change the API to return
all matching windows and update the permission logic to consult each candidate's
allowlist: add a new method getWindowsForOrigin(origin: string): WindowHelper[]
(or change the existing getWindowForOrigin to return an array) and in
setDevicePermissionHandler iterate the array of WindowHelper instances (from
windowsHandlers) and check each WindowHelper's allowlist/permission logic to
decide which window grants permission; also update the select-hid-device handler
callers to use the new method if needed and preserve backward compatibility or
update all call sites accordingly (refer to getWindowForOrigin, windowsHandlers,
WindowHelper, setDevicePermissionHandler, and select-hid-device).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ChefManager.ts`:
- Around line 108-114: The permission handlers currently deny every non-HID
permission/device by returning false; change both
defaultSession.setPermissionCheckHandler and
defaultSession.setDevicePermissionHandler so they only explicitly handle 'hid'
and otherwise return undefined (or no value) to let Electron/Chromium apply its
default behavior; keep the existing webContents null guard and the window lookup
via this.windowsHelper.getWindowForWebContents and continue to return
window?.hasAllowedWebHIDDevices() for HID checks while returning undefined for
all other permission or device types.

---

Nitpick comments:
In `@src/helpers/AllWindowsManager.ts`:
- Around line 60-62: getWindowForOrigin currently returns the first WindowHelper
that matches an origin which is ambiguous when multiple windows share the same
origin; change the API to return all matching windows and update the permission
logic to consult each candidate's allowlist: add a new method
getWindowsForOrigin(origin: string): WindowHelper[] (or change the existing
getWindowForOrigin to return an array) and in setDevicePermissionHandler iterate
the array of WindowHelper instances (from windowsHandlers) and check each
WindowHelper's allowlist/permission logic to decide which window grants
permission; also update the select-hid-device handler callers to use the new
method if needed and preserve backward compatibility or update all call sites
accordingly (refer to getWindowForOrigin, windowsHandlers, WindowHelper,
setDevicePermissionHandler, and select-hid-device).

In `@src/helpers/WindowHelper.ts`:
- Around line 473-485: When a device has an empty collections array but the
config specifies a usagePage/usage filter, _matchesUsageFilter currently returns
false silently; add a guarded log when device.collections.length === 0 and
(allowedDevice.usagePage !== undefined || allowedDevice.usage !== undefined) to
record why the device was denied. Inside _matchesUsageFilter, before calling
device.collections.some(...), emit a debug/warn log including identifying fields
from device (e.g., vendorId, productId, productName) and the allowedDevice
usagePage/usage so hot-plug/driver timing issues are visible, but keep the
existing boolean return behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f6bd2f7-d86e-4b96-a076-c076f2ed15d0

📥 Commits

Reviewing files that changed from the base of the PR and between de777ff and d9ae9ac.

📒 Files selected for processing (7)
  • README.md
  • docs/WebHID-Configuration.md
  • examples/config-with-webhid.json
  • src/ChefManager.ts
  • src/helpers/AllWindowsManager.ts
  • src/helpers/WindowHelper.ts
  • src/lib/config.ts

Comment thread src/ChefManager.ts
in Electron by default most permissions are pre-approved in the absence of this callback; most still need explicit approvals in other subsequent callbacks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/ChefManager.ts (1)

141-161: select-hid-device always picks the first allowed match — document or revisit if multiple matching devices may be connected.

details.deviceList.find(...) at Line 150 deterministically returns the first allowed device. If a kiosk has two physically connected devices that both satisfy a single allowedWebHIDDevices entry (e.g. two identical control surfaces), the page can never reach the second one — and navigator.hid.requestDevice will not show a chooser since event.preventDefault() was called at Line 142. This is probably intentional for the typical single-device deployment, but worth either:

  • Adding a brief comment stating the auto-select-first policy, or
  • Returning the list filtered (callback isn't a multi-select API in Electron, so a comment is the pragmatic choice).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ChefManager.ts` around lines 141 - 161, The select-hid-device handler
currently auto-selects the first matching device (details.deviceList.find(...)
inside the 'select-hid-device' listener) which prevents the user chooser from
appearing because event.preventDefault() is called; update the code by adding a
concise comment above the 'select-hid-device' handler documenting this
auto-select-first policy and the rationale (e.g., kiosk/single-device use),
referencing the use of details.deviceList.find, window.isAllowedWebHIDDevice,
and the callback(device.deviceId) behavior so future reviewers know this is
intentional (or where to change it if multi-device support is later required).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ChefManager.ts`:
- Around line 108-112: The inline comment misstates intent: update the comment
for defaultSession.setPermissionCheckHandler to state that this handler
intentionally denies the 'deprecated-sync-clipboard-read' permission (to enforce
use of async clipboard APIs) while granting all other non-'hid' permissions,
i.e., it deliberately diverges from Electron's default permissive behavior;
alternatively, if the original goal was to match Electron's default, remove the
custom handler for non-HID permissions and let Electron handle permission checks
instead.

---

Nitpick comments:
In `@src/ChefManager.ts`:
- Around line 141-161: The select-hid-device handler currently auto-selects the
first matching device (details.deviceList.find(...) inside the
'select-hid-device' listener) which prevents the user chooser from appearing
because event.preventDefault() is called; update the code by adding a concise
comment above the 'select-hid-device' handler documenting this auto-select-first
policy and the rationale (e.g., kiosk/single-device use), referencing the use of
details.deviceList.find, window.isAllowedWebHIDDevice, and the
callback(device.deviceId) behavior so future reviewers know this is intentional
(or where to change it if multi-device support is later required).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2c658a2-a6fd-427c-91d9-f51c408d855d

📥 Commits

Reviewing files that changed from the base of the PR and between d9ae9ac and e89cf53.

📒 Files selected for processing (1)
  • src/ChefManager.ts

Comment thread src/ChefManager.ts
@ianshade ianshade merged commit f25f931 into main May 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants