tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d2c66790e1eb1254120756f33b7e0af3ed0769a8
parent c14352afe04ae145b13cf0d752beaed5db22f6a2
Author: Jan-Ivar Bruaroey <jib@mozilla.com>
Date:   Fri, 31 Oct 2025 15:54:28 +0000

Bug 1913599 - Interventions for some websites relying on createEncodedStreams(). r=twisniewski,webcompat-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D268638

Diffstat:
Mbrowser/extensions/webcompat/data/interventions.json | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abrowser/extensions/webcompat/injections/js/bug1913599-shim-createencodedstreams.js | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 208 insertions(+), 0 deletions(-)

diff --git a/browser/extensions/webcompat/data/interventions.json b/browser/extensions/webcompat/data/interventions.json @@ -5273,6 +5273,122 @@ } ] }, + "1913599": { + "label": "createEncodedStreams shim test-page", + "bugs": { + "1913599": { + "issue": "broken-meetings", + "matches": ["https://jan-ivar.github.io/*"] + } + }, + "interventions": [ + { + "platforms": ["all"], + "only_channels": ["nightly"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, + "1896361": { + "label": "Meta Messenger", + "bugs": { + "1896361": { + "issue": "broken-meetings", + "matches": ["https://www.facebook.com/*", "https://www.messenger.com/*"] + } + }, + "interventions": [ + { + "platforms": ["all"], + "only_channels": ["nightly"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, + "1896424": { + "label": "meet.google.com legacy group calls (exploratory)", + "bugs": { + "1896424": { + "issue": "broken-meetings", + "matches": ["https://meet.google.com/calling/*"] + } + }, + "interventions": [ + { + "platforms": [], + "only_channels": ["nightly"], + "not_platforms": ["android"], + "ua_string": ["Chrome_with_FxQuantum"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, + "1902507": { + "label": "riverside.fm", + "bugs": { + "1902507": { + "issue": "broken-meetings", + "matches": ["https://riverside.fm/*"] + } + }, + "interventions": [ + { + "platforms": ["all"], + "only_channels": ["nightly"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, + "1902508": { + "label": "goto.com", + "bugs": { + "1902508": { + "issue": "broken-meetings", + "matches": ["https://*.goto.com/*"] + } + }, + "interventions": [ + { + "platforms": ["all"], + "only_channels": ["nightly"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, + "1904141": { + "label": "mega.nz", + "bugs": { + "1904141": { + "issue": "broken-meetings", + "matches": ["https://mega.nz/*"] + } + }, + "interventions": [ + { + "platforms": ["all"], + "only_channels": ["nightly"], + "content_scripts": { + "all_frames": true, + "js": ["bug1913599-shim-createencodedstreams.js"] + } + } + ] + }, "1973019": { "label": "mitsukoshi.mistore.jp", "bugs": { diff --git a/browser/extensions/webcompat/injections/js/bug1913599-shim-createencodedstreams.js b/browser/extensions/webcompat/injections/js/bug1913599-shim-createencodedstreams.js @@ -0,0 +1,92 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * Bug 1913599 - Sites that depend on legacy createEncodedStreams() + * + * Several websites that offer end-to-end encrypted communication in + * Chrome fail to work in Firefox, either ghosting the button that + * offers this feature or erroring with a message like "Voice/Video + * calling is not supported on this browser". + * + * These webpages rely on the older Chrome-only createEncodedStreams() + * API instead of the standard RTCRtpScriptTransform API now available + * in all browsers. The following shims the former using the latter. + * + * Note: this shim has inherent performance limitations being on + * main thread. Websites are encouraged to upgrade to the standard + * worker-based API directly for optimal performance in Firefox. + */ + +/* globals exportFunction, cloneInto */ + +console.info( + "createEncodedStreams() is being shimmed for compatibility reasons. Please consider updating to the RTCRtpScriptTransform API for optimal performance! See https://bugzil.la/1913599 for details." +); + +const win = window.wrappedJSObject; +if (!win.RTCRtpSender.prototype.createEncodedStreams) { + win.RTCRtpSender.prototype.createEncodedStreams = + win.RTCRtpReceiver.prototype.createEncodedStreams = exportFunction( + function createEncodedStreams() { + let onrtctransform; // appease linter + function work() { + const originals = []; + onrtctransform = async ({ transformer: { readable, writable } }) => { + const diverter = new TransformStream({ + transform: (original, controller) => { + originals.push(original); + controller.enqueue(original); + }, + }); + const reinserter = new TransformStream({ + transform: (frame, controller) => { + const original = originals.shift(); + original.data = frame.data; + controller.enqueue(original); + }, + }); + self.postMessage( + { readable: diverter.readable, writable: reinserter.writable }, + { transfer: [diverter.readable, reinserter.writable] } + ); + await readable + .pipeThrough({ + writable: diverter.writable, + readable: reinserter.readable, + }) + .pipeTo(writable); + }; + } + this._worker = new Worker( + `data:text/javascript,(${work.toString()})()` + ); + this.transform = new window.RTCRtpScriptTransform(this._worker); + this._dummy = onrtctransform; // appease linter + const readableNow = new TransformStream(); + const writableNow = new TransformStream(); + const haveData = new Promise( + r => (this._worker.onmessage = e => r(e.data)) + ); + haveData + .then(({ readable }) => readable.pipeTo(readableNow.writable)) + .catch(e => readableNow.writable.abort(e)); + haveData + .then(({ writable }) => writableNow.readable.pipeTo(writable)) + .catch(e => writableNow.readable.cancel(e)); + + const result = new win.Object(); + result.readable = cloneInto(readableNow.readable, window, { + wrapReflectors: true, + }); + result.writable = cloneInto(writableNow.writable, window, { + wrapReflectors: true, + }); + return result; + }, + window + ); +}