tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2024
- 1 participants
- 250 discussions

[Git][tpo/applications/tor-browser][tor-browser-128.2.0esr-14.0-1] 2 commits: fixup! Temporary commit: manually place generated wasm files
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch tor-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
d1f3724c by onyinyang at 2024-09-02T11:25:51+02:00
fixup! Temporary commit: manually place generated wasm files
Bug #42502: Adds methods to handle key rotations in lox_wasm and updates
wasm-bindgen to account for a version update
- - - - -
d83a1b45 by onyinyang at 2024-09-02T11:26:01+02:00
fixup! Lox integration
Bug #42502 Imports lox-wasm functions to handle Key Rotations
Updates pubkey function to fetch Lox pubkeys regularly and check
for changes. If changes are detected, Lox credentials are immediately
updated. See further explanation here:
https://gitlab.torproject.org/tpo/anti-censorship/lox/-/merge_requests/183
- - - - -
3 changed files:
- toolkit/components/lox/Lox.sys.mjs
- toolkit/components/lox/content/lox_wasm_bg.wasm
- toolkit/components/lox/lox_wasm.jsm
Changes:
=====================================
toolkit/components/lox/Lox.sys.mjs
=====================================
@@ -9,6 +9,7 @@ const lazy = {};
ChromeUtils.defineLazyGetter(lazy, "logger", () => {
return console.createInstance({
+ maxLogLevel: "Warn",
maxLogLevelPref: "lox.log_level",
prefix: "Lox",
});
@@ -50,6 +51,8 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
handle_check_blockage: "resource://gre/modules/lox_wasm.jsm",
blockage_migration: "resource://gre/modules/lox_wasm.jsm",
handle_blockage_migration: "resource://gre/modules/lox_wasm.jsm",
+ check_lox_pubkeys_update: "resource://gre/modules/lox_wasm.jsm",
+ handle_update_cred: "resource://gre/modules/lox_wasm.jsm",
});
export const LoxTopics = Object.freeze({
@@ -61,7 +64,7 @@ export const LoxTopics = Object.freeze({
// Whenever we gain a new upgrade or blockage event, or clear events.
UpdateEvents: "lox:update-events",
// Whenever the next unlock *might* have changed.
- // getNextUnlock uses #credentials and #constants, sow ill fire when either
+ // getNextUnlock uses #credentials and #constants, so will fire when either
// value changes.
UpdateNextUnlock: "lox:update-next-unlock",
// Whenever the remaining invites *might* have changed.
@@ -194,7 +197,7 @@ class LoxImpl {
observe(subject, topic) {
switch (topic) {
- case lazy.TorSettingsTopics.SettingsChanged:
+ case lazy.TorSettingsTopics.SettingsChanged: {
const { changes } = subject.wrappedJSObject;
if (
changes.includes("bridges.enabled") ||
@@ -218,6 +221,7 @@ class LoxImpl {
}
}
break;
+ }
case lazy.TorSettingsTopics.Ready:
// Set the initial #activeLoxId.
this.#updateActiveLoxId();
@@ -403,24 +407,98 @@ class LoxImpl {
);
}
+ /**
+ * Update Lox credential after Lox key rotation
+ * Do not call directly, use #getPubKeys() instead to start the update only
+ * once
+ *
+ * @param {string} prevkeys The public keys we are replacing
+ */
+ async #updatePubkeys(prevkeys) {
+ let pubKeys;
+ try {
+ pubKeys = await this.#makeRequest("pubkeys", []);
+ } catch (error) {
+ lazy.logger.debug("Failed to get pubkeys", error);
+ // Make the next call try again.
+ this.#pubKeyPromise = null;
+ if (!this.#pubKeys) {
+ throw error;
+ }
+ return;
+ }
+ const prevKeys = this.#pubKeys;
+ if (prevKeys !== null) {
+ // check if the lox pubkeys have changed and update the lox
+ // credentials if so
+ let lox_cred_req;
+ try {
+ lox_cred_req = JSON.parse(
+ lazy.check_lox_pubkeys_update(
+ JSON.stringify(pubKeys),
+ prevkeys,
+ this.#getCredentials(this.#activeLoxId)
+ )
+ );
+ } catch (error) {
+ lazy.logger.debug("Check lox pubkey update failed", error);
+ // Make the next call try again.
+ this.#pubKeyPromise = null;
+ return;
+ }
+ if (lox_cred_req.updated) {
+ lazy.logger.debug(
+ `Lox pubkey updated, update Lox credential "${this.#activeLoxId}"`
+ );
+ let response;
+ try {
+ // TODO: If this call doesn't succeed due to a networking error, the Lox
+ // credential may be in an unusable state (spent but not updated)
+ // until this request can be completed successfully (and until Lox
+ // is refactored to send repeat responses:
+ // https://gitlab.torproject.org/tpo/anti-censorship/lox/-/issues/74)
+ response = await this.#makeRequest("updatecred", lox_cred_req.req);
+ } catch (error) {
+ lazy.logger.debug("Lox cred update failed.", error);
+ // Make the next call try again.
+ this.#pubKeyPromise = null;
+ return;
+ }
+ if (response.hasOwnProperty("error")) {
+ lazy.logger.error(response.error);
+ this.#pubKeyPromise = null;
+ lazy.logger.debug(
+ `Error response to Lox pubkey update request: "${response.error}", reverting to old pubkeys`
+ );
+ return;
+ }
+ let cred;
+ try {
+ cred = lazy.handle_update_cred(
+ lox_cred_req.req,
+ JSON.stringify(response),
+ pubKeys
+ );
+ } catch (error) {
+ lazy.logger.debug("Unable to handle updated Lox cred", error);
+ // Make the next call try again.
+ this.#pubKeyPromise = null;
+ return;
+ }
+ this.#changeCredentials(this.#activeLoxId, cred);
+ }
+ }
+ // If we arrive here we haven't had other errors before, we can actually
+ // store the new public key.
+ this.#pubKeys = JSON.stringify(pubKeys);
+ this.#store();
+ }
+
async #getPubKeys() {
// FIXME: We are always refetching #pubKeys, #encTable and #constants once
// per session, but they may change more frequently. tor-browser#42502
if (this.#pubKeyPromise === null) {
- this.#pubKeyPromise = this.#makeRequest("pubkeys", [])
- .then(pubKeys => {
- this.#pubKeys = JSON.stringify(pubKeys);
- this.#store();
- })
- .catch(error => {
- lazy.logger.debug("Failed to get pubkeys", error);
- // Make the next call try again.
- this.#pubKeyPromise = null;
- // We always try to update, but if that doesn't work fall back to stored data
- if (!this.#pubKeys) {
- throw error;
- }
- });
+ this.#pubKeyPromise = this.#updatePubkeys();
}
await this.#pubKeyPromise;
}
@@ -508,6 +586,11 @@ class LoxImpl {
lazy.logger.warn("No loxId for the background task");
return;
}
+
+ // Attempt to update pubkeys each time background tasks are run
+ // this should catch key rotations (ideally some days) prior to the next
+ // credential update
+ await this.#getPubKeys();
try {
const levelup = await this.#attemptUpgrade(loxId);
if (levelup) {
@@ -631,13 +714,16 @@ class LoxImpl {
}
/**
- * Redeems a Lox invitation to obtain a credential and bridges.
+ * Redeems a Lox open invitation to obtain an untrusted Lox credential
+ * and 1 bridge.
*
- * @param {string} invite A Lox invitation.
+ * @param {string} invite A Lox open invitation.
* @returns {string} The loxId of the associated credential on success.
*/
async redeemInvite(invite) {
this.#assertInitialized();
+ // It's fine to get pubkey here without a delay since the user will not have a Lox
+ // credential yet
await this.#getPubKeys();
let request = await lazy.open_invite(JSON.parse(invite).invite);
let response = await this.#makeRequest(
@@ -691,7 +777,18 @@ class LoxImpl {
*/
async generateInvite(loxId) {
this.#assertInitialized();
- await this.#getPubKeys();
+ // Check for pubkey update prior to invitation generation
+ // to avoid invite being generated with outdated keys
+ // TODO: it's still possible the keys could be rotated before the invitation is redeemed
+ // so updating the invite after issuing should also be possible somehow
+ if (this.#pubKeys == null) {
+ // TODO: Set pref to call this function after some time #43086
+ // See also: https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests…
+ await this.#getPubKeys();
+ throw new LoxError(
+ `Pubkeys just updated, retry later to avoid deanonymization`
+ );
+ }
await this.#getEncTable();
let level = this.#getLevel(loxId);
if (level < 1) {
@@ -740,7 +837,6 @@ class LoxImpl {
}
async #blockageMigration(loxId) {
- await this.#getPubKeys();
let request;
try {
request = lazy.check_blockage(this.#getCredentials(loxId), this.#pubKeys);
@@ -783,11 +879,10 @@ class LoxImpl {
/** Attempts to upgrade the currently saved Lox credential.
* If an upgrade is available, save an event in the event list.
*
- * @param {string} loxId Lox ID
- * @returns {boolean} Whether a levelup event occurred.
+ * @param {string} loxId Lox ID
+ * @returns {boolean} Whether a levelup event occurred.
*/
async #attemptUpgrade(loxId) {
- await this.#getPubKeys();
await this.#getEncTable();
await this.#getConstants();
let level = this.#getLevel(loxId);
@@ -821,60 +916,84 @@ class LoxImpl {
* @returns {boolean} Whether the credential was successfully migrated.
*/
async #trustMigration(loxId) {
- await this.#getPubKeys();
- return new Promise(resolve => {
- let request = "";
- try {
- request = lazy.trust_promotion(
- this.#getCredentials(loxId),
- this.#pubKeys
- );
- } catch (err) {
- lazy.logger.debug("Not ready to upgrade");
- resolve(false);
- }
- this.#makeRequest("trustpromo", JSON.parse(request).request)
- .then(response => {
- if (response.hasOwnProperty("error")) {
- lazy.logger.error("Error response from trustpromo", response.error);
- resolve(false);
- }
- lazy.logger.debug("Got promotion cred", response, request);
- let promoCred = lazy.handle_trust_promotion(
- request,
- JSON.stringify(response)
- );
- lazy.logger.debug("Formatted promotion cred");
- request = lazy.trust_migration(
- this.#getCredentials(loxId),
- promoCred,
- this.#pubKeys
- );
- lazy.logger.debug("Formatted migration request");
- this.#makeRequest("trustmig", JSON.parse(request).request)
- .then(response => {
- if (response.hasOwnProperty("error")) {
- lazy.logger.error(
- "Error response from trustmig",
- response.error
- );
- resolve(false);
- }
- lazy.logger.debug("Got new credential");
- let cred = lazy.handle_trust_migration(request, response);
- this.#changeCredentials(loxId, cred);
- resolve(true);
- })
- .catch(err => {
- lazy.logger.error("Failed trust migration", err);
- resolve(false);
- });
- })
- .catch(err => {
- lazy.logger.error("Failed trust promotion", err);
- resolve(false);
- });
- });
+ if (this.#pubKeys == null) {
+ // TODO: Set pref to call this function after some time #43086
+ // See also: https://gitlab.torproject.org/tpo/applications/tor-browser/-/merge_requests…
+ this.#getPubKeys();
+ return false;
+ }
+ let request, response;
+ try {
+ request = lazy.trust_promotion(
+ this.#getCredentials(loxId),
+ this.#pubKeys
+ );
+ } catch (err) {
+ lazy.logger.debug("Not ready to upgrade", err);
+ return false;
+ }
+ try {
+ response = await this.#makeRequest(
+ "trustpromo",
+ JSON.parse(request).request
+ );
+ } catch (err) {
+ lazy.logger.error("Failed trust promotion", err);
+ return false;
+ }
+ if (response.hasOwnProperty("error")) {
+ lazy.logger.error("Error response from trustpromo", response.error);
+ return false;
+ }
+ lazy.logger.debug("Got promotion cred", response, request);
+ let promoCred;
+ try {
+ promoCred = lazy.handle_trust_promotion(
+ request,
+ JSON.stringify(response)
+ );
+ lazy.logger.debug("Formatted promotion cred");
+ } catch (err) {
+ lazy.logger.error(
+ "Unable to handle trustpromo response properly",
+ response.error
+ );
+ return false;
+ }
+ try {
+ request = lazy.trust_migration(
+ this.#getCredentials(loxId),
+ promoCred,
+ this.#pubKeys
+ );
+ lazy.logger.debug("Formatted migration request");
+ } catch (err) {
+ lazy.logger.error("Failed to generate trust migration request", err);
+ return false;
+ }
+ try {
+ response = await this.#makeRequest(
+ "trustmig",
+ JSON.parse(request).request
+ );
+ } catch (err) {
+ lazy.logger.error("Failed trust migration", err);
+ return false;
+ }
+ if (response.hasOwnProperty("error")) {
+ lazy.logger.error("Error response from trustmig", response.error);
+ return false;
+ }
+ lazy.logger.debug("Got new credential");
+ let cred;
+ try {
+ cred = lazy.handle_trust_migration(request, response);
+ } catch (err) {
+ lazy.logger.error("Failed to handle response from trustmig", err);
+ return false;
+ }
+ this.#changeCredentials(loxId, cred);
+ return true;
}
/**
=====================================
toolkit/components/lox/content/lox_wasm_bg.wasm
=====================================
Binary files a/toolkit/components/lox/content/lox_wasm_bg.wasm and b/toolkit/components/lox/content/lox_wasm_bg.wasm differ
=====================================
toolkit/components/lox/lox_wasm.jsm
=====================================
@@ -1,4 +1,4 @@
-var EXPORTED_SYMBOLS = ["set_panic_hook", "open_invite", "handle_new_lox_credential", "trust_promotion", "handle_trust_promotion", "trust_migration", "handle_trust_migration", "level_up", "handle_level_up", "issue_invite", "handle_issue_invite", "prepare_invite", "redeem_invite", "handle_redeem_invite", "check_blockage", "handle_check_blockage", "blockage_migration", "handle_blockage_migration", "get_last_upgrade_time", "get_trust_level", "get_invites_remaining", "get_issued_invite_expiry", "get_received_invite_expiry", "get_bridgelines_from_bucket", "invitation_is_trusted", "get_next_unlock", "init", "initSync"];
+var EXPORTED_SYMBOLS = ["set_panic_hook", "open_invite", "handle_new_lox_credential", "trust_promotion", "handle_trust_promotion", "trust_migration", "handle_trust_migration", "level_up", "handle_level_up", "issue_invite", "handle_issue_invite", "prepare_invite", "redeem_invite", "handle_redeem_invite", "check_blockage", "handle_check_blockage", "blockage_migration", "handle_blockage_migration", "update_cred", "handle_update_cred", "update_invite", "handle_update_invite", "get_last_upgrade_time", "get_trust_level", "get_invites_remaining", "get_issued_invite_expiry", "get_received_invite_expiry", "get_bridgelines_from_bucket", "invitation_is_trusted", "get_next_unlock", "check_lox_pubkeys_update", "check_invitation_pubkeys_update", "init", "initSync"];
let wasm;
let module;
@@ -57,52 +57,6 @@ function set_panic_hook() {
let WASM_VECTOR_LEN = 0;
-function passArray8ToWasm0(arg, malloc) {
- const ptr = malloc(arg.length * 1, 1) >>> 0;
- getUint8Memory0().set(arg, ptr / 1);
- WASM_VECTOR_LEN = arg.length;
- return ptr;
-}
-
-let cachedInt32Memory0 = null;
-
-function getInt32Memory0() {
- if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
- cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
- }
- return cachedInt32Memory0;
-}
-/**
-* @param {Uint8Array} invite
-* @returns {string}
-*/
-function open_invite(invite) {
- let deferred3_0;
- let deferred3_1;
- try {
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
- const ptr0 = passArray8ToWasm0(invite, wasm.__wbindgen_malloc);
- const len0 = WASM_VECTOR_LEN;
- wasm.open_invite(retptr, ptr0, len0);
- var r0 = getInt32Memory0()[retptr / 4 + 0];
- var r1 = getInt32Memory0()[retptr / 4 + 1];
- var r2 = getInt32Memory0()[retptr / 4 + 2];
- var r3 = getInt32Memory0()[retptr / 4 + 3];
- var ptr2 = r0;
- var len2 = r1;
- if (r3) {
- ptr2 = 0; len2 = 0;
- throw takeObject(r2);
- }
- deferred3_0 = ptr2;
- deferred3_1 = len2;
- return getStringFromWasm0(ptr2, len2);
- } finally {
- wasm.__wbindgen_add_to_stack_pointer(16);
- wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
- }
-}
-
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
@@ -150,11 +104,52 @@ function passStringToWasm0(arg, malloc, realloc) {
const ret = encodeString(arg, view);
offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
+
+let cachedInt32Memory0 = null;
+
+function getInt32Memory0() {
+ if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
+ cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
+ }
+ return cachedInt32Memory0;
+}
+/**
+* @param {string} base64_invite
+* @returns {string}
+*/
+function open_invite(base64_invite) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(base64_invite, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.open_invite(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
/**
* @param {string} open_lox_result
* @param {string} open_lox_response
@@ -726,6 +721,148 @@ function handle_blockage_migration(blockage_migration_request, blockage_migratio
}
}
+/**
+* @param {string} lox_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function update_cred(lox_cred, lox_pub) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.update_cred(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} update_cred_request
+* @param {string} update_cred_response
+* @param {string} updated_lox_pub
+* @returns {string}
+*/
+function handle_update_cred(update_cred_request, update_cred_response, updated_lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(update_cred_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(update_cred_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(updated_lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_update_cred(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} invite_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function update_invite(invite_cred, lox_pub) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(invite_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.update_invite(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} update_invite_request
+* @param {string} update_invite_response
+* @param {string} updated_lox_pub
+* @returns {string}
+*/
+function handle_update_invite(update_invite_request, update_invite_response, updated_lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(update_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(update_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(updated_lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_update_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
/**
* @param {string} lox_cred_str
* @returns {string}
@@ -971,6 +1108,80 @@ function get_next_unlock(constants_str, lox_cred_str) {
}
}
+/**
+* @param {string} new_pubkeys_str
+* @param {string} old_pubkeys_str
+* @param {string} old_lox_cred
+* @returns {string}
+*/
+function check_lox_pubkeys_update(new_pubkeys_str, old_pubkeys_str, old_lox_cred) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(new_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(old_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(old_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.check_lox_pubkeys_update(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} new_pubkeys_str
+* @param {string} old_pubkeys_str
+* @param {string} old_invite_cred
+* @returns {string}
+*/
+function check_invitation_pubkeys_update(new_pubkeys_str, old_pubkeys_str, old_invite_cred) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(new_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(old_pubkeys_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(old_invite_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.check_invitation_pubkeys_update(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
function handleError(f, args) {
try {
return f.apply(this, args);
@@ -1013,11 +1224,11 @@ async function __wbg_load(module, imports) {
function __wbg_get_imports(window) {
const imports = {};
imports.wbg = {};
- imports.wbg.__wbg_new0_622c21a64f3d83ea = function() {
+ imports.wbg.__wbg_new0_7d84e5b2cd9fdc73 = function() {
const ret = new Date();
return addHeapObject(ret);
};
- imports.wbg.__wbg_getTime_9272be78826033e1 = function(arg0) {
+ imports.wbg.__wbg_getTime_2bc4375165f02d15 = function(arg0) {
const ret = getObject(arg0).getTime();
return ret;
};
@@ -1057,7 +1268,7 @@ function __wbg_get_imports(window) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
- imports.wbg.__wbg_crypto_c48a774b022d20ac = function(arg0) {
+ imports.wbg.__wbg_crypto_1d1f22824a6a080c = function(arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
};
@@ -1066,15 +1277,15 @@ function __wbg_get_imports(window) {
const ret = typeof(val) === 'object' && val !== null;
return ret;
};
- imports.wbg.__wbg_process_298734cf255a885d = function(arg0) {
+ imports.wbg.__wbg_process_4a72847cc503995b = function(arg0) {
const ret = getObject(arg0).process;
return addHeapObject(ret);
};
- imports.wbg.__wbg_versions_e2e78e134e3e5d01 = function(arg0) {
+ imports.wbg.__wbg_versions_f686565e586dd935 = function(arg0) {
const ret = getObject(arg0).versions;
return addHeapObject(ret);
};
- imports.wbg.__wbg_node_1cd7a5d853dbea79 = function(arg0) {
+ imports.wbg.__wbg_node_104a2ff8d6ea03a2 = function(arg0) {
const ret = getObject(arg0).node;
return addHeapObject(ret);
};
@@ -1082,7 +1293,7 @@ function __wbg_get_imports(window) {
const ret = typeof(getObject(arg0)) === 'string';
return ret;
};
- imports.wbg.__wbg_require_8f08ceecec0f4fee = function() { return handleError(function () {
+ imports.wbg.__wbg_require_cca90b1a94a0255b = function() { return handleError(function () {
const ret = module.require;
return addHeapObject(ret);
}, arguments) };
@@ -1090,31 +1301,31 @@ function __wbg_get_imports(window) {
const ret = typeof(getObject(arg0)) === 'function';
return ret;
};
- imports.wbg.__wbg_call_5da1969d7cd31ccd = function() { return handleError(function (arg0, arg1, arg2) {
+ imports.wbg.__wbg_call_b3ca7c6051f9bec1 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
return addHeapObject(ret);
}, arguments) };
- imports.wbg.__wbg_msCrypto_bcb970640f50a1e8 = function(arg0) {
+ imports.wbg.__wbg_msCrypto_eb05e62b530a1508 = function(arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
};
- imports.wbg.__wbg_newwithlength_6c2df9e2f3028c43 = function(arg0) {
+ imports.wbg.__wbg_newwithlength_e9b4878cebadb3d3 = function(arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
};
- imports.wbg.__wbg_self_f0e34d89f33b99fd = function() { return handleError(function () {
+ imports.wbg.__wbg_self_ce0dbfc45cf2f5be = function() { return handleError(function () {
const ret = window;
return addHeapObject(ret);
}, arguments) };
- imports.wbg.__wbg_window_d3b084224f4774d7 = function() { return handleError(function () {
+ imports.wbg.__wbg_window_c6fb939a7f436783 = function() { return handleError(function () {
const ret = window.window;
return addHeapObject(ret);
}, arguments) };
- imports.wbg.__wbg_globalThis_9caa27ff917c6860 = function() { return handleError(function () {
+ imports.wbg.__wbg_globalThis_d1e6af4856ba331b = function() { return handleError(function () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
- imports.wbg.__wbg_global_35dfdd59a4da3e74 = function() { return handleError(function () {
+ imports.wbg.__wbg_global_207b558942527489 = function() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
@@ -1122,11 +1333,11 @@ function __wbg_get_imports(window) {
const ret = getObject(arg0) === undefined;
return ret;
};
- imports.wbg.__wbg_newnoargs_c62ea9419c21fbac = function(arg0, arg1) {
+ imports.wbg.__wbg_newnoargs_e258087cd0daa0ea = function(arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
- imports.wbg.__wbg_call_90c26b09837aba1c = function() { return handleError(function (arg0, arg1) {
+ imports.wbg.__wbg_call_27c0f87801dedf93 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).call(getObject(arg1));
return addHeapObject(ret);
}, arguments) };
@@ -1134,29 +1345,29 @@ function __wbg_get_imports(window) {
const ret = wasm.memory;
return addHeapObject(ret);
};
- imports.wbg.__wbg_buffer_a448f833075b71ba = function(arg0) {
+ imports.wbg.__wbg_buffer_12d079cc21e14bdb = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
- imports.wbg.__wbg_newwithbyteoffsetandlength_d0482f893617af71 = function(arg0, arg1, arg2) {
+ imports.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
- imports.wbg.__wbg_randomFillSync_dc1e9a60c158336d = function() { return handleError(function (arg0, arg1) {
+ imports.wbg.__wbg_randomFillSync_5c9c955aa56b6049 = function() { return handleError(function (arg0, arg1) {
getObject(arg0).randomFillSync(takeObject(arg1));
}, arguments) };
- imports.wbg.__wbg_subarray_2e940e41c0f5a1d9 = function(arg0, arg1, arg2) {
+ imports.wbg.__wbg_subarray_a1f73cd4b5b42fe1 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
- imports.wbg.__wbg_getRandomValues_37fa2ca9e4e07fab = function() { return handleError(function (arg0, arg1) {
+ imports.wbg.__wbg_getRandomValues_3aa56aa6edec874c = function() { return handleError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
- imports.wbg.__wbg_new_8f67e318f15d7254 = function(arg0) {
+ imports.wbg.__wbg_new_63b92bc8671ed464 = function(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
- imports.wbg.__wbg_set_2357bf09366ee480 = function(arg0, arg1, arg2) {
+ imports.wbg.__wbg_set_a47bac70306a19a7 = function(arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/e464b1…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/e464b1…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-128.2.0esr-14.0-1] fixup! Firefox preference overrides.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch mullvad-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
e67e2a7e by Dan Ballard at 2024-09-02T11:15:49+02:00
fixup! Firefox preference overrides.
Bug 43023: Remove whitelist of samsung color emoji font
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -677,6 +677,12 @@ pref("toolkit.winRegisterApplicationRestart", false);
pref("browser.startup.windowsLaunchOnLogin.enabled", false);
#endif
+#ifdef ANDROID
+// tor-browser#43023 Force use of only standard emoji font
+// (not actually stopping samsung emoji font detection, but defense in depth and a step towards normalization)
+pref("font.name-list.emoji", "Noto Color Emoji");
+#endif
+
// If we are bundling fonts, whitelist those bundled fonts, and restrict system fonts to a selection.
#ifdef MOZ_BUNDLED_FONTS
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/e67…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/e67…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-128.2.0esr-14.0-1] fixup! Firefox preference overrides.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch base-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
bd93d2a7 by Dan Ballard at 2024-09-02T11:15:16+02:00
fixup! Firefox preference overrides.
Bug 43023: Remove whitelist of samsung color emoji font
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -678,6 +678,12 @@ pref("toolkit.winRegisterApplicationRestart", false);
pref("browser.startup.windowsLaunchOnLogin.enabled", false);
#endif
+#ifdef ANDROID
+// tor-browser#43023 Force use of only standard emoji font
+// (not actually stopping samsung emoji font detection, but defense in depth and a step towards normalization)
+pref("font.name-list.emoji", "Noto Color Emoji");
+#endif
+
// If we are bundling fonts, whitelist those bundled fonts, and restrict system fonts to a selection.
#ifdef MOZ_BUNDLED_FONTS
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/bd93d2a…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/bd93d2a…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-128.2.0esr-14.0-1] fixup! Firefox preference overrides.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch tor-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
e464b173 by Dan Ballard at 2024-09-02T08:37:47+00:00
fixup! Firefox preference overrides.
Bug 43023: Remove whitelist of samsung color emoji font
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -678,6 +678,12 @@ pref("toolkit.winRegisterApplicationRestart", false);
pref("browser.startup.windowsLaunchOnLogin.enabled", false);
#endif
+#ifdef ANDROID
+// tor-browser#43023 Force use of only standard emoji font
+// (not actually stopping samsung emoji font detection, but defense in depth and a step towards normalization)
+pref("font.name-list.emoji", "Noto Color Emoji");
+#endif
+
// If we are bundling fonts, whitelist those bundled fonts, and restrict system fonts to a selection.
#ifdef MOZ_BUNDLED_FONTS
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e464b17…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/e464b17…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-128.2.0esr-14.0-1] Bug 1885101: Match screen and window properties with top window for...
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch base-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
bb922d4c by Fatih at 2024-09-02T10:35:36+02:00
Bug 1885101: Match screen and window properties with top window for ScreenRect, ScreenAvailRect and WindowOuterSize. r=timhuang,emilio
This patch removes test_iframe.html. We remove it because the newly introduced test covers the tests done in that test. The reason for removing it in the first place is now that screen properties are inherited/spoofed xorigin, we get a 4px difference. The reasosn for 4px difference is the test runner runs tests in an iframe with a 2px border on each side.
Differential Revision: https://phabricator.services.mozilla.com/D215509
- - - - -
12 changed files:
- browser/components/resistfingerprinting/test/mochitest/mochitest.toml
- + browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
- − browser/components/resistfingerprinting/test/mochitest/test_iframe.html
- docshell/base/BrowsingContext.h
- docshell/base/CanonicalBrowsingContext.cpp
- dom/base/nsGlobalWindowOuter.cpp
- dom/base/nsScreen.cpp
- dom/base/nsScreen.h
- dom/base/test/chrome/bug418986-1.js
- layout/base/nsPresContext.cpp
- layout/base/nsPresContext.h
- toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
Changes:
=====================================
browser/components/resistfingerprinting/test/mochitest/mochitest.toml
=====================================
@@ -27,8 +27,6 @@ scheme = "https"
scheme = "https"
support-files = ["test_hide_gamepad_info_iframe.html"]
-["test_iframe.html"]
-
["test_keyboard_event.html"]
["test_pointer_event.html"]
@@ -36,3 +34,5 @@ support-files = ["../../../../../dom/events/test/pointerevents/mochitest_support
["test_speech_synthesis.html"]
skip-if = ["verify"]
+
+["test_bug1885101_screenwindow_sizes.html"]
=====================================
browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
=====================================
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Tests if +WindowOuterSizeExceptIFrame works properly</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ </head>
+
+ <body>
+ <iframe id="mainFrame"></iframe>
+
+ <template id="mainFrameContents">
+ <script>
+ window.parent.postMessage(
+ {
+ screen: {
+ height: window.screen.height,
+ width: window.screen.width,
+ availHeight: window.screen.availHeight,
+ availWidth: window.screen.availWidth,
+ },
+ outerHeight,
+ outerWidth,
+ },
+ "*"
+ );
+ </script>
+ </template>
+
+ <script>
+ document.addEventListener("DOMContentLoaded", function () {
+ SimpleTest.waitForExplicitFinish();
+
+ window.addEventListener("message", e => {
+ const data = e.data;
+
+ // Check for outer size
+ SimpleTest.is(
+ data.outerHeight,
+ window.outerHeight,
+ "iframe's window.outerHeight should be equal to window.top.outerHeight"
+ );
+
+ SimpleTest.is(
+ data.outerWidth,
+ window.outerWidth,
+ "iframe's window.outerWidth should be equal to window.top.outerWidth"
+ );
+
+ // Check for screen size
+ SimpleTest.is(
+ data.screen.height,
+ window.screen.height,
+ "iframe's window.screen.height should be equal to window.top.screen.height"
+ );
+
+ SimpleTest.is(
+ data.screen.width,
+ window.screen.width,
+ "iframe's window.screen.width should be equal to window.top.screen.width"
+ );
+
+ // Check for avail size
+ SimpleTest.is(
+ data.screen.availHeight,
+ window.screen.availHeight,
+ "iframe's window.screen.availHeight should be equal to window.top.screen.availHeight"
+ );
+
+ SimpleTest.is(
+ data.screen.availWidth,
+ window.screen.availWidth,
+ "iframe's window.screen.availWidth should be equal to window.top.screen.availWidth"
+ );
+
+ SimpleTest.finish();
+ });
+
+ function setFrameSource() {
+ const frame = document.getElementById("mainFrame");
+ const template = document.getElementById("mainFrameContents");
+ frame.srcdoc = template.innerHTML;
+ }
+
+ SpecialPowers.pushPrefEnv(
+ {
+ set: [
+ ["privacy.fingerprintingProtection", true],
+ [
+ "privacy.fingerprintingProtection.overrides",
+ "+WindowOuterSize,+ScreenRect,+ScreenAvailRect",
+ ],
+ ],
+ },
+ () => setFrameSource()
+ );
+ });
+ </script>
+ </body>
+</html>
=====================================
browser/components/resistfingerprinting/test/mochitest/test_iframe.html deleted
=====================================
@@ -1,18 +0,0 @@
-<!doctype html>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<body>
-<script>
- add_task(async function() {
- await SpecialPowers.pushPrefEnv({
- "set": [["privacy.resistFingerprinting", true]],
- });
- is(screen.width, window.innerWidth, "Width should be spoofed");
- is(screen.height, window.innerHeight, "Height should be spoofed");
- let iframe = document.createElement("iframe");
- document.body.appendChild(iframe);
- is(iframe.contentWindow.screen.width, iframe.contentWindow.innerWidth, "Width should be spoofed in iframe");
- is(iframe.contentWindow.screen.height, iframe.contentWindow.innerHeight, "Height should be spoofed in iframe");
- });
-</script>
-</body>
=====================================
docshell/base/BrowsingContext.h
=====================================
@@ -272,7 +272,10 @@ struct EmbedderColorSchemes {
/* If true, this browsing context is within a hidden embedded document. */ \
FIELD(IsUnderHiddenEmbedderElement, bool) \
/* If true, this browsing context is offline */ \
- FIELD(ForceOffline, bool)
+ FIELD(ForceOffline, bool) \
+ /* Used to propagate window.top's inner size for RFPTarget::Window* \
+ * protections */ \
+ FIELD(TopInnerSizeForRFP, CSSIntSize)
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
@@ -1253,6 +1256,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_ForceOffline>, bool aNewValue,
ContentParent* aSource);
+ bool CanSet(FieldIndex<IDX_TopInnerSizeForRFP>, bool, ContentParent*) {
+ return IsTop();
+ }
+
bool CanSet(FieldIndex<IDX_EmbeddedInContentDocument>, bool,
ContentParent* aSource) {
return CheckOnlyEmbedderCanSet(aSource);
=====================================
docshell/base/CanonicalBrowsingContext.cpp
=====================================
@@ -324,6 +324,7 @@ void CanonicalBrowsingContext::ReplacedBy(
txn.SetHasRestoreData(GetHasRestoreData());
txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart());
txn.SetForceOffline(GetForceOffline());
+ txn.SetTopInnerSizeForRFP(GetTopInnerSizeForRFP());
// Propagate some settings on BrowsingContext replacement so they're not lost
// on bfcached navigations. These are important for GeckoView (see bug
=====================================
dom/base/nsGlobalWindowOuter.cpp
=====================================
@@ -3513,9 +3513,10 @@ CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
ErrorResult& aError) {
if (nsIGlobalObject::ShouldResistFingerprinting(aCallerType,
RFPTarget::WindowOuterSize)) {
- CSSSize size;
- aError = GetInnerSize(size);
- return RoundedToInt(size);
+ if (BrowsingContext* bc = GetBrowsingContext()) {
+ return bc->Top()->GetTopInnerSizeForRFP();
+ }
+ return {};
}
// Windows showing documents in RDM panes and any subframes within them
=====================================
dom/base/nsScreen.cpp
=====================================
@@ -62,7 +62,7 @@ nsDeviceContext* nsScreen::GetDeviceContext() const {
CSSIntRect nsScreen::GetRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -91,7 +91,7 @@ CSSIntRect nsScreen::GetRect() {
CSSIntRect nsScreen::GetAvailRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenAvailRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -165,18 +165,14 @@ JSObject* nsScreen::WrapObject(JSContext* aCx,
return Screen_Binding::Wrap(aCx, this, aGivenProto);
}
-CSSIntRect nsScreen::GetWindowInnerRect() {
- nsCOMPtr<nsPIDOMWindowInner> win = GetOwner();
- if (!win) {
- return {};
- }
- double width;
- double height;
- if (NS_FAILED(win->GetInnerWidth(&width)) ||
- NS_FAILED(win->GetInnerHeight(&height))) {
- return {};
+CSSIntRect nsScreen::GetTopWindowInnerRectForRFP() {
+ if (nsPIDOMWindowInner* inner = GetOwner()) {
+ if (BrowsingContext* bc = inner->GetBrowsingContext()) {
+ CSSIntSize size = bc->Top()->GetTopInnerSizeForRFP();
+ return {0, 0, size.width, size.height};
+ }
}
- return {0, 0, int32_t(std::round(width)), int32_t(std::round(height))};
+ return {};
}
bool nsScreen::ShouldResistFingerprinting(RFPTarget aTarget) const {
=====================================
dom/base/nsScreen.h
=====================================
@@ -88,7 +88,7 @@ class nsScreen : public mozilla::DOMEventTargetHelper {
nsDeviceContext* GetDeviceContext() const;
mozilla::CSSIntRect GetRect();
mozilla::CSSIntRect GetAvailRect();
- mozilla::CSSIntRect GetWindowInnerRect();
+ mozilla::CSSIntRect GetTopWindowInnerRectForRFP();
private:
virtual ~nsScreen();
=====================================
dom/base/test/chrome/bug418986-1.js
=====================================
@@ -24,14 +24,14 @@ var test = function (isContent) {
["mozInnerScreenY", 0],
["screen.pixelDepth", 24],
["screen.colorDepth", 24],
- ["screen.availWidth", "innerWidth"],
- ["screen.availHeight", "innerHeight"],
+ ["screen.availWidth", "outerWidth"],
+ ["screen.availHeight", "outerHeight"],
["screen.left", 0],
["screen.top", 0],
["screen.availLeft", 0],
["screen.availTop", 0],
- ["screen.width", "innerWidth"],
- ["screen.height", "innerHeight"],
+ ["screen.width", "outerWidth"],
+ ["screen.height", "outerHeight"],
["screen.orientation.type", "'landscape-primary'"],
["screen.orientation.angle", 0],
["screen.mozOrientation", "'landscape-primary'"],
=====================================
layout/base/nsPresContext.cpp
=====================================
@@ -1459,6 +1459,32 @@ void nsPresContext::SetOverrideDPPX(float aDPPX) {
MediaFeatureChangePropagation::JustThisDocument);
}
+void nsPresContext::UpdateTopInnerSizeForRFP() {
+ if (!mDocument->ShouldResistFingerprinting(RFPTarget::WindowOuterSize) ||
+ !mDocument->GetBrowsingContext() ||
+ !mDocument->GetBrowsingContext()->IsTop()) {
+ return;
+ }
+
+ CSSSize size = CSSPixel::FromAppUnits(GetVisibleArea().Size());
+
+ switch (StaticPrefs::dom_innerSize_rounding()) {
+ case 1:
+ size.width = std::roundf(size.width);
+ size.height = std::roundf(size.height);
+ break;
+ case 2:
+ size.width = std::truncf(size.width);
+ size.height = std::truncf(size.height);
+ break;
+ default:
+ break;
+ }
+
+ Unused << mDocument->GetBrowsingContext()->SetTopInnerSizeForRFP(
+ CSSIntSize{(int)size.width, (int)size.height});
+}
+
gfxSize nsPresContext::ScreenSizeInchesForFontInflation(bool* aChanged) {
if (aChanged) {
*aChanged = false;
@@ -2972,6 +2998,8 @@ void nsPresContext::SetVisibleArea(const nsRect& r) {
{mozilla::MediaFeatureChangeReason::ViewportChange},
MediaFeatureChangePropagation::JustThisDocument);
}
+
+ UpdateTopInnerSizeForRFP();
}
}
=====================================
layout/base/nsPresContext.h
=====================================
@@ -540,6 +540,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
void SetFullZoom(float aZoom);
void SetOverrideDPPX(float);
void SetInRDMPane(bool aInRDMPane);
+ void UpdateTopInnerSizeForRFP();
public:
float GetFullZoom() { return mFullZoom; }
=====================================
toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
=====================================
@@ -34,12 +34,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -57,12 +57,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -80,13 +80,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -104,13 +104,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -128,13 +128,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -153,12 +153,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -177,13 +177,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -202,13 +202,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -221,13 +221,13 @@ const TEST_CASES = [
},
},
// Test multiple entries that enable HW concurrency in the first-party context
- // and WindowOuter in the third-party context.
+ // and ScreenAvailRect in the third-party context.
{
entires: [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
{
@@ -239,7 +239,7 @@ const TEST_CASES = [
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -335,22 +335,22 @@ async function openAndSetupTestPageForPopup() {
}
async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
- let testWindowOuter = enabled => {
+ let testScreenAvailRect = enabled => {
if (enabled) {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for ScreenAvailRect."
);
} else {
ok(
- content.wrappedJSObject.outerHeight !=
- content.wrappedJSObject.innerHeight ||
- content.wrappedJSObject.outerWidth !=
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is not enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight !=
+ content.wrappedJSObject.screen.height ||
+ content.wrappedJSObject.screen.availWidth !=
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is not enabled for ScreenAvailRect."
);
}
};
@@ -370,8 +370,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
tab.linkedBrowser,
- [expected.windowOuter.top],
- testWindowOuter
+ [expected.screenAvailRect.top],
+ testScreenAvailRect
);
let expectHWConcurrencyTop = expected.hwConcurrency.top
? SPOOFED_HW_CONCURRENCY
@@ -401,8 +401,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
firstPartyBC,
- [expected.windowOuter.firstParty],
- testWindowOuter
+ [expected.screenAvailRect.firstParty],
+ testScreenAvailRect
);
let expectHWConcurrencyFirstParty = expected.hwConcurrency.firstParty
? SPOOFED_HW_CONCURRENCY
@@ -432,8 +432,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
thirdPartyBC,
- [expected.windowOuter.thirdParty],
- testWindowOuter
+ [expected.screenAvailRect.thirdParty],
+ testScreenAvailRect
);
let expectHWConcurrencyThirdParty = expected.hwConcurrency.thirdParty
? SPOOFED_HW_CONCURRENCY
@@ -517,7 +517,7 @@ add_task(async function test_popup_inheritance() {
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
@@ -532,22 +532,22 @@ add_task(async function test_popup_inheritance() {
// Ensure the third-party iframe has the correct overrides.
await SpecialPowers.spawn(thirdPartyFrameBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for third-party iframe."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for third-party iframe."
);
});
// Verify the popup inherits overrides from the opener.
await SpecialPowers.spawn(popupBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for the pop-up."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for the pop-up."
);
content.close();
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/bb922d4…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/bb922d4…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-128.2.0esr-14.0-1] Bug 1885101: Match screen and window properties with top window for...
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch mullvad-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
f5fe7501 by Fatih at 2024-09-02T10:35:23+02:00
Bug 1885101: Match screen and window properties with top window for ScreenRect, ScreenAvailRect and WindowOuterSize. r=timhuang,emilio
This patch removes test_iframe.html. We remove it because the newly introduced test covers the tests done in that test. The reason for removing it in the first place is now that screen properties are inherited/spoofed xorigin, we get a 4px difference. The reasosn for 4px difference is the test runner runs tests in an iframe with a 2px border on each side.
Differential Revision: https://phabricator.services.mozilla.com/D215509
- - - - -
12 changed files:
- browser/components/resistfingerprinting/test/mochitest/mochitest.toml
- + browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
- − browser/components/resistfingerprinting/test/mochitest/test_iframe.html
- docshell/base/BrowsingContext.h
- docshell/base/CanonicalBrowsingContext.cpp
- dom/base/nsGlobalWindowOuter.cpp
- dom/base/nsScreen.cpp
- dom/base/nsScreen.h
- dom/base/test/chrome/bug418986-1.js
- layout/base/nsPresContext.cpp
- layout/base/nsPresContext.h
- toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
Changes:
=====================================
browser/components/resistfingerprinting/test/mochitest/mochitest.toml
=====================================
@@ -27,8 +27,6 @@ scheme = "https"
scheme = "https"
support-files = ["test_hide_gamepad_info_iframe.html"]
-["test_iframe.html"]
-
["test_keyboard_event.html"]
["test_pointer_event.html"]
@@ -36,3 +34,5 @@ support-files = ["../../../../../dom/events/test/pointerevents/mochitest_support
["test_speech_synthesis.html"]
skip-if = ["verify"]
+
+["test_bug1885101_screenwindow_sizes.html"]
=====================================
browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
=====================================
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Tests if +WindowOuterSizeExceptIFrame works properly</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ </head>
+
+ <body>
+ <iframe id="mainFrame"></iframe>
+
+ <template id="mainFrameContents">
+ <script>
+ window.parent.postMessage(
+ {
+ screen: {
+ height: window.screen.height,
+ width: window.screen.width,
+ availHeight: window.screen.availHeight,
+ availWidth: window.screen.availWidth,
+ },
+ outerHeight,
+ outerWidth,
+ },
+ "*"
+ );
+ </script>
+ </template>
+
+ <script>
+ document.addEventListener("DOMContentLoaded", function () {
+ SimpleTest.waitForExplicitFinish();
+
+ window.addEventListener("message", e => {
+ const data = e.data;
+
+ // Check for outer size
+ SimpleTest.is(
+ data.outerHeight,
+ window.outerHeight,
+ "iframe's window.outerHeight should be equal to window.top.outerHeight"
+ );
+
+ SimpleTest.is(
+ data.outerWidth,
+ window.outerWidth,
+ "iframe's window.outerWidth should be equal to window.top.outerWidth"
+ );
+
+ // Check for screen size
+ SimpleTest.is(
+ data.screen.height,
+ window.screen.height,
+ "iframe's window.screen.height should be equal to window.top.screen.height"
+ );
+
+ SimpleTest.is(
+ data.screen.width,
+ window.screen.width,
+ "iframe's window.screen.width should be equal to window.top.screen.width"
+ );
+
+ // Check for avail size
+ SimpleTest.is(
+ data.screen.availHeight,
+ window.screen.availHeight,
+ "iframe's window.screen.availHeight should be equal to window.top.screen.availHeight"
+ );
+
+ SimpleTest.is(
+ data.screen.availWidth,
+ window.screen.availWidth,
+ "iframe's window.screen.availWidth should be equal to window.top.screen.availWidth"
+ );
+
+ SimpleTest.finish();
+ });
+
+ function setFrameSource() {
+ const frame = document.getElementById("mainFrame");
+ const template = document.getElementById("mainFrameContents");
+ frame.srcdoc = template.innerHTML;
+ }
+
+ SpecialPowers.pushPrefEnv(
+ {
+ set: [
+ ["privacy.fingerprintingProtection", true],
+ [
+ "privacy.fingerprintingProtection.overrides",
+ "+WindowOuterSize,+ScreenRect,+ScreenAvailRect",
+ ],
+ ],
+ },
+ () => setFrameSource()
+ );
+ });
+ </script>
+ </body>
+</html>
=====================================
browser/components/resistfingerprinting/test/mochitest/test_iframe.html deleted
=====================================
@@ -1,18 +0,0 @@
-<!doctype html>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<body>
-<script>
- add_task(async function() {
- await SpecialPowers.pushPrefEnv({
- "set": [["privacy.resistFingerprinting", true]],
- });
- is(screen.width, window.innerWidth, "Width should be spoofed");
- is(screen.height, window.innerHeight, "Height should be spoofed");
- let iframe = document.createElement("iframe");
- document.body.appendChild(iframe);
- is(iframe.contentWindow.screen.width, iframe.contentWindow.innerWidth, "Width should be spoofed in iframe");
- is(iframe.contentWindow.screen.height, iframe.contentWindow.innerHeight, "Height should be spoofed in iframe");
- });
-</script>
-</body>
=====================================
docshell/base/BrowsingContext.h
=====================================
@@ -272,7 +272,10 @@ struct EmbedderColorSchemes {
/* If true, this browsing context is within a hidden embedded document. */ \
FIELD(IsUnderHiddenEmbedderElement, bool) \
/* If true, this browsing context is offline */ \
- FIELD(ForceOffline, bool)
+ FIELD(ForceOffline, bool) \
+ /* Used to propagate window.top's inner size for RFPTarget::Window* \
+ * protections */ \
+ FIELD(TopInnerSizeForRFP, CSSIntSize)
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
@@ -1253,6 +1256,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_ForceOffline>, bool aNewValue,
ContentParent* aSource);
+ bool CanSet(FieldIndex<IDX_TopInnerSizeForRFP>, bool, ContentParent*) {
+ return IsTop();
+ }
+
bool CanSet(FieldIndex<IDX_EmbeddedInContentDocument>, bool,
ContentParent* aSource) {
return CheckOnlyEmbedderCanSet(aSource);
=====================================
docshell/base/CanonicalBrowsingContext.cpp
=====================================
@@ -324,6 +324,7 @@ void CanonicalBrowsingContext::ReplacedBy(
txn.SetHasRestoreData(GetHasRestoreData());
txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart());
txn.SetForceOffline(GetForceOffline());
+ txn.SetTopInnerSizeForRFP(GetTopInnerSizeForRFP());
// Propagate some settings on BrowsingContext replacement so they're not lost
// on bfcached navigations. These are important for GeckoView (see bug
=====================================
dom/base/nsGlobalWindowOuter.cpp
=====================================
@@ -3513,9 +3513,10 @@ CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
ErrorResult& aError) {
if (nsIGlobalObject::ShouldResistFingerprinting(aCallerType,
RFPTarget::WindowOuterSize)) {
- CSSSize size;
- aError = GetInnerSize(size);
- return RoundedToInt(size);
+ if (BrowsingContext* bc = GetBrowsingContext()) {
+ return bc->Top()->GetTopInnerSizeForRFP();
+ }
+ return {};
}
// Windows showing documents in RDM panes and any subframes within them
=====================================
dom/base/nsScreen.cpp
=====================================
@@ -62,7 +62,7 @@ nsDeviceContext* nsScreen::GetDeviceContext() const {
CSSIntRect nsScreen::GetRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -91,7 +91,7 @@ CSSIntRect nsScreen::GetRect() {
CSSIntRect nsScreen::GetAvailRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenAvailRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -165,18 +165,14 @@ JSObject* nsScreen::WrapObject(JSContext* aCx,
return Screen_Binding::Wrap(aCx, this, aGivenProto);
}
-CSSIntRect nsScreen::GetWindowInnerRect() {
- nsCOMPtr<nsPIDOMWindowInner> win = GetOwner();
- if (!win) {
- return {};
- }
- double width;
- double height;
- if (NS_FAILED(win->GetInnerWidth(&width)) ||
- NS_FAILED(win->GetInnerHeight(&height))) {
- return {};
+CSSIntRect nsScreen::GetTopWindowInnerRectForRFP() {
+ if (nsPIDOMWindowInner* inner = GetOwner()) {
+ if (BrowsingContext* bc = inner->GetBrowsingContext()) {
+ CSSIntSize size = bc->Top()->GetTopInnerSizeForRFP();
+ return {0, 0, size.width, size.height};
+ }
}
- return {0, 0, int32_t(std::round(width)), int32_t(std::round(height))};
+ return {};
}
bool nsScreen::ShouldResistFingerprinting(RFPTarget aTarget) const {
=====================================
dom/base/nsScreen.h
=====================================
@@ -88,7 +88,7 @@ class nsScreen : public mozilla::DOMEventTargetHelper {
nsDeviceContext* GetDeviceContext() const;
mozilla::CSSIntRect GetRect();
mozilla::CSSIntRect GetAvailRect();
- mozilla::CSSIntRect GetWindowInnerRect();
+ mozilla::CSSIntRect GetTopWindowInnerRectForRFP();
private:
virtual ~nsScreen();
=====================================
dom/base/test/chrome/bug418986-1.js
=====================================
@@ -24,14 +24,14 @@ var test = function (isContent) {
["mozInnerScreenY", 0],
["screen.pixelDepth", 24],
["screen.colorDepth", 24],
- ["screen.availWidth", "innerWidth"],
- ["screen.availHeight", "innerHeight"],
+ ["screen.availWidth", "outerWidth"],
+ ["screen.availHeight", "outerHeight"],
["screen.left", 0],
["screen.top", 0],
["screen.availLeft", 0],
["screen.availTop", 0],
- ["screen.width", "innerWidth"],
- ["screen.height", "innerHeight"],
+ ["screen.width", "outerWidth"],
+ ["screen.height", "outerHeight"],
["screen.orientation.type", "'landscape-primary'"],
["screen.orientation.angle", 0],
["screen.mozOrientation", "'landscape-primary'"],
=====================================
layout/base/nsPresContext.cpp
=====================================
@@ -1459,6 +1459,32 @@ void nsPresContext::SetOverrideDPPX(float aDPPX) {
MediaFeatureChangePropagation::JustThisDocument);
}
+void nsPresContext::UpdateTopInnerSizeForRFP() {
+ if (!mDocument->ShouldResistFingerprinting(RFPTarget::WindowOuterSize) ||
+ !mDocument->GetBrowsingContext() ||
+ !mDocument->GetBrowsingContext()->IsTop()) {
+ return;
+ }
+
+ CSSSize size = CSSPixel::FromAppUnits(GetVisibleArea().Size());
+
+ switch (StaticPrefs::dom_innerSize_rounding()) {
+ case 1:
+ size.width = std::roundf(size.width);
+ size.height = std::roundf(size.height);
+ break;
+ case 2:
+ size.width = std::truncf(size.width);
+ size.height = std::truncf(size.height);
+ break;
+ default:
+ break;
+ }
+
+ Unused << mDocument->GetBrowsingContext()->SetTopInnerSizeForRFP(
+ CSSIntSize{(int)size.width, (int)size.height});
+}
+
gfxSize nsPresContext::ScreenSizeInchesForFontInflation(bool* aChanged) {
if (aChanged) {
*aChanged = false;
@@ -2972,6 +2998,8 @@ void nsPresContext::SetVisibleArea(const nsRect& r) {
{mozilla::MediaFeatureChangeReason::ViewportChange},
MediaFeatureChangePropagation::JustThisDocument);
}
+
+ UpdateTopInnerSizeForRFP();
}
}
=====================================
layout/base/nsPresContext.h
=====================================
@@ -540,6 +540,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
void SetFullZoom(float aZoom);
void SetOverrideDPPX(float);
void SetInRDMPane(bool aInRDMPane);
+ void UpdateTopInnerSizeForRFP();
public:
float GetFullZoom() { return mFullZoom; }
=====================================
toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
=====================================
@@ -34,12 +34,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -57,12 +57,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -80,13 +80,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -104,13 +104,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -128,13 +128,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -153,12 +153,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -177,13 +177,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -202,13 +202,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -221,13 +221,13 @@ const TEST_CASES = [
},
},
// Test multiple entries that enable HW concurrency in the first-party context
- // and WindowOuter in the third-party context.
+ // and ScreenAvailRect in the third-party context.
{
entires: [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
{
@@ -239,7 +239,7 @@ const TEST_CASES = [
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -335,22 +335,22 @@ async function openAndSetupTestPageForPopup() {
}
async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
- let testWindowOuter = enabled => {
+ let testScreenAvailRect = enabled => {
if (enabled) {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for ScreenAvailRect."
);
} else {
ok(
- content.wrappedJSObject.outerHeight !=
- content.wrappedJSObject.innerHeight ||
- content.wrappedJSObject.outerWidth !=
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is not enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight !=
+ content.wrappedJSObject.screen.height ||
+ content.wrappedJSObject.screen.availWidth !=
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is not enabled for ScreenAvailRect."
);
}
};
@@ -370,8 +370,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
tab.linkedBrowser,
- [expected.windowOuter.top],
- testWindowOuter
+ [expected.screenAvailRect.top],
+ testScreenAvailRect
);
let expectHWConcurrencyTop = expected.hwConcurrency.top
? SPOOFED_HW_CONCURRENCY
@@ -401,8 +401,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
firstPartyBC,
- [expected.windowOuter.firstParty],
- testWindowOuter
+ [expected.screenAvailRect.firstParty],
+ testScreenAvailRect
);
let expectHWConcurrencyFirstParty = expected.hwConcurrency.firstParty
? SPOOFED_HW_CONCURRENCY
@@ -432,8 +432,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
thirdPartyBC,
- [expected.windowOuter.thirdParty],
- testWindowOuter
+ [expected.screenAvailRect.thirdParty],
+ testScreenAvailRect
);
let expectHWConcurrencyThirdParty = expected.hwConcurrency.thirdParty
? SPOOFED_HW_CONCURRENCY
@@ -517,7 +517,7 @@ add_task(async function test_popup_inheritance() {
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
@@ -532,22 +532,22 @@ add_task(async function test_popup_inheritance() {
// Ensure the third-party iframe has the correct overrides.
await SpecialPowers.spawn(thirdPartyFrameBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for third-party iframe."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for third-party iframe."
);
});
// Verify the popup inherits overrides from the opener.
await SpecialPowers.spawn(popupBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for the pop-up."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for the pop-up."
);
content.close();
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/f5f…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/f5f…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-128.2.0esr-14.0-1] Bug 1885101: Match screen and window properties with top window for...
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch tor-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
eb4cf955 by Fatih at 2024-09-02T08:34:39+00:00
Bug 1885101: Match screen and window properties with top window for ScreenRect, ScreenAvailRect and WindowOuterSize. r=timhuang,emilio
This patch removes test_iframe.html. We remove it because the newly introduced test covers the tests done in that test. The reason for removing it in the first place is now that screen properties are inherited/spoofed xorigin, we get a 4px difference. The reasosn for 4px difference is the test runner runs tests in an iframe with a 2px border on each side.
Differential Revision: https://phabricator.services.mozilla.com/D215509
- - - - -
12 changed files:
- browser/components/resistfingerprinting/test/mochitest/mochitest.toml
- + browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
- − browser/components/resistfingerprinting/test/mochitest/test_iframe.html
- docshell/base/BrowsingContext.h
- docshell/base/CanonicalBrowsingContext.cpp
- dom/base/nsGlobalWindowOuter.cpp
- dom/base/nsScreen.cpp
- dom/base/nsScreen.h
- dom/base/test/chrome/bug418986-1.js
- layout/base/nsPresContext.cpp
- layout/base/nsPresContext.h
- toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
Changes:
=====================================
browser/components/resistfingerprinting/test/mochitest/mochitest.toml
=====================================
@@ -27,8 +27,6 @@ scheme = "https"
scheme = "https"
support-files = ["test_hide_gamepad_info_iframe.html"]
-["test_iframe.html"]
-
["test_keyboard_event.html"]
["test_pointer_event.html"]
@@ -36,3 +34,5 @@ support-files = ["../../../../../dom/events/test/pointerevents/mochitest_support
["test_speech_synthesis.html"]
skip-if = ["verify"]
+
+["test_bug1885101_screenwindow_sizes.html"]
=====================================
browser/components/resistfingerprinting/test/mochitest/test_bug1885101_screenwindow_sizes.html
=====================================
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Tests if +WindowOuterSizeExceptIFrame works properly</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ </head>
+
+ <body>
+ <iframe id="mainFrame"></iframe>
+
+ <template id="mainFrameContents">
+ <script>
+ window.parent.postMessage(
+ {
+ screen: {
+ height: window.screen.height,
+ width: window.screen.width,
+ availHeight: window.screen.availHeight,
+ availWidth: window.screen.availWidth,
+ },
+ outerHeight,
+ outerWidth,
+ },
+ "*"
+ );
+ </script>
+ </template>
+
+ <script>
+ document.addEventListener("DOMContentLoaded", function () {
+ SimpleTest.waitForExplicitFinish();
+
+ window.addEventListener("message", e => {
+ const data = e.data;
+
+ // Check for outer size
+ SimpleTest.is(
+ data.outerHeight,
+ window.outerHeight,
+ "iframe's window.outerHeight should be equal to window.top.outerHeight"
+ );
+
+ SimpleTest.is(
+ data.outerWidth,
+ window.outerWidth,
+ "iframe's window.outerWidth should be equal to window.top.outerWidth"
+ );
+
+ // Check for screen size
+ SimpleTest.is(
+ data.screen.height,
+ window.screen.height,
+ "iframe's window.screen.height should be equal to window.top.screen.height"
+ );
+
+ SimpleTest.is(
+ data.screen.width,
+ window.screen.width,
+ "iframe's window.screen.width should be equal to window.top.screen.width"
+ );
+
+ // Check for avail size
+ SimpleTest.is(
+ data.screen.availHeight,
+ window.screen.availHeight,
+ "iframe's window.screen.availHeight should be equal to window.top.screen.availHeight"
+ );
+
+ SimpleTest.is(
+ data.screen.availWidth,
+ window.screen.availWidth,
+ "iframe's window.screen.availWidth should be equal to window.top.screen.availWidth"
+ );
+
+ SimpleTest.finish();
+ });
+
+ function setFrameSource() {
+ const frame = document.getElementById("mainFrame");
+ const template = document.getElementById("mainFrameContents");
+ frame.srcdoc = template.innerHTML;
+ }
+
+ SpecialPowers.pushPrefEnv(
+ {
+ set: [
+ ["privacy.fingerprintingProtection", true],
+ [
+ "privacy.fingerprintingProtection.overrides",
+ "+WindowOuterSize,+ScreenRect,+ScreenAvailRect",
+ ],
+ ],
+ },
+ () => setFrameSource()
+ );
+ });
+ </script>
+ </body>
+</html>
=====================================
browser/components/resistfingerprinting/test/mochitest/test_iframe.html deleted
=====================================
@@ -1,18 +0,0 @@
-<!doctype html>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<body>
-<script>
- add_task(async function() {
- await SpecialPowers.pushPrefEnv({
- "set": [["privacy.resistFingerprinting", true]],
- });
- is(screen.width, window.innerWidth, "Width should be spoofed");
- is(screen.height, window.innerHeight, "Height should be spoofed");
- let iframe = document.createElement("iframe");
- document.body.appendChild(iframe);
- is(iframe.contentWindow.screen.width, iframe.contentWindow.innerWidth, "Width should be spoofed in iframe");
- is(iframe.contentWindow.screen.height, iframe.contentWindow.innerHeight, "Height should be spoofed in iframe");
- });
-</script>
-</body>
=====================================
docshell/base/BrowsingContext.h
=====================================
@@ -272,7 +272,10 @@ struct EmbedderColorSchemes {
/* If true, this browsing context is within a hidden embedded document. */ \
FIELD(IsUnderHiddenEmbedderElement, bool) \
/* If true, this browsing context is offline */ \
- FIELD(ForceOffline, bool)
+ FIELD(ForceOffline, bool) \
+ /* Used to propagate window.top's inner size for RFPTarget::Window* \
+ * protections */ \
+ FIELD(TopInnerSizeForRFP, CSSIntSize)
// BrowsingContext, in this context, is the cross process replicated
// environment in which information about documents is stored. In
@@ -1253,6 +1256,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_ForceOffline>, bool aNewValue,
ContentParent* aSource);
+ bool CanSet(FieldIndex<IDX_TopInnerSizeForRFP>, bool, ContentParent*) {
+ return IsTop();
+ }
+
bool CanSet(FieldIndex<IDX_EmbeddedInContentDocument>, bool,
ContentParent* aSource) {
return CheckOnlyEmbedderCanSet(aSource);
=====================================
docshell/base/CanonicalBrowsingContext.cpp
=====================================
@@ -324,6 +324,7 @@ void CanonicalBrowsingContext::ReplacedBy(
txn.SetHasRestoreData(GetHasRestoreData());
txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart());
txn.SetForceOffline(GetForceOffline());
+ txn.SetTopInnerSizeForRFP(GetTopInnerSizeForRFP());
// Propagate some settings on BrowsingContext replacement so they're not lost
// on bfcached navigations. These are important for GeckoView (see bug
=====================================
dom/base/nsGlobalWindowOuter.cpp
=====================================
@@ -3514,9 +3514,10 @@ CSSIntSize nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType,
ErrorResult& aError) {
if (nsIGlobalObject::ShouldResistFingerprinting(aCallerType,
RFPTarget::WindowOuterSize)) {
- CSSSize size;
- aError = GetInnerSize(size);
- return RoundedToInt(size);
+ if (BrowsingContext* bc = GetBrowsingContext()) {
+ return bc->Top()->GetTopInnerSizeForRFP();
+ }
+ return {};
}
// Windows showing documents in RDM panes and any subframes within them
=====================================
dom/base/nsScreen.cpp
=====================================
@@ -62,7 +62,7 @@ nsDeviceContext* nsScreen::GetDeviceContext() const {
CSSIntRect nsScreen::GetRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -91,7 +91,7 @@ CSSIntRect nsScreen::GetRect() {
CSSIntRect nsScreen::GetAvailRect() {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting(RFPTarget::ScreenAvailRect)) {
- return GetWindowInnerRect();
+ return GetTopWindowInnerRectForRFP();
}
// Here we manipulate the value of aRect to represent the screen size,
@@ -165,18 +165,14 @@ JSObject* nsScreen::WrapObject(JSContext* aCx,
return Screen_Binding::Wrap(aCx, this, aGivenProto);
}
-CSSIntRect nsScreen::GetWindowInnerRect() {
- nsCOMPtr<nsPIDOMWindowInner> win = GetOwner();
- if (!win) {
- return {};
- }
- double width;
- double height;
- if (NS_FAILED(win->GetInnerWidth(&width)) ||
- NS_FAILED(win->GetInnerHeight(&height))) {
- return {};
+CSSIntRect nsScreen::GetTopWindowInnerRectForRFP() {
+ if (nsPIDOMWindowInner* inner = GetOwner()) {
+ if (BrowsingContext* bc = inner->GetBrowsingContext()) {
+ CSSIntSize size = bc->Top()->GetTopInnerSizeForRFP();
+ return {0, 0, size.width, size.height};
+ }
}
- return {0, 0, int32_t(std::round(width)), int32_t(std::round(height))};
+ return {};
}
bool nsScreen::ShouldResistFingerprinting(RFPTarget aTarget) const {
=====================================
dom/base/nsScreen.h
=====================================
@@ -88,7 +88,7 @@ class nsScreen : public mozilla::DOMEventTargetHelper {
nsDeviceContext* GetDeviceContext() const;
mozilla::CSSIntRect GetRect();
mozilla::CSSIntRect GetAvailRect();
- mozilla::CSSIntRect GetWindowInnerRect();
+ mozilla::CSSIntRect GetTopWindowInnerRectForRFP();
private:
virtual ~nsScreen();
=====================================
dom/base/test/chrome/bug418986-1.js
=====================================
@@ -24,14 +24,14 @@ var test = function (isContent) {
["mozInnerScreenY", 0],
["screen.pixelDepth", 24],
["screen.colorDepth", 24],
- ["screen.availWidth", "innerWidth"],
- ["screen.availHeight", "innerHeight"],
+ ["screen.availWidth", "outerWidth"],
+ ["screen.availHeight", "outerHeight"],
["screen.left", 0],
["screen.top", 0],
["screen.availLeft", 0],
["screen.availTop", 0],
- ["screen.width", "innerWidth"],
- ["screen.height", "innerHeight"],
+ ["screen.width", "outerWidth"],
+ ["screen.height", "outerHeight"],
["screen.orientation.type", "'landscape-primary'"],
["screen.orientation.angle", 0],
["screen.mozOrientation", "'landscape-primary'"],
=====================================
layout/base/nsPresContext.cpp
=====================================
@@ -1459,6 +1459,32 @@ void nsPresContext::SetOverrideDPPX(float aDPPX) {
MediaFeatureChangePropagation::JustThisDocument);
}
+void nsPresContext::UpdateTopInnerSizeForRFP() {
+ if (!mDocument->ShouldResistFingerprinting(RFPTarget::WindowOuterSize) ||
+ !mDocument->GetBrowsingContext() ||
+ !mDocument->GetBrowsingContext()->IsTop()) {
+ return;
+ }
+
+ CSSSize size = CSSPixel::FromAppUnits(GetVisibleArea().Size());
+
+ switch (StaticPrefs::dom_innerSize_rounding()) {
+ case 1:
+ size.width = std::roundf(size.width);
+ size.height = std::roundf(size.height);
+ break;
+ case 2:
+ size.width = std::truncf(size.width);
+ size.height = std::truncf(size.height);
+ break;
+ default:
+ break;
+ }
+
+ Unused << mDocument->GetBrowsingContext()->SetTopInnerSizeForRFP(
+ CSSIntSize{(int)size.width, (int)size.height});
+}
+
gfxSize nsPresContext::ScreenSizeInchesForFontInflation(bool* aChanged) {
if (aChanged) {
*aChanged = false;
@@ -2972,6 +2998,8 @@ void nsPresContext::SetVisibleArea(const nsRect& r) {
{mozilla::MediaFeatureChangeReason::ViewportChange},
MediaFeatureChangePropagation::JustThisDocument);
}
+
+ UpdateTopInnerSizeForRFP();
}
}
=====================================
layout/base/nsPresContext.h
=====================================
@@ -540,6 +540,7 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
void SetFullZoom(float aZoom);
void SetOverrideDPPX(float);
void SetInRDMPane(bool aInRDMPane);
+ void UpdateTopInnerSizeForRFP();
public:
float GetFullZoom() { return mFullZoom; }
=====================================
toolkit/components/resistfingerprinting/tests/browser/browser_fingerprintingWebCompat.js
=====================================
@@ -34,12 +34,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -57,12 +57,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -80,13 +80,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: true,
@@ -104,13 +104,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -128,13 +128,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "*",
thirdPartyDomain: "example.org",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: true,
@@ -153,12 +153,12 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -177,13 +177,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "*",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -202,13 +202,13 @@ const TEST_CASES = [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.net",
thirdPartyDomain: "example.com",
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: false,
firstParty: false,
thirdParty: false,
@@ -221,13 +221,13 @@ const TEST_CASES = [
},
},
// Test multiple entries that enable HW concurrency in the first-party context
- // and WindowOuter in the third-party context.
+ // and ScreenAvailRect in the third-party context.
{
entires: [
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
},
{
@@ -239,7 +239,7 @@ const TEST_CASES = [
},
],
expects: {
- windowOuter: {
+ screenAvailRect: {
top: true,
firstParty: true,
thirdParty: false,
@@ -335,22 +335,22 @@ async function openAndSetupTestPageForPopup() {
}
async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
- let testWindowOuter = enabled => {
+ let testScreenAvailRect = enabled => {
if (enabled) {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for ScreenAvailRect."
);
} else {
ok(
- content.wrappedJSObject.outerHeight !=
- content.wrappedJSObject.innerHeight ||
- content.wrappedJSObject.outerWidth !=
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is not enabled for WindowOuterSize."
+ content.wrappedJSObject.screen.availHeight !=
+ content.wrappedJSObject.screen.height ||
+ content.wrappedJSObject.screen.availWidth !=
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is not enabled for ScreenAvailRect."
);
}
};
@@ -370,8 +370,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
tab.linkedBrowser,
- [expected.windowOuter.top],
- testWindowOuter
+ [expected.screenAvailRect.top],
+ testScreenAvailRect
);
let expectHWConcurrencyTop = expected.hwConcurrency.top
? SPOOFED_HW_CONCURRENCY
@@ -401,8 +401,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
firstPartyBC,
- [expected.windowOuter.firstParty],
- testWindowOuter
+ [expected.screenAvailRect.firstParty],
+ testScreenAvailRect
);
let expectHWConcurrencyFirstParty = expected.hwConcurrency.firstParty
? SPOOFED_HW_CONCURRENCY
@@ -432,8 +432,8 @@ async function verifyResultInTab(tab, firstPartyBC, thirdPartyBC, expected) {
);
await SpecialPowers.spawn(
thirdPartyBC,
- [expected.windowOuter.thirdParty],
- testWindowOuter
+ [expected.screenAvailRect.thirdParty],
+ testScreenAvailRect
);
let expectHWConcurrencyThirdParty = expected.hwConcurrency.thirdParty
? SPOOFED_HW_CONCURRENCY
@@ -517,7 +517,7 @@ add_task(async function test_popup_inheritance() {
{
id: "1",
last_modified: 1000000000000001,
- overrides: "+WindowOuterSize",
+ overrides: "+ScreenRect,+ScreenAvailRect",
firstPartyDomain: "example.com",
thirdPartyDomain: "example.org",
},
@@ -532,22 +532,22 @@ add_task(async function test_popup_inheritance() {
// Ensure the third-party iframe has the correct overrides.
await SpecialPowers.spawn(thirdPartyFrameBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for third-party iframe."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for third-party iframe."
);
});
// Verify the popup inherits overrides from the opener.
await SpecialPowers.spawn(popupBC, [], _ => {
ok(
- content.wrappedJSObject.outerHeight ==
- content.wrappedJSObject.innerHeight &&
- content.wrappedJSObject.outerWidth ==
- content.wrappedJSObject.innerWidth,
- "Fingerprinting target WindowOuterSize is enabled for the pop-up."
+ content.wrappedJSObject.screen.availHeight ==
+ content.wrappedJSObject.screen.height &&
+ content.wrappedJSObject.screen.availWidth ==
+ content.wrappedJSObject.screen.width,
+ "Fingerprinting target ScreenAvailRect is enabled for the pop-up."
);
content.close();
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/eb4cf95…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/eb4cf95…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-128.2.0esr-14.0-1] fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch mullvad-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
3f90b231 by Pier Angelo Vendrame at 2024-09-02T10:23:18+02:00
fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
Bug 42747: Discard unsupported updates earlier.
Firefox's updater has a function to select updates, which checks mainly
the version number.
Therefore, a more recent update that is unsupported will be chosen over
a compatible one.
We patch this to be able to provide an alternative update path to
Windows 7.
- - - - -
1 changed file:
- toolkit/mozapps/update/UpdateService.sys.mjs
Changes:
=====================================
toolkit/mozapps/update/UpdateService.sys.mjs
=====================================
@@ -3700,18 +3700,20 @@ export class UpdateService {
switch (update.type) {
case "major":
- if (!majorUpdate) {
+ if (!majorUpdate || majorUpdate.unsupported) {
majorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(majorUpdate.appVersion, update.appVersion) <= 0
) {
majorUpdate = update;
}
break;
case "minor":
- if (!minorUpdate) {
+ if (!minorUpdate || minorUpdate.unsupported) {
minorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(minorUpdate.appVersion, update.appVersion) <= 0
) {
minorUpdate = update;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/3f9…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/3f9…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-128.2.0esr-14.0-1] fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch base-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
5661f525 by Pier Angelo Vendrame at 2024-09-02T10:23:38+02:00
fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
Bug 42747: Discard unsupported updates earlier.
Firefox's updater has a function to select updates, which checks mainly
the version number.
Therefore, a more recent update that is unsupported will be chosen over
a compatible one.
We patch this to be able to provide an alternative update path to
Windows 7.
- - - - -
1 changed file:
- toolkit/mozapps/update/UpdateService.sys.mjs
Changes:
=====================================
toolkit/mozapps/update/UpdateService.sys.mjs
=====================================
@@ -3700,18 +3700,20 @@ export class UpdateService {
switch (update.type) {
case "major":
- if (!majorUpdate) {
+ if (!majorUpdate || majorUpdate.unsupported) {
majorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(majorUpdate.appVersion, update.appVersion) <= 0
) {
majorUpdate = update;
}
break;
case "minor":
- if (!minorUpdate) {
+ if (!minorUpdate || minorUpdate.unsupported) {
minorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(minorUpdate.appVersion, update.appVersion) <= 0
) {
minorUpdate = update;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/5661f52…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/5661f52…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-128.2.0esr-14.0-1] 2 commits: fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
by Pier Angelo Vendrame (@pierov) 02 Sep '24
by Pier Angelo Vendrame (@pierov) 02 Sep '24
02 Sep '24
Pier Angelo Vendrame pushed to branch tor-browser-128.2.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
af856ef0 by Pier Angelo Vendrame at 2024-09-02T10:11:08+02:00
fixup! Bug 4234: Use the Firefox Update Process for Base Browser.
Bug 42747: Discard unsupported updates earlier.
Firefox's updater has a function to select updates, which checks mainly
the version number.
Therefore, a more recent update that is unsupported will be chosen over
a compatible one.
We patch this to be able to provide an alternative update path to
Windows 7.
- - - - -
aa6ba139 by Pier Angelo Vendrame at 2024-09-02T10:11:12+02:00
fixup! Bug 19121: reinstate the update.xml hash check
Bug 42737: Drop the hash check on updates.
Updates are already signed, the hash check is redundant.
Revert "Bug 19121: reinstate the update.xml hash check"
This reverts commit 14ac8e5c0aff14dda4b15e435db58bea80960389.
- - - - -
3 changed files:
- toolkit/mozapps/update/UpdateService.sys.mjs
- toolkit/mozapps/update/UpdateTelemetry.sys.mjs
- toolkit/mozapps/update/nsIUpdateService.idl
Changes:
=====================================
toolkit/mozapps/update/UpdateService.sys.mjs
=====================================
@@ -2110,8 +2110,6 @@ class UpdatePatch {
// over writing nsIUpdatePatch attributes.
_attrNames = [
"errorCode",
- "hashFunction",
- "hashValue",
"finalURL",
"selected",
"size",
@@ -2164,8 +2162,6 @@ class UpdatePatch {
}
break;
case "finalURL":
- case "hashFunction":
- case "hashValue":
case "state":
case "type":
case "URL":
@@ -2186,8 +2182,6 @@ class UpdatePatch {
*/
serialize(updates) {
var patch = updates.createElementNS(URI_UPDATE_NS, "patch");
- patch.setAttribute("hashFunction", this.hashFunction);
- patch.setAttribute("hashValue", this.hashValue);
patch.setAttribute("size", this.size);
patch.setAttribute("type", this.type);
patch.setAttribute("URL", this.URL);
@@ -3757,18 +3751,20 @@ export class UpdateService {
switch (update.type) {
case "major":
- if (!majorUpdate) {
+ if (!majorUpdate || majorUpdate.unsupported) {
majorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(majorUpdate.appVersion, update.appVersion) <= 0
) {
majorUpdate = update;
}
break;
case "minor":
- if (!minorUpdate) {
+ if (!minorUpdate || minorUpdate.unsupported) {
minorUpdate = update;
} else if (
+ !update.unsupported &&
vc.compare(minorUpdate.appVersion, update.appVersion) <= 0
) {
minorUpdate = update;
@@ -5876,56 +5872,7 @@ class Downloader {
}
LOG("Downloader:_verifyDownload downloaded size == expected size.");
- let fileStream = Cc[
- "@mozilla.org/network/file-input-stream;1"
- ].createInstance(Ci.nsIFileInputStream);
- fileStream.init(
- destination,
- FileUtils.MODE_RDONLY,
- FileUtils.PERMS_FILE,
- 0
- );
-
- let digest;
- try {
- let hash = Cc["@mozilla.org/security/hash;1"].createInstance(
- Ci.nsICryptoHash
- );
- var hashFunction =
- Ci.nsICryptoHash[this._patch.hashFunction.toUpperCase()];
- if (hashFunction == undefined) {
- throw Components.Exception("", Cr.NS_ERROR_UNEXPECTED);
- }
- hash.init(hashFunction);
- hash.updateFromStream(fileStream, -1);
- // NOTE: For now, we assume that the format of _patch.hashValue is hex
- // encoded binary (such as what is typically output by programs like
- // sha1sum). In the future, this may change to base64 depending on how
- // we choose to compute these hashes.
- hash = hash.finish(false);
- digest = Array.from(hash, (c, i) =>
- hash.charCodeAt(i).toString(16).padStart(2, "0")
- ).join("");
- } catch (e) {
- LOG(
- "Downloader:_verifyDownload - failed to compute hash of the downloaded update archive"
- );
- digest = "";
- }
-
- fileStream.close();
-
- if (digest == this._patch.hashValue.toLowerCase()) {
- LOG("Downloader:_verifyDownload hashes match.");
- return true;
- }
-
- LOG("Downloader:_verifyDownload hashes do not match. ");
- AUSTLMY.pingDownloadCode(
- this.isCompleteUpdate,
- AUSTLMY.DWNLD_ERR_VERIFY_NO_HASH_MATCH
- );
- return false;
+ return true;
}
/**
@@ -6565,9 +6512,6 @@ class Downloader {
" is higher than patch size: " +
this._patch.size
);
- // It's important that we use a different code than
- // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
- // between a hash error and a wrong download error.
AUSTLMY.pingDownloadCode(
this.isCompleteUpdate,
AUSTLMY.DWNLD_ERR_PATCH_SIZE_LARGER
@@ -6586,9 +6530,6 @@ class Downloader {
" is not equal to expected patch size: " +
this._patch.size
);
- // It's important that we use a different code than
- // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
- // between a hash error and a wrong download error.
AUSTLMY.pingDownloadCode(
this.isCompleteUpdate,
AUSTLMY.DWNLD_ERR_PATCH_SIZE_NOT_EQUAL
=====================================
toolkit/mozapps/update/UpdateTelemetry.sys.mjs
=====================================
@@ -190,7 +190,6 @@ export var AUSTLMY = {
DWNLD_ERR_VERIFY_NO_REQUEST: 13,
DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL: 14,
DWNLD_ERR_WRITE_FAILURE: 15,
- DWNLD_ERR_VERIFY_NO_HASH_MATCH: 16,
// Temporary failure code to see if there are failures without an update phase
DWNLD_UNKNOWN_PHASE_ERR_WRITE_FAILURE: 40,
=====================================
toolkit/mozapps/update/nsIUpdateService.idl
=====================================
@@ -39,17 +39,6 @@ interface nsIUpdatePatch : nsISupports
*/
attribute AString finalURL;
- /**
- * The hash function to use when determining this file's integrity
- */
- attribute AString hashFunction;
-
- /**
- * The value of the hash function named above that should be computed if
- * this file is not corrupt.
- */
- attribute AString hashValue;
-
/**
* The size of this file, in bytes.
*/
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a6ebf6…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a6ebf6…
You're receiving this email because of your account on gitlab.torproject.org.
1
0