mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-08 08:58:38 +01:00
Relax media checks in calling lobbies
This commit is contained in:
@@ -89,7 +89,7 @@ export type PropsDataType = {
|
||||
hasHideMenuBar?: boolean;
|
||||
hasIncomingCallNotifications: boolean;
|
||||
hasLinkPreviews: boolean;
|
||||
hasMediaCameraPermissions: boolean;
|
||||
hasMediaCameraPermissions: boolean | undefined;
|
||||
hasMediaPermissions: boolean;
|
||||
hasMessageAudio: boolean;
|
||||
hasMinimizeToAndStartInSystemTray: boolean;
|
||||
@@ -609,7 +609,7 @@ export function Preferences({
|
||||
onChange={onMediaPermissionsChange}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={hasMediaCameraPermissions}
|
||||
checked={hasMediaCameraPermissions ?? false}
|
||||
label={i18n('icu:mediaCameraPermissionsDescription')}
|
||||
moduleClassName="Preferences__checkbox"
|
||||
name="mediaCameraPermissions"
|
||||
|
||||
@@ -119,7 +119,9 @@ export class SettingsChannel extends EventEmitter {
|
||||
return userConfig.get('mediaPermissions') || false;
|
||||
});
|
||||
ipc.handle('settings:get:mediaCameraPermissions', () => {
|
||||
return userConfig.get('mediaCameraPermissions') || false;
|
||||
// Intentionally returning `undefined` when unset to let app properly
|
||||
// onboard the user.
|
||||
return userConfig.get('mediaCameraPermissions');
|
||||
});
|
||||
ipc.handle('settings:set:mediaPermissions', (_event, value) => {
|
||||
userConfig.set('mediaPermissions', value);
|
||||
|
||||
+34
-19
@@ -92,6 +92,7 @@ import type { ProcessedEnvelope } from '../textsecure/Types.d';
|
||||
import type { GetIceServersResultType } from '../textsecure/WebAPI';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { normalizeGroupCallTimestamp } from '../util/ringrtc/normalizeGroupCallTimestamp';
|
||||
import { requestCameraPermissions } from '../util/callingPermissions';
|
||||
import {
|
||||
AUDIO_LEVEL_INTERVAL_MS,
|
||||
REQUESTED_VIDEO_WIDTH,
|
||||
@@ -351,6 +352,18 @@ async function ensureSystemPermissions({
|
||||
}
|
||||
}
|
||||
|
||||
async function checkCameraPermission(): Promise<boolean> {
|
||||
// If user never went through on boarding, the value is going to be
|
||||
// `undefined` and we should ask for permissions. If it is explicitly `false`
|
||||
// camera is intentionally not available.
|
||||
const cameraPermission = await window.IPC.getMediaCameraPermissions();
|
||||
if (cameraPermission === false) {
|
||||
return false;
|
||||
}
|
||||
const status = await window.IPC.getMediaAccessStatus('camera');
|
||||
return status !== 'denied';
|
||||
}
|
||||
|
||||
function getLogId(
|
||||
options:
|
||||
| {
|
||||
@@ -500,11 +513,11 @@ export class CallingClass {
|
||||
async startCallingLobby({
|
||||
conversation,
|
||||
hasLocalAudio,
|
||||
hasLocalVideo,
|
||||
preferLocalVideo,
|
||||
}: Readonly<{
|
||||
conversation: Readonly<ConversationType>;
|
||||
hasLocalAudio: boolean;
|
||||
hasLocalVideo: boolean;
|
||||
preferLocalVideo: boolean;
|
||||
}>): Promise<
|
||||
| undefined
|
||||
| ({ hasLocalAudio: boolean; hasLocalVideo: boolean } & (
|
||||
@@ -569,6 +582,8 @@ export class CallingClass {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasLocalVideo = preferLocalVideo && (await checkCameraPermission());
|
||||
|
||||
const haveMediaPermissions = await this.#requestPermissions(hasLocalVideo);
|
||||
if (!haveMediaPermissions) {
|
||||
log.info(`${logId}: Permissions were denied, new call not allowed.`);
|
||||
@@ -899,12 +914,12 @@ export class CallingClass {
|
||||
callLinkRootKey,
|
||||
adminPasskey,
|
||||
hasLocalAudio,
|
||||
hasLocalVideo = true,
|
||||
preferLocalVideo = true,
|
||||
}: Readonly<{
|
||||
callLinkRootKey: CallLinkRootKey;
|
||||
adminPasskey: Buffer | undefined;
|
||||
hasLocalAudio: boolean;
|
||||
hasLocalVideo?: boolean;
|
||||
preferLocalVideo?: boolean;
|
||||
}>): Promise<
|
||||
| undefined
|
||||
| {
|
||||
@@ -918,7 +933,17 @@ export class CallingClass {
|
||||
}
|
||||
> {
|
||||
const roomId = getRoomIdFromRootKey(callLinkRootKey);
|
||||
log.info('startCallLinkLobby() for roomId', roomId);
|
||||
const logId = `startCallLinkLobby(roomId=${roomId})`;
|
||||
log.info(`${logId}: starting`);
|
||||
|
||||
const hasLocalVideo = preferLocalVideo && (await checkCameraPermission());
|
||||
|
||||
const haveMediaPermissions = await this.#requestPermissions(hasLocalVideo);
|
||||
if (!haveMediaPermissions) {
|
||||
log.info(
|
||||
`${logId}: Permissions were denied, but allow joining group call`
|
||||
);
|
||||
}
|
||||
|
||||
await ensureSystemPermissions({ hasLocalAudio, hasLocalVideo });
|
||||
|
||||
@@ -937,7 +962,9 @@ export class CallingClass {
|
||||
groupCall.setOutgoingAudioMuted(!hasLocalAudio);
|
||||
groupCall.setOutgoingVideoMuted(!hasLocalVideo);
|
||||
|
||||
drop(this.enableLocalCamera());
|
||||
if (hasLocalVideo) {
|
||||
drop(this.enableLocalCamera());
|
||||
}
|
||||
|
||||
return {
|
||||
callMode: CallMode.Adhoc,
|
||||
@@ -2742,23 +2769,11 @@ export class CallingClass {
|
||||
}
|
||||
}
|
||||
|
||||
async #requestCameraPermissions(): Promise<boolean> {
|
||||
const cameraPermission = await window.IPC.getMediaCameraPermissions();
|
||||
if (!cameraPermission) {
|
||||
await window.IPC.showPermissionsPopup(true, true);
|
||||
|
||||
// Check the setting again (from the source of truth).
|
||||
return window.IPC.getMediaCameraPermissions();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async #requestPermissions(isVideoCall: boolean): Promise<boolean> {
|
||||
const microphonePermission = await requestMicrophonePermissions(true);
|
||||
if (microphonePermission) {
|
||||
if (isVideoCall) {
|
||||
return this.#requestCameraPermissions();
|
||||
return requestCameraPermissions();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -2536,7 +2536,7 @@ function startCallingLobby({
|
||||
conversation,
|
||||
hasLocalAudio:
|
||||
groupCallDeviceCount < MAX_CALL_PARTICIPANTS_FOR_DEFAULT_MUTE,
|
||||
hasLocalVideo: isVideoCall,
|
||||
preferLocalVideo: isVideoCall,
|
||||
});
|
||||
if (!callLobbyData) {
|
||||
throw new Error('Failed to start call lobby');
|
||||
|
||||
@@ -2178,7 +2178,7 @@ describe('calling duck', () => {
|
||||
);
|
||||
|
||||
sinon.assert.calledWithMatch(startCallingLobbyStub, {
|
||||
hasLocalVideo: true,
|
||||
preferLocalVideo: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2189,7 +2189,7 @@ describe('calling duck', () => {
|
||||
})(noop, () => rootState, null);
|
||||
|
||||
sinon.assert.calledWithMatch(startCallingLobbyStub, {
|
||||
hasLocalVideo: true,
|
||||
preferLocalVideo: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2200,7 +2200,7 @@ describe('calling duck', () => {
|
||||
})(noop, () => rootState, null);
|
||||
|
||||
sinon.assert.calledWithMatch(startCallingLobbyStub, {
|
||||
hasLocalVideo: false,
|
||||
preferLocalVideo: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ export async function requestCameraPermissions(): Promise<boolean> {
|
||||
await window.IPC.showPermissionsPopup(true, true);
|
||||
|
||||
// Check the setting again (from the source of truth).
|
||||
return window.IPC.getMediaCameraPermissions();
|
||||
return (await window.IPC.getMediaCameraPermissions()) ?? false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -91,7 +91,7 @@ export type IPCEventsValuesType = {
|
||||
|
||||
// Optional
|
||||
mediaPermissions: boolean;
|
||||
mediaCameraPermissions: boolean;
|
||||
mediaCameraPermissions: boolean | undefined;
|
||||
|
||||
// Only getters
|
||||
|
||||
@@ -734,7 +734,9 @@ export function createIPCEvents(
|
||||
return window.IPC.getMediaAccessStatus(mediaType);
|
||||
},
|
||||
getMediaPermissions: window.IPC.getMediaPermissions,
|
||||
getMediaCameraPermissions: window.IPC.getMediaCameraPermissions,
|
||||
getMediaCameraPermissions: async () => {
|
||||
return (await window.IPC.getMediaCameraPermissions()) || false;
|
||||
},
|
||||
|
||||
setMediaPlaybackDisabled: (playbackDisabled: boolean) => {
|
||||
window.reduxActions?.lightbox.setPlaybackDisabled(playbackDisabled);
|
||||
|
||||
Vendored
+1
-1
@@ -70,7 +70,7 @@ export type IPCType = {
|
||||
getMediaAccessStatus: (
|
||||
mediaType: 'screen' | 'microphone' | 'camera'
|
||||
) => Promise<ReturnType<SystemPreferences['getMediaAccessStatus']>>;
|
||||
getMediaCameraPermissions: () => Promise<boolean>;
|
||||
getMediaCameraPermissions: () => Promise<boolean | undefined>;
|
||||
openSystemMediaPermissions: (
|
||||
mediaType: 'microphone' | 'camera'
|
||||
) => Promise<void>;
|
||||
|
||||
Reference in New Issue
Block a user