Skip to content

Commit

Permalink
feat: listen for navigator permissions changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kpchoy committed Aug 1, 2024
1 parent bf1f508 commit 437cad3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
9 changes: 9 additions & 0 deletions lib/twilio/audiohelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,15 @@ class AudioHelper extends EventEmitter {
if (isEnumerationSupported) {
this._initializeEnumeration();
}
navigator.permissions.query({ name: 'microphone' as PermissionName }).then((microphonePermissionStatus) => {
if (microphonePermissionStatus.state !== 'granted') {
const handleStateChange = () => {
this._updateAvailableDevices();
microphonePermissionStatus.removeEventListener('change', this._updateAvailableDevices);
}
microphonePermissionStatus.addEventListener('change', handleStateChange);
}
});
}

/**
Expand Down
52 changes: 51 additions & 1 deletion tests/audiohelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ function getUserMedia() {
return Promise.resolve({ id: 'default', getTracks: () => [] });
}

const defaultNavigator = {
permissions: {
query: function() {
return Promise.resolve('prompt');
}
},
mediaDevices: {
enumerateDevices: function(){
return Promise.resolve([]);
}
}
};

describe('AudioHelper', () => {
context('when enumerateDevices is not supported', () => {
const noop = () => {};
Expand Down Expand Up @@ -34,7 +47,7 @@ describe('AudioHelper', () => {
? navigator
: undefined;
HTMLAudioElement = undefined;
navigator = { };
navigator = defaultNavigator;
});

after(() => {
Expand Down Expand Up @@ -68,6 +81,8 @@ describe('AudioHelper', () => {
let availableDevices;
let handlers;
let mediaDevices;
let oldHTMLAudioElement;
let oldNavigator;

beforeEach(() => {
eventObserver = new AudioProcessorEventObserver();
Expand Down Expand Up @@ -100,6 +115,23 @@ describe('AudioHelper', () => {
});
});

before(() => {
oldHTMLAudioElement = typeof HTMLAudioElement !== 'undefined'
? HTMLAudioElement
: undefined;
oldNavigator = typeof navigator !== 'undefined'
? navigator
: undefined;
HTMLAudioElement = undefined;
navigator = defaultNavigator
});

after(() => {
HTMLAudioElement = oldHTMLAudioElement;
navigator = oldNavigator;
});


describe('constructor', () => {
it('should set .isOutputSelectionSupported to true', () => {
assert.equal(audio.isOutputSelectionSupported, true);
Expand All @@ -124,6 +156,24 @@ describe('AudioHelper', () => {
});
});

describe('navigator.permissions', () => {
it('should listen for microphone state changes', () => {
let onChangeHandler = sinon.stub();
let microphonePermissionStatus = {
state: 'prompt',
addEventListener: (eventName, listener) => {
if (eventName === 'change') {
listener()
}
}
};
navigator.permissions.query = () => Promise.resolve(microphonePermissionStatus);
audio = new AudioHelper(onActiveOutputsChanged, onActiveInputChanged, {});
microphonePermissionStatus.addEventListener('change', onChangeHandler);
sinon.assert.calledOnce(onChangeHandler);
})
})

describe('._destroy', () => {
it('should properly dispose the audio instance', () => {
audio._stopDefaultInputDeviceStream = sinon.stub();
Expand Down
5 changes: 5 additions & 0 deletions tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ root.navigator = {
},
platform: 'platform',
userAgent: 'userAgent',
permissions: {
query: function() {
return Promise.resolve('prompt');
}
}
};

root.RTCPeerConnection = root.window.RTCPeerConnection = function() { };
Expand Down

0 comments on commit 437cad3

Please sign in to comment.