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 --- .../test/unit/test_InstallationTelemetry.js | 284 +++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 browser/modules/test/unit/test_InstallationTelemetry.js (limited to 'browser/modules/test/unit/test_InstallationTelemetry.js') diff --git a/browser/modules/test/unit/test_InstallationTelemetry.js b/browser/modules/test/unit/test_InstallationTelemetry.js new file mode 100644 index 0000000000..64d9964cbe --- /dev/null +++ b/browser/modules/test/unit/test_InstallationTelemetry.js @@ -0,0 +1,284 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ +"use strict"; + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); +const { AttributionIOUtils } = ChromeUtils.importESModule( + "resource:///modules/AttributionCode.sys.mjs" +); +const { BrowserUsageTelemetry } = ChromeUtils.import( + "resource:///modules/BrowserUsageTelemetry.jsm" +); +const { TelemetryTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TelemetryTestUtils.sys.mjs" +); +ChromeUtils.defineESModuleGetters(this, { + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", +}); + +const TIMESTAMP_PREF = "app.installation.timestamp"; + +function encodeUtf16(str) { + const buf = new ArrayBuffer(str.length * 2); + const utf16 = new Uint16Array(buf); + for (let i = 0; i < str.length; i++) { + utf16[i] = str.charCodeAt(i); + } + return new Uint8Array(buf); +} + +// Returns Promise +function writeJsonUtf16(fileName, obj) { + const str = JSON.stringify(obj); + return IOUtils.write(fileName, encodeUtf16(str)); +} + +async function runReport( + dataFile, + installType, + { clearTS, setTS, assertRejects, expectExtra, expectTS, msixPrefixes } +) { + // Setup timestamp + if (clearTS) { + Services.prefs.clearUserPref(TIMESTAMP_PREF); + } + if (typeof setTS == "string") { + Services.prefs.setStringPref(TIMESTAMP_PREF, setTS); + } + + // Init events + Services.telemetry.clearEvents(); + + // Exercise reportInstallationTelemetry + if (typeof assertRejects != "undefined") { + await Assert.rejects( + BrowserUsageTelemetry.reportInstallationTelemetry(dataFile), + assertRejects + ); + } else if (!msixPrefixes) { + await BrowserUsageTelemetry.reportInstallationTelemetry(dataFile); + } else { + await BrowserUsageTelemetry.reportInstallationTelemetry( + dataFile, + msixPrefixes + ); + } + + // Check events + TelemetryTestUtils.assertEvents( + expectExtra + ? [{ object: installType, value: null, extra: expectExtra }] + : [], + { category: "installation", method: "first_seen" }, + { clear: false } + ); + // Provenance Data is currently only supported on Windows. + if (AppConstants.platform == "win") { + let provenanceExtra = { + data_exists: "true", + file_system: "NTFS", + ads_exists: "true", + security_zone: "3", + refer_url_exist: "true", + refer_url_moz: "true", + host_url_exist: "true", + host_url_moz: "true", + }; + TelemetryTestUtils.assertEvents( + expectExtra + ? [{ object: installType, value: null, extra: provenanceExtra }] + : [], + { category: "installation", method: "first_seen_prov_ext" } + ); + } else { + TelemetryTestUtils.assertEvents( + expectExtra ? [{ object: installType, value: null, extra: {} }] : [], + { category: "installation", method: "first_seen_prov_ext" } + ); + } + + // Check timestamp + if (typeof expectTS == "string") { + Assert.equal(expectTS, Services.prefs.getStringPref(TIMESTAMP_PREF)); + } +} + +add_setup(function setup() { + let origReadUTF8 = AttributionIOUtils.readUTF8; + registerCleanupFunction(() => { + AttributionIOUtils.readUTF8 = origReadUTF8; + }); + AttributionIOUtils.readUTF8 = async path => { + return ` +[Mozilla] +fileSystem=NTFS +zoneIdFileSize=194 +zoneIdBufferLargeEnough=true +zoneIdTruncated=false + +[MozillaZoneIdentifierStartSentinel] +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mozilla.org/ +HostUrl=https://download-installer.cdn.mozilla.net/pub/firefox/nightly/latest-mozilla-central-l10n/Firefox%20Installer.en-US.exe +`; + }; +}); + +let condition = { + skip_if: () => + AppConstants.platform !== "win" || + !Services.sysinfo.getProperty("hasWinPackageId"), +}; +add_task(condition, async function testInstallationTelemetryMSIX() { + // Unfortunately, we have no way to inject different installation ping data + // into the system in a way that doesn't just completely override the code + // under test - so other than a basic test of the happy path, there's + // nothing we can do here. + let msixExtra = { + version: AppConstants.MOZ_APP_VERSION, + build_id: AppConstants.MOZ_BULIDID, + admin_user: "false", + from_msi: "false", + silent: "false", + default_path: "true", + install_existed: "false", + other_inst: "false", + other_msix_inst: "false", + profdir_existed: "false", + }; + + await runReport("fake", "msix", { + expectExtra: msixExtra, + }); +}); +condition = { + skip_if: () => + AppConstants.platform === "win" && + Services.sysinfo.getProperty("hasWinPackageId"), +}; +add_task(condition, async function testInstallationTelemetry() { + let dataFilePath = await IOUtils.createUniqueFile( + Services.dirsvc.get("TmpD", Ci.nsIFile).path, + "installation-telemetry-test-data" + Math.random() + ".json" + ); + let dataFile = new FileUtils.File(dataFilePath); + + registerCleanupFunction(async () => { + try { + await IOUtils.remove(dataFilePath); + } catch (ex) { + // Ignore remove failure, file may not exist by now + } + + Services.prefs.clearUserPref(TIMESTAMP_PREF); + }); + + // Test with normal stub data + let stubData = { + version: "99.0abc", + build_id: "123", + installer_type: "stub", + admin_user: true, + install_existed: false, + profdir_existed: false, + install_timestamp: "0", + }; + let stubExtra = { + version: "99.0abc", + build_id: "123", + admin_user: "true", + install_existed: "false", + other_inst: "false", + other_msix_inst: "false", + profdir_existed: "false", + }; + + await writeJsonUtf16(dataFilePath, stubData); + await runReport(dataFile, "stub", { + clearTS: true, + expectExtra: stubExtra, + expectTS: "0", + }); + + // Check that it doesn't generate another event when the timestamp is unchanged + await runReport(dataFile, "stub", { expectTS: "0" }); + + // New timestamp + stubData.install_timestamp = "1"; + await writeJsonUtf16(dataFilePath, stubData); + await runReport(dataFile, "stub", { + expectExtra: stubExtra, + expectTS: "1", + }); + + // Test with normal full data + let fullData = { + version: "99.0abc", + build_id: "123", + installer_type: "full", + admin_user: false, + install_existed: true, + profdir_existed: true, + silent: false, + from_msi: false, + default_path: true, + + install_timestamp: "1", + }; + let fullExtra = { + version: "99.0abc", + build_id: "123", + admin_user: "false", + install_existed: "true", + other_inst: "false", + other_msix_inst: "false", + profdir_existed: "true", + silent: "false", + from_msi: "false", + default_path: "true", + }; + + await writeJsonUtf16(dataFilePath, fullData); + await runReport(dataFile, "full", { + clearTS: true, + expectExtra: fullExtra, + expectTS: "1", + }); + + // Check that it doesn't generate another event when the timestamp is unchanged + await runReport(dataFile, "full", { expectTS: "1" }); + + // New timestamp and a check to make sure we can find installed MSIX packages + // by overriding the prefixes a bit further down. + fullData.install_timestamp = "2"; + // This check only works on Windows 10 and above + if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) { + fullExtra.other_msix_inst = "true"; + } + await writeJsonUtf16(dataFilePath, fullData); + await runReport(dataFile, "full", { + expectExtra: fullExtra, + expectTS: "2", + msixPrefixes: ["Microsoft"], + }); + + // Missing field + delete fullData.install_existed; + fullData.install_timestamp = "3"; + await writeJsonUtf16(dataFilePath, fullData); + await runReport(dataFile, "full", { assertRejects: /install_existed/ }); + + // Malformed JSON + await IOUtils.write(dataFilePath, encodeUtf16("hello")); + await runReport(dataFile, "stub", { + assertRejects: /unexpected character/, + }); + + // Missing file, should return with no exception + await IOUtils.remove(dataFilePath); + await runReport(dataFile, "stub", { setTS: "3", expectTS: "3" }); +}); -- cgit v1.2.3