Skip to content

fix: reject getDisplayMedia calls without user gesture on server view#3313

Open
arijiiiitttt wants to merge 2 commits into
RocketChat:masterfrom
arijiiiitttt:Fixes-#3308
Open

fix: reject getDisplayMedia calls without user gesture on server view#3313
arijiiiitttt wants to merge 2 commits into
RocketChat:masterfrom
arijiiiitttt:Fixes-#3308

Conversation

@arijiiiitttt
Copy link
Copy Markdown

@arijiiiitttt arijiiiitttt commented Apr 29, 2026

Closes #3308

Problem

Since 4.14.0, the screen share picker opens automatically on every app launch on Linux/Wayland/Flatpak. PR #3266 registered
setDisplayMediaRequestHandler on every server view webview. The Rocket.Chat web app calls getDisplayMedia() at load time as a capability probe, and the newly registered handler catches this and opens the picker unconditionally.

Fix

Added a userGesture guard inside setupServerViewDisplayMedia() in serverViewScreenSharing.ts. If the request has no user gesture (i.e. triggered automatically by the page), it is silently rejected and the picker is not shown.

Testing

  • Verified the code compiles cleanly
  • Verified screen sharing still works when manually triggered on Windows
  • Could not reproduce the Linux/Wayland/Flatpak environment locally — please verify on that setup

Summary by CodeRabbit

  • Bug Fixes

    • Enforced user-gesture requirement for screen-sharing requests so attempts without explicit user interaction are promptly rejected; failures fall back to disabling video to keep sessions secure.
  • Refactor

    • Adjusted handler registration formatting for improved consistency.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4fc31093-58bd-41a4-ab44-ff329d360109

📥 Commits

Reviewing files that changed from the base of the PR and between 29b637d and e12d8a5.

📒 Files selected for processing (1)
  • src/screenSharing/serverViewScreenSharing.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/screenSharing/serverViewScreenSharing.ts

Walkthrough

The display-media request handler in server-view screen sharing now rejects requests that lack request.userGesture by immediately invoking the callback with an empty result; requests with a user gesture continue to be handled (delegation and existing error handling preserved).

Changes

Cohort / File(s) Summary
Display Media Request Handling
src/screenSharing/serverViewScreenSharing.ts
Added a check for request.userGesture; if absent the handler responds immediately with an empty result (cb({} as any)), otherwise it delegates to currentProvider.handleDisplayMediaRequest(cb) and retains the existing try/catch logging and { video: false } fallback.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: rejecting getDisplayMedia calls without user gesture on server view, which directly addresses the regression.
Linked Issues check ✅ Passed The code change implements the suggested fix by adding a userGesture guard to prevent getDisplayMedia calls without user gesture, directly addressing the requirements in issue #3308.
Out of Scope Changes check ✅ Passed All changes in the pull request are scoped to fixing the regression in #3308 by adding the userGesture check, with no unrelated modifications present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 29, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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/screenSharing/serverViewScreenSharing.ts (1)

74-85: Unify and type the deny response instead of mixed as any payloads.

Using both cb({} as any) and cb({ video: false } as any) makes behavior/API compatibility harder to reason about and can mask Electron typing drift. Prefer one deny path helper with a verified payload shape.

Suggested hardening
       guestWebContents.session.setDisplayMediaRequestHandler(
   (request, cb) => {
+    const deny = () => cb({ video: false } as any);
     if (!request.userGesture) {
-      cb({} as any);
+      deny();
       return;
     }
     try {
       currentProvider.handleDisplayMediaRequest(cb);
     } catch (error) {
       console.error(
         'Server view screen sharing: error in handler:',
         error
       );
-      cb({ video: false } as any);
+      deny();
     }
   },
   { useSystemPicker: false }
 );
