summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js
diff options
context:
space:
mode:
authorRuben Rodriguez <ruben@trisquel.info>2022-09-08 20:18:54 -0400
committerRuben Rodriguez <ruben@trisquel.info>2022-09-08 20:18:54 -0400
commit5da28b0f8771834ae208d61431d632875e9f8e7d (patch)
tree688ecaff26197bad8abde617b4947b11d617309e /data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js
parent4a87716686104266a9cccc2d83cc249e312f3673 (diff)
Updated extensions:
* Upgraded Privacy Redirect to 1.1.49 and configured to use the 10 most reliable invidious instances * Removed ViewTube * Added torproxy@icecat.gnu based on 'Proxy toggle' extension * Added jShelter 0.11.1 * Upgraded LibreJS to 7.21.0 * Upgraded HTTPS Everywhere to 2021.7.13 * Upgraded SubmitMe to 1.9
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js166
1 files changed, 166 insertions, 0 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js b/data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js
new file mode 100644
index 0000000..bba9bd0
--- /dev/null
+++ b/data/extensions/jsr@javascriptrestrictor/wrappingS-MCS.js
@@ -0,0 +1,166 @@
+/** \file
+ * \brief Wrappers for Media Capture and Streams standard
+ *
+ * \see https://www.w3.org/TR/mediacapture-streams/
+ *
+ * \author Copyright (C) 2021 Libor Polcak
+ * \author Copyright (C) 2021 Matus Svancar
+ *
+ * \license SPDX-License-Identifier: GPL-3.0-or-later
+ * \license SPDX-License-Identifier: MPL-2.0
+ */
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+//
+// Alternatively, the contents of this file may be used under the terms
+// of the Mozilla Public License, v. 2.0, as described below:
+//
+// 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/.
+//
+// \copyright Copyright (c) 2020 The Brave Authors.
+
+/** \file
+ * This file contains wrapper for MediaDevices.enumerateDevices https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices
+ * \ingroup wrappers
+ *
+ * The goal is to prevent fingerprinting by modifying return value of enumerateDevices.
+ *
+ * This wrapper operates with three levels of protection:
+ *
+ * * (0) - return promise with suffled array
+ * * (1) - return promise with shuffled array with additional 0-4 fake devices
+ * * (2) - return empty promise
+ *
+ * The shuffling approach is inspired by the algorithms created by [Brave Software](https://brave.com)
+ * available [here](https://github.com/brave/brave-core/blob/master/chromium_src/third_party/blink/renderer/modules/mediastream/media_devices.cc).
+ *
+ */
+/*
+
+/*
+ * Create private namespace
+ */
+(function() {
+ /**
+ * \brief change reurn value of enumerateDevices
+ *
+ * Depending on level chosen this function returns:
+ * * (0,1) - promise with modified device array
+ * * (2) - empty promise
+ */
+ function farbleEnumerateDevices() {
+ // to emulate correctly we need a fresh Promise and a fresh Array (with same values) on every call
+ return cachedDevices.then(r => {
+ r = r.concat();
+ return r;
+ });
+ }
+ /**
+ * \brief create and return MediaDeviceInfo object by overlaying a native one with fake properties
+ *
+ * \param browserEnum enum specifying browser 0 - Chrome 1 - Firefox
+ */
+ function fakeDevice(device, fd_prng){
+ var kinds = ["videoinput", "audioinput", "audiooutput"];
+ let browserEnum = device.groupId.length == 44 ? 1 : 0;
+ var deviceId = browserEnum == 1 ? randomString(43, browserEnum, fd_prng)+ "=" : "";
+ let fakeData = {
+ deviceId,
+ groupId: deviceRandomString(browserEnum),
+ kind: kinds[Math.floor(fd_prng() * 3)],
+ label: "",
+ };
+ let json = JSON.stringify(fakeData);
+ fakeData.toJSON = () => json;
+ let overlay = WrapHelper.overlay(device, fakeData);
+ return overlay;
+ }
+ /**
+ * \brief return random string for MediaDeviceInfo parameters
+ *
+ * \param browserEnum enum specifying browser 0 - Chrome 1 - Firefox
+ */
+ function deviceRandomString(browserEnum) {
+ var ret = "";
+ var lengths = [64, 43];
+ var charSets = ["abcdefghijklmnopqrstuvwxyz0123456789","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"];
+ var length = lengths[browserEnum];
+ var charSet = charSets[browserEnum];
+ for ( var i = 0; i < length; i++ ) {
+ ret += charSet.charAt(Math.floor(Math.random() * charSet.length));
+ }
+ if(browserEnum == 1)
+ ret += "=";
+ return ret;
+ }
+ var wrappers = [
+ {
+ parent_object: "MediaDevices.prototype",
+ parent_object_property: "enumerateDevices",
+ wrapped_objects: [{
+ original_name: "MediaDevices.prototype.enumerateDevices",
+ callable_name: "origEnumerateDevices",
+ }],
+ helping_code: farbleEnumerateDevices + shuffleArray + deviceRandomString + randomString + fakeDevice + `
+ var fd_prng = alea(domainHash, "S-MCS MediaDevices.prototype.enumerateDevices");
+ let [level] = args;
+ let cachedDevices = level < 2 ?
+ origEnumerateDevices.call(navigator.mediaDevices).then(result => {
+ try {
+ let shuffle = () => {
+ if (result.length > 1) shuffleArray(result);
+ return result;
+ };
+ if (level === 1 && result.length) {
+ var enumd_prng = alea(domainHash, "MediaDevices.prototype.enumerateDevices");
+ let additional = Math.floor(enumd_prng()*4);
+ if (additional > 0) {
+ let adding = [];
+ while (additional-- > 0) {
+ adding.push(origEnumerateDevices.call(navigator.mediaDevices).then(([device]) => {
+ let fake = fakeDevice(device, fd_prng);
+ result.push(fake);
+ }));
+ }
+ return Promise.all(adding).then(r => {
+ return shuffle();
+ });
+ }
+ }
+ return shuffle();
+ } catch (e) {
+ console.error("Error in farble promise callback", e);
+ throw e;
+ }
+ })
+ : Promise.resolve([]);
+ `,
+ wrapping_function_args: "",
+ /** \fn fake MediaDevices.prototype.enumerateDevices
+ * \brief Modifies return value
+ *
+ * Depending on level chosen this function returns:
+ * * (0) - promise with shuffled array
+ * * (1) - promise with shuffled array with additional 0-4 fake devices
+ * * (2) - empty promise
+ */
+ wrapping_function_body: `
+ return farbleEnumerateDevices();
+ `,
+ },
+ ]
+ add_wrappers(wrappers);
+})()