Send error to global widget if missing screen sharing permissions (#2554)

This commit is contained in:
Claudio Costa
2023-02-16 10:20:50 -06:00
committed by GitHub
parent 5cc2e98a1d
commit 7127ec153a
4 changed files with 121 additions and 4 deletions

View File

@@ -137,6 +137,7 @@ export const CALLS_WIDGET_SHARE_SCREEN = 'calls-widget-share-screen';
export const CALLS_WIDGET_CHANNEL_LINK_CLICK = 'calls-widget-channel-link-click';
export const CALLS_JOINED_CALL = 'calls-joined-call';
export const CALLS_POPOUT_FOCUS = 'calls-popout-focus';
export const CALLS_ERROR = 'calls-error';
export const REQUEST_CLEAR_DOWNLOADS_DROPDOWN = 'request-clear-downloads-dropdown';
export const CLOSE_DOWNLOADS_DROPDOWN = 'close-downloads-dropdown';

View File

@@ -12,6 +12,7 @@ import {
CALLS_WIDGET_RESIZE,
CALLS_WIDGET_SHARE_SCREEN,
CALLS_WIDGET_CHANNEL_LINK_CLICK,
CALLS_ERROR,
DESKTOP_SOURCES_RESULT,
DESKTOP_SOURCES_MODAL_REQUEST,
DISPATCH_GET_DESKTOP_SOURCES,
@@ -75,3 +76,13 @@ ipcRenderer.on(CALLS_WIDGET_SHARE_SCREEN, (event, message) => {
window.location.origin,
);
});
ipcRenderer.on(CALLS_ERROR, (event, message) => {
window.postMessage(
{
type: CALLS_ERROR,
message,
},
window.location.origin,
);
});

View File

@@ -4,7 +4,7 @@
/* eslint-disable max-lines */
'use strict';
import {app, systemPreferences} from 'electron';
import {app, systemPreferences, desktopCapturer} from 'electron';
import Config from 'common/config';
import {getTabViewName, TAB_MESSAGING} from 'common/tabs/TabView';
@@ -39,6 +39,10 @@ jest.mock('electron', () => ({
},
systemPreferences: {
getUserDefault: jest.fn(),
getMediaAccessStatus: jest.fn(() => 'granted'),
},
desktopCapturer: {
getSources: jest.fn(),
},
}));
@@ -1042,6 +1046,84 @@ describe('main/windows/windowManager', () => {
});
});
describe('handleGetDesktopSources', () => {
const windowManager = new WindowManager();
windowManager.viewManager = {
showByName: jest.fn(),
getCurrentView: jest.fn(),
};
beforeEach(() => {
windowManager.viewManager.views = new Map();
windowManager.callsWidgetWindow = new CallsWidgetWindow();
windowManager.callsWidgetWindow.win = {
webContents: {
send: jest.fn(),
},
};
});
afterEach(() => {
jest.resetAllMocks();
Config.teams = [];
});
it('should send sources back', async () => {
jest.spyOn(desktopCapturer, 'getSources').mockResolvedValue([
{
id: 'screen0',
thumbnail: {
toDataURL: jest.fn(),
},
},
{
id: 'window0',
thumbnail: {
toDataURL: jest.fn(),
},
},
]);
await windowManager.handleGetDesktopSources(null, 'widget', null);
expect(windowManager.callsWidgetWindow.win.webContents.send).toHaveBeenCalledWith('desktop-sources-result', [
{
id: 'screen0',
},
{
id: 'window0',
},
]);
});
it('should send error with no sources', async () => {
jest.spyOn(desktopCapturer, 'getSources').mockResolvedValue([]);
await windowManager.handleGetDesktopSources(null, 'widget', null);
expect(windowManager.callsWidgetWindow.win.webContents.send).toHaveBeenCalledWith('calls-error', {
err: 'screen-permissions',
});
});
it('should send error with no permissions', async () => {
jest.spyOn(desktopCapturer, 'getSources').mockResolvedValue([
{
id: 'screen0',
thumbnail: {
toDataURL: jest.fn(),
},
},
]);
jest.spyOn(systemPreferences, 'getMediaAccessStatus').mockReturnValue('denied');
await windowManager.handleGetDesktopSources(null, 'widget', null);
expect(systemPreferences.getMediaAccessStatus).toHaveBeenCalledWith('screen');
expect(windowManager.callsWidgetWindow.win.webContents.send).toHaveBeenCalledWith('calls-error', {
err: 'screen-permissions',
});
});
});
describe('handleDesktopSourcesModalRequest', () => {
const windowManager = new WindowManager();
windowManager.switchServer = jest.fn();

View File

@@ -34,6 +34,7 @@ import {
CALLS_LEAVE_CALL,
DESKTOP_SOURCES_MODAL_REQUEST,
CALLS_WIDGET_CHANNEL_LINK_CLICK,
CALLS_ERROR,
} from 'common/communication';
import urlUtils from 'common/utils/url';
import {SECOND} from 'common/utils/constants';
@@ -822,16 +823,33 @@ export class WindowManager {
return event.sender.id;
}
handleGetDesktopSources = async (event: IpcMainEvent, viewName: string, opts: Electron.SourcesOptions) => {
handleGetDesktopSources = (event: IpcMainEvent, viewName: string, opts: Electron.SourcesOptions) => {
log.debug('WindowManager.handleGetDesktopSources', {viewName, opts});
const globalWidget = viewName === 'widget' && this.callsWidgetWindow;
const view = this.viewManager?.views.get(viewName);
if (!view && !globalWidget) {
return;
return Promise.resolve();
}
desktopCapturer.getSources(opts).then((sources) => {
return desktopCapturer.getSources(opts).then((sources) => {
let hasScreenPermissions = true;
if (systemPreferences.getMediaAccessStatus) {
const screenPermissions = systemPreferences.getMediaAccessStatus('screen');
log.debug('screenPermissions', screenPermissions);
if (screenPermissions === 'denied') {
log.info('no screen sharing permissions');
hasScreenPermissions = false;
}
}
if (!hasScreenPermissions || !sources?.length) {
this.callsWidgetWindow?.win.webContents.send(CALLS_ERROR, {
err: 'screen-permissions',
});
return;
}
const message = sources.map((source) => {
return {
id: source.id,
@@ -845,6 +863,11 @@ export class WindowManager {
} else {
this.callsWidgetWindow?.win.webContents.send(DESKTOP_SOURCES_RESULT, message);
}
}).catch((err) => {
log.error('desktopCapturer.getSources failed', err);
this.callsWidgetWindow?.win.webContents.send(CALLS_ERROR, {
err: 'screen-permissions',
});
});
}