@fakes/media-devices
Version:
A interactive fake implementation of MediaDevices interface in the browser for testing
155 lines (154 loc) • 6.67 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserConsentTracker = exports.RequestedMediaInput = void 0;
const Deferred_1 = require("./Deferred");
const PermissionStatusFake_1 = require("./permissions/PermissionStatusFake");
var RequestedMediaInput;
(function (RequestedMediaInput) {
RequestedMediaInput["Microphone"] = "Microphone";
RequestedMediaInput["Camera"] = "Camera";
})(RequestedMediaInput = exports.RequestedMediaInput || (exports.RequestedMediaInput = {}));
const resultingPermissionStateFor = (context, action) => {
if (action === 'allow') {
return 'granted';
}
if (action === 'block') {
return 'denied';
}
context.notImplemented.call(`resultingPermissionStateFor() action: ${action}`);
};
class UserConsentTracker {
constructor(_context, _userConsent) {
this._context = _context;
this._userConsent = _userConsent;
this._trackedPermissionStatus = {
camera: [],
microphone: [],
};
this._pendingPermissionRequest = undefined;
}
permissionStatusFor(kind) {
const permissionState = this.permissionStateFor(kind);
const permissionStatus = new PermissionStatusFake_1.PermissionStatusFake(permissionState);
this._trackedPermissionStatus[kind].push(permissionStatus);
return permissionStatus;
}
setPermissionFor(kind, state) {
this._userConsent[kind] = state;
this._trackedPermissionStatus[kind].forEach((permissionStatus) => permissionStatus.updateTo(state));
}
requestPermissionFor(permissionRequest) {
if (this._pendingPermissionRequest) {
this._context.notImplemented.call('There is already a pending permission request, not sure if this can happen');
}
if (this.permissionGrantedFor(permissionRequest.deviceKind)) {
permissionRequest.granted();
return;
}
if (this.permissionBlockedFor(permissionRequest.deviceKind)) {
permissionRequest.blocked();
return;
}
this._pendingPermissionRequest = permissionRequest;
}
permissionStateFor(kind) {
return this._userConsent[kind];
}
permissionGrantedFor(deviceKind) {
if (deviceKind === 'videoinput') {
return this._userConsent.camera === 'granted';
}
if (deviceKind === 'audioinput') {
return this._userConsent.microphone === 'granted';
}
this._context.notImplemented.call(`permissionGrantedFor '${deviceKind}'`);
}
permissionBlockedFor(deviceKind) {
if (deviceKind === 'videoinput') {
return this._userConsent.camera === 'denied';
}
if (deviceKind === 'audioinput') {
return this._userConsent.microphone === 'denied';
}
this._context.notImplemented.call(`permissionGrantedFor '${deviceKind}'`);
}
//todo add an override for the wait time and poll interval
async deviceAccessPrompt() {
const deferred = new Deferred_1.Deferred();
const maximumWaitTime = 1000;
const pollInterval = 100;
let timeWaited = 0;
let pollForPendingPermissionRequest = () => {
if (this._pendingPermissionRequest) {
const complete = (action) => {
if (this._pendingPermissionRequest === undefined) {
throw new Error('there is no pending permission request');
}
const updatedPermission = resultingPermissionStateFor(this._context, action);
if (this._pendingPermissionRequest.deviceKind === 'audioinput') {
this._userConsent.microphone = updatedPermission;
this._trackedPermissionStatus.microphone.forEach((fake) => fake.updateTo(updatedPermission));
}
if (this._pendingPermissionRequest.deviceKind === 'videoinput') {
this._userConsent.camera = updatedPermission;
this._trackedPermissionStatus.camera.forEach((fake) => fake.updateTo(updatedPermission));
}
this._pendingPermissionRequest = undefined;
};
const value = this.permissionPromptFor(this._context, this._pendingPermissionRequest, complete);
deferred.resolve(value);
return;
}
if (timeWaited >= maximumWaitTime) {
deferred.reject(new Error(`After waiting for ${maximumWaitTime} ms there still is no pending permission request`));
return;
}
timeWaited += pollInterval;
// TODO add scheduler abstraction to encapsulate window access
window.setTimeout(pollForPendingPermissionRequest, pollInterval);
};
pollForPendingPermissionRequest();
// check with the Permission Manager if permissions where already rejected
// check if there was a request for media
return deferred.promise;
}
permissionPromptFor(context, permissionRequest, complete) {
const requestedPermissions = [];
if (permissionRequest.deviceKind === 'videoinput' && !this.permissionGrantedFor('videoinput')) {
requestedPermissions.push(RequestedMediaInput.Camera);
}
if (permissionRequest.deviceKind === 'audioinput' && !this.permissionGrantedFor('audioinput')) {
requestedPermissions.push(RequestedMediaInput.Microphone);
}
return new (class {
requestedPermissions() {
return requestedPermissions;
}
takeAction(action) {
complete(action);
if (action === 'allow') {
permissionRequest.granted();
return;
}
if (action === 'block') {
permissionRequest.blocked();
return;
}
context.notImplemented.call(`takeAction '${action}'`);
}
})();
}
accessAllowedFor(kind) {
if (kind === 'audioinput') {
return this._userConsent.microphone === 'granted';
}
if (kind === 'videoinput') {
return this._userConsent.camera === 'granted';
}
if (kind === 'audiooutput') {
return this._userConsent.microphone === 'granted';
}
this._context.notImplemented.call(`not sure how to implement this for ${kind}`);
}
}
exports.UserConsentTracker = UserConsentTracker;