[MM-59044] Add per-server permission check for screen sharing (#3097)

This commit is contained in:
Devin Binnie 2024-07-19 15:52:07 -04:00 committed by GitHub
parent 7c27a6d1cd
commit 198b1afe88
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 0 deletions

View file

@ -114,10 +114,12 @@
"main.permissionsManager.checkPermission.dialog.detail.media": "{appName} will use the microphone and camera for calls and voice messages. You can always change this later in your computer's settings.", "main.permissionsManager.checkPermission.dialog.detail.media": "{appName} will use the microphone and camera for calls and voice messages. You can always change this later in your computer's settings.",
"main.permissionsManager.checkPermission.dialog.detail.notifications": "{appName} will send you notifications for messages and calls. You can configure your notification preferences in Settings.", "main.permissionsManager.checkPermission.dialog.detail.notifications": "{appName} will send you notifications for messages and calls. You can configure your notification preferences in Settings.",
"main.permissionsManager.checkPermission.dialog.detail.openExternal": "{appName} will open the requested link in an external application. If you do not trust this link, or do not recognize it, click Deny. You can always change this later in your computer's settings.", "main.permissionsManager.checkPermission.dialog.detail.openExternal": "{appName} will open the requested link in an external application. If you do not trust this link, or do not recognize it, click Deny. You can always change this later in your computer's settings.",
"main.permissionsManager.checkPermission.dialog.detail.screenShare": "{appName} will use this permission to share your screen for calls. You can always change this later in your computer's settings.",
"main.permissionsManager.checkPermission.dialog.message.geolocation": "{appName} ({url}) would like to access your location.", "main.permissionsManager.checkPermission.dialog.message.geolocation": "{appName} ({url}) would like to access your location.",
"main.permissionsManager.checkPermission.dialog.message.media": "{appName} ({url}) would like to access the microphone and camera.", "main.permissionsManager.checkPermission.dialog.message.media": "{appName} ({url}) would like to access the microphone and camera.",
"main.permissionsManager.checkPermission.dialog.message.notifications": "{appName} ({url}) would like to send you notifications.", "main.permissionsManager.checkPermission.dialog.message.notifications": "{appName} ({url}) would like to send you notifications.",
"main.permissionsManager.checkPermission.dialog.message.openExternal": "{appName} ({url}) would like permission to open the following URL: {externalURL}", "main.permissionsManager.checkPermission.dialog.message.openExternal": "{appName} ({url}) would like permission to open the following URL: {externalURL}",
"main.permissionsManager.checkPermission.dialog.message.screenShare": "{appName} ({url}) would like to be able to view your screen.",
"main.permissionsManager.checkPermission.dialog.title": "Permission Requested", "main.permissionsManager.checkPermission.dialog.title": "Permission Requested",
"main.tray.tray.expired": "Session Expired: Please sign in to continue receiving notifications.", "main.tray.tray.expired": "Session Expired: Please sign in to continue receiving notifications.",
"main.tray.tray.mention": "You have been mentioned", "main.tray.tray.mention": "You have been mentioned",
@ -170,6 +172,7 @@
"renderer.components.newServerModal.permissions.notifications": "Notifications", "renderer.components.newServerModal.permissions.notifications": "Notifications",
"renderer.components.newServerModal.permissions.notifications.mac": "You may also need to enable notifications in macOS for Mattermost. Click <link>here</link> to open the System Preferences.", "renderer.components.newServerModal.permissions.notifications.mac": "You may also need to enable notifications in macOS for Mattermost. Click <link>here</link> to open the System Preferences.",
"renderer.components.newServerModal.permissions.notifications.windows": "You may also need to enable notifications in Windows for Mattermost. Click <link>here</link> to open the Notification Settings.", "renderer.components.newServerModal.permissions.notifications.windows": "You may also need to enable notifications in Windows for Mattermost. Click <link>here</link> to open the Notification Settings.",
"renderer.components.newServerModal.permissions.screenShare": "Screen Share",
"renderer.components.newServerModal.permissions.title": "Permissions", "renderer.components.newServerModal.permissions.title": "Permissions",
"renderer.components.newServerModal.serverDisplayName": "Server Display Name", "renderer.components.newServerModal.serverDisplayName": "Server Display Name",
"renderer.components.newServerModal.serverDisplayName.description": "The name of the server displayed on your desktop app tab bar.", "renderer.components.newServerModal.serverDisplayName.description": "The name of the server displayed on your desktop app tab bar.",

View file

@ -45,6 +45,7 @@ const supportedPermissionTypes = [
'fullscreen', 'fullscreen',
'openExternal', 'openExternal',
'clipboard-sanitized-write', 'clipboard-sanitized-write',
'screenShare',
]; ];
// permissions that require a dialog // permissions that require a dialog
@ -53,6 +54,7 @@ const authorizablePermissionTypes = [
'geolocation', 'geolocation',
'notifications', 'notifications',
'openExternal', 'openExternal',
'screenShare',
]; ];
type PermissionsByOrigin = { type PermissionsByOrigin = {
@ -239,10 +241,12 @@ t('main.permissionsManager.checkPermission.dialog.message.media');
t('main.permissionsManager.checkPermission.dialog.message.geolocation'); t('main.permissionsManager.checkPermission.dialog.message.geolocation');
t('main.permissionsManager.checkPermission.dialog.message.notifications'); t('main.permissionsManager.checkPermission.dialog.message.notifications');
t('main.permissionsManager.checkPermission.dialog.message.openExternal'); t('main.permissionsManager.checkPermission.dialog.message.openExternal');
t('main.permissionsManager.checkPermission.dialog.message.screenShare');
t('main.permissionsManager.checkPermission.dialog.detail.media'); t('main.permissionsManager.checkPermission.dialog.detail.media');
t('main.permissionsManager.checkPermission.dialog.detail.geolocation'); t('main.permissionsManager.checkPermission.dialog.detail.geolocation');
t('main.permissionsManager.checkPermission.dialog.detail.notifications'); t('main.permissionsManager.checkPermission.dialog.detail.notifications');
t('main.permissionsManager.checkPermission.dialog.detail.openExternal'); t('main.permissionsManager.checkPermission.dialog.detail.openExternal');
t('main.permissionsManager.checkPermission.dialog.detail.screenShare');
let permissionsManager = new PermissionsManager(permissionsJson); let permissionsManager = new PermissionsManager(permissionsJson);

View file

@ -17,6 +17,7 @@ import {
CALLS_PLUGIN_ID, CALLS_PLUGIN_ID,
} from 'common/utils/constants'; } from 'common/utils/constants';
import urlUtils from 'common/utils/url'; import urlUtils from 'common/utils/url';
import PermissionsManager from 'main/permissionsManager';
import { import {
resetScreensharePermissionsMacOS, resetScreensharePermissionsMacOS,
openScreensharePermissionsSettingsMacOS, openScreensharePermissionsSettingsMacOS,
@ -56,6 +57,9 @@ jest.mock('common/utils/url', () => ({
getFormattedPathName: jest.fn(), getFormattedPathName: jest.fn(),
parseURL: jest.fn(), parseURL: jest.fn(),
})); }));
jest.mock('main/permissionsManager', () => ({
doPermissionRequest: jest.fn(),
}));
jest.mock('main/windows/mainWindow', () => ({ jest.mock('main/windows/mainWindow', () => ({
get: jest.fn(), get: jest.fn(),
focus: jest.fn(), focus: jest.fn(),
@ -599,6 +603,11 @@ describe('main/windows/callsWidgetWindow', () => {
arr.push([`${item.name}_${view.name}`, { arr.push([`${item.name}_${view.name}`, {
sendToRenderer: jest.fn(), sendToRenderer: jest.fn(),
webContentsId: index, webContentsId: index,
view: {
server: {
url: new URL('http://server-1.com'),
},
},
}]); }]);
}); });
return arr; return arr;
@ -606,6 +615,7 @@ describe('main/windows/callsWidgetWindow', () => {
const views = new Map(map); const views = new Map(map);
beforeEach(() => { beforeEach(() => {
PermissionsManager.doPermissionRequest.mockReturnValue(Promise.resolve(true));
ViewManager.getViewByWebContentsId.mockImplementation((id) => [...views.values()].find((view) => view.webContentsId === id)); ViewManager.getViewByWebContentsId.mockImplementation((id) => [...views.values()].find((view) => view.webContentsId === id));
callsWidgetWindow.mainView = views.get('server-1_view-1'); callsWidgetWindow.mainView = views.get('server-1_view-1');
}); });

View file

@ -27,6 +27,7 @@ import {Logger} from 'common/log';
import {CALLS_PLUGIN_ID, MINIMUM_CALLS_WIDGET_HEIGHT, MINIMUM_CALLS_WIDGET_WIDTH} from 'common/utils/constants'; import {CALLS_PLUGIN_ID, MINIMUM_CALLS_WIDGET_HEIGHT, MINIMUM_CALLS_WIDGET_WIDTH} from 'common/utils/constants';
import {getFormattedPathName, isCallsPopOutURL, parseURL} from 'common/utils/url'; import {getFormattedPathName, isCallsPopOutURL, parseURL} from 'common/utils/url';
import Utils from 'common/utils/util'; import Utils from 'common/utils/util';
import PermissionsManager from 'main/permissionsManager';
import { import {
composeUserAgent, composeUserAgent,
getLocalPreload, getLocalPreload,
@ -403,6 +404,11 @@ export class CallsWidgetWindow {
} }
} }
if (!await PermissionsManager.doPermissionRequest(view.webContentsId, 'screenShare', {requestingUrl: view.view.server.url.toString(), isMainFrame: false})) {
log.warn('screen share permissions disallowed', view.webContentsId, view.view.server.url.toString());
return [];
}
const screenPermissionsErrArgs = ['screen-permissions', this.callID]; const screenPermissionsErrArgs = ['screen-permissions', this.callID];
return desktopCapturer.getSources(opts).then((sources) => { return desktopCapturer.getSources(opts).then((sources) => {

View file

@ -577,6 +577,16 @@ class NewServerModal extends React.PureComponent<Props, State> {
defaultMessage='Location' defaultMessage='Location'
/> />
</Toggle> </Toggle>
<Toggle
isChecked={this.state.permissions.screenShare?.allowed}
onChange={this.handleChangePermission('screenShare')}
>
<i className='icon icon-monitor-share'/>
<FormattedMessage
id='renderer.components.newServerModal.permissions.screenShare'
defaultMessage='Screen Share'
/>
</Toggle>
</> </>
} }
</Modal.Body> </Modal.Body>