For the Electron version used by this project, what is the documented callback payload to deny/cancel a request in `session.setDisplayMediaRequestHandler`? Is `callback({})` supported, or should denial be done with `callback({ video: false })` or another explicit shape?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screenSharing/serverViewScreenSharing.ts` around lines 74 - 85, Unify the
denial path by replacing the mixed payloads with a single typed helper (e.g.,
denyDisplayMedia) and use it everywhere instead of cb({} as any) or cb({ video:
false } as any); implement denyDisplayMedia(cb:
DisplayMediaRequestHandlerCallback) that invokes cb with the explicit,
Electron-typed denial payload (use the exact callback payload shape from
Electron's typings) and update the branch that currently calls cb({} as any) and
the catch block that calls cb({ video: false } as any) to call
denyDisplayMedia(cb); ensure currentProvider.handleDisplayMediaRequest(cb)
remains unchanged.
🤖 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/screenSharing/serverViewScreenSharing.ts`:
- Around line 72-88: The callback block passed to the screen-sharing API is
mis-indented and causing Prettier lint failures; reformat the anonymous callback
so its opening line, body (if check for request.userGesture, try/catch,
console.error, and cb calls), and the trailing options object ({
useSystemPicker: false }) follow project indentation rules—locate the block
around the call that invokes currentProvider.handleDisplayMediaRequest and the
surrounding callback, align braces and statements consistently (ensure the
if/return, try/catch and cb(...) lines are indented one level inside the
callback) to satisfy Prettier.

---

Nitpick comments:
In `@src/screenSharing/serverViewScreenSharing.ts`:
- Around line 74-85: Unify the denial path by replacing the mixed payloads with
a single typed helper (e.g., denyDisplayMedia) and use it everywhere instead of
cb({} as any) or cb({ video: false } as any); implement denyDisplayMedia(cb:
DisplayMediaRequestHandlerCallback) that invokes cb with the explicit,
Electron-typed denial payload (use the exact callback payload shape from
Electron's typings) and update the branch that currently calls cb({} as any) and
the catch block that calls cb({ video: false } as any) to call
denyDisplayMedia(cb); ensure currentProvider.handleDisplayMediaRequest(cb)
remains 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: b70bda59-4b65-4acd-b3e3-13826c0a11c5

📥 Commits

Reviewing files that changed from the base of the PR and between e1fe77e and 29b637d.

📒 Files selected for processing (1)
  • src/screenSharing/serverViewScreenSharing.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from @rocket.chat/fuselage for all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments

Files:

  • src/screenSharing/serverViewScreenSharing.ts
🪛 ESLint
src/screenSharing/serverViewScreenSharing.ts

[error] 72-72: Insert ······

(prettier/prettier)


[error] 73-73: Insert ······

(prettier/prettier)


[error] 74-74: Replace ······ with ············

(prettier/prettier)


[error] 75-75: Insert ······

(prettier/prettier)


[error] 76-76: Insert ······

(prettier/prettier)


[error] 77-77: Insert ······

(prettier/prettier)


[error] 78-78: Insert ······

(prettier/prettier)


[error] 79-79: Insert ······

(prettier/prettier)


[error] 80-80: Replace ······ with ············

(prettier/prettier)


[error] 81-81: Insert ······

(prettier/prettier)


[error] 82-82: Insert ······

(prettier/prettier)


[error] 83-83: Replace ······ with ············

(prettier/prettier)


[error] 84-84: Replace ······ with ············

(prettier/prettier)


[error] 85-85: Insert ······

(prettier/prettier)


[error] 86-86: Insert ······

(prettier/prettier)


[error] 87-87: Insert ······

(prettier/prettier)


[error] 88-88: Insert ······

(prettier/prettier)

🔇 Additional comments (1)
src/screenSharing/serverViewScreenSharing.ts (1)

72-76: Nice fix: user-gesture gate addresses the startup picker regression.

This guard cleanly blocks automatic getDisplayMedia() probes from opening the picker while preserving user-initiated flow.

Comment thread src/screenSharing/serverViewScreenSharing.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Screen share picker opens on every app launch (regression since 4.14.0, likely PR #3266)

2 participants