From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../rs-blocklist/test_blocklist_mlbf_dump.js | 156 +++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_mlbf_dump.js (limited to 'toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_mlbf_dump.js') diff --git a/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_mlbf_dump.js b/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_mlbf_dump.js new file mode 100644 index 0000000000..3cbd607339 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/rs-blocklist/test_blocklist_mlbf_dump.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * @fileOverview Verifies that the MLBF dump of the addons blocklist is + * correctly registered. + */ + +Services.prefs.setBoolPref("extensions.blocklist.useMLBF", true); + +const ExtensionBlocklistMLBF = getExtensionBlocklistMLBF(); + +// A known blocked version from bug 1626602. +const blockedAddon = { + id: "{6f62927a-e380-401a-8c9e-c485b7d87f0d}", + version: "9.2.0", + // The following date is the date of the first checked in MLBF. Any MLBF + // generated in the future should be generated after this date, to be useful. + signedDate: new Date(1588098908496), // 2020-04-28 (dummy date) + signedState: AddonManager.SIGNEDSTATE_SIGNED, +}; + +// A known add-on that is not blocked, as of writing. It is likely not going +// to be blocked because it does not have any executable code. +const nonBlockedAddon = { + id: "disable-ctrl-q-and-cmd-q@robwu.nl", + version: "1", + signedDate: new Date(1482430349000), // 2016-12-22 (actual signing time). + signedState: AddonManager.SIGNEDSTATE_SIGNED, +}; + +async function sha256(arrayBuffer) { + Cu.importGlobalProperties(["crypto"]); + let hash = await crypto.subtle.digest("SHA-256", arrayBuffer); + const toHex = b => b.toString(16).padStart(2, "0"); + return Array.from(new Uint8Array(hash), toHex).join(""); +} + +// A list of { inputRecord, downloadPromise }: +// - inputRecord is the record that was used for looking up the MLBF. +// - downloadPromise is the result of trying to download it. +const observed = []; + +add_task(async function setup() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + ExtensionBlocklistMLBF.ensureInitialized(); + + // Tapping into the internals of ExtensionBlocklistMLBF._fetchMLBF to observe + // MLBF request details. + + // Despite being called "download", this does not actually access the network + // when there is a valid dump. + const originalImpl = ExtensionBlocklistMLBF._client.attachments.download; + ExtensionBlocklistMLBF._client.attachments.download = function (record) { + let downloadPromise = originalImpl.apply(this, arguments); + observed.push({ inputRecord: record, downloadPromise }); + return downloadPromise; + }; + + await promiseStartupManager(); +}); + +async function verifyBlocklistWorksWithDump() { + Assert.equal( + await Blocklist.getAddonBlocklistState(blockedAddon), + Ci.nsIBlocklistService.STATE_BLOCKED, + "A add-on that is known to be on the blocklist should be blocked" + ); + Assert.equal( + await Blocklist.getAddonBlocklistState(nonBlockedAddon), + Ci.nsIBlocklistService.STATE_NOT_BLOCKED, + "A known non-blocked add-on should not be blocked" + ); +} + +add_task(async function verify_dump_first_run() { + await verifyBlocklistWorksWithDump(); + Assert.equal(observed.length, 1, "expected number of MLBF download requests"); + + const { inputRecord, downloadPromise } = observed.pop(); + + Assert.ok(inputRecord, "addons-bloomfilters collection dump exists"); + + const downloadResult = await downloadPromise; + + // Verify that the "download" result really originates from the local dump. + // "dump_match" means that the record exists in the collection and that an + // attachment was found. + // + // If this fails: + // - "dump_fallback" means that the MLBF attachment is out of sync with the + // collection data. + // - undefined could mean that the implementation of Attachments.sys.mjs changed. + Assert.equal( + downloadResult._source, + "dump_match", + "MLBF attachment should match the RemoteSettings collection" + ); + + Assert.equal( + await sha256(downloadResult.buffer), + inputRecord.attachment.hash, + "The content of the attachment should actually matches the record" + ); +}); + +add_task(async function use_dump_fallback_when_collection_is_out_of_sync() { + await AddonTestUtils.loadBlocklistRawData({ + // last_modified higher than any value in addons-bloomfilters.json. + extensionsMLBF: [{ last_modified: Date.now() }], + }); + Assert.equal(observed.length, 1, "Expected new download on update"); + + const { inputRecord, downloadPromise } = observed.pop(); + Assert.equal(inputRecord, null, "No MLBF record found"); + + const downloadResult = await downloadPromise; + Assert.equal( + downloadResult._source, + "dump_fallback", + "should have used fallback despite the absence of a MLBF record" + ); + + await verifyBlocklistWorksWithDump(); + Assert.equal(observed.length, 0, "Blocklist uses cached result"); +}); + +// Verifies that the dump would supersede local data. This can happen after an +// application upgrade, where the local database contains outdated records from +// a previous application version. +add_task(async function verify_dump_supersedes_old_dump() { + // Delete in-memory value; otherwise the cached record from the previous test + // task would be re-used and nothing would be downloaded. + delete ExtensionBlocklistMLBF._mlbfData; + + await AddonTestUtils.loadBlocklistRawData({ + // last_modified lower than any value in addons-bloomfilters.json. + extensionsMLBF: [{ last_modified: 1 }], + }); + Assert.equal(observed.length, 1, "Expected new download on update"); + + const { inputRecord, downloadPromise } = observed.pop(); + Assert.ok(inputRecord, "should have read from addons-bloomfilters dump"); + + const downloadResult = await downloadPromise; + Assert.equal( + downloadResult._source, + "dump_match", + "Should have replaced outdated collection records with dump" + ); + + await verifyBlocklistWorksWithDump(); + Assert.equal(observed.length, 0, "Blocklist uses cached result"); +}); -- cgit v1.2.3