From c741bbb4a3b506fdaf289c5b5802f490a505bdb6 Mon Sep 17 00:00:00 2001 From: Thanh Dodeur Date: Wed, 19 Apr 2023 06:12:58 +0000 Subject: [PATCH] [FIX] mail: prevent potential memory leak of AudioContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, The audio context used in media_monitoring was not closed. Which could lead to memory leaks. The source was not connected to the destination in the script processor (used in old browsers that do not support audioWorklets), which would prevent the monitored audio to be used as an audio source. closes odoo/odoo#119124 X-original-commit: f1c3f78dd6e17fe2a3f5a01d8510ca4343b880fe Signed-off-by: Thanh Dodeur (tso) Signed-off-by: Sébastien Theys (seb) --- addons/mail/static/src/rtc/media_monitoring.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/mail/static/src/rtc/media_monitoring.js b/addons/mail/static/src/rtc/media_monitoring.js index d525d46acd1..b50e448fb65 100644 --- a/addons/mail/static/src/rtc/media_monitoring.js +++ b/addons/mail/static/src/rtc/media_monitoring.js @@ -17,7 +17,7 @@ const HUMAN_VOICE_FREQUENCY_RANGE = [80, 1000]; * last time the threshold was exceeded to go back to inactive state, this prevents * stuttering when the speech volume oscillates around the threshold value. * @param {function(boolean):void} [processorOptions.onThreshold] a function to be called when the threshold is passed - * @param {function(number):void} [processorOptions] a function to be called at each tics + * @param {function(number):void} [processorOptions.onTic] a function to be called at each tics * @param {number} [processorOptions.volumeThreshold] the normalized minimum value for audio detection * @returns {Object} returnValue * @returns {function} returnValue.disconnect callback to cleanly end the monitoring @@ -42,10 +42,11 @@ export async function monitorAudio(track, processorOptions) { processor = _loadScriptProcessor(source, audioContext, processorOptions); } - return () => { + return async () => { processor.disconnect(); source.disconnect(); monitoredTrack.stop(); + await audioContext.close(); }; } @@ -77,6 +78,7 @@ function _loadScriptProcessor( source.connect(analyser); const scriptProcessorNode = audioContext.createScriptProcessor(bitSize, 1, 1); analyser.connect(scriptProcessorNode); + analyser.connect(audioContext.destination); analyser.fftsize = bitSize; scriptProcessorNode.connect(audioContext.destination); @@ -155,7 +157,8 @@ async function _loadAudioWorkletProcessor( postAllTics: !!onTic, }, }); - source.connect(thresholdProcessor).connect(audioContext.destination); + source.connect(thresholdProcessor); + source.connect(audioContext.destination); thresholdProcessor.port.onmessage = (event) => { const { isAboveThreshold, volume } = event.data; if (isAboveThreshold !== undefined) {