1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/
6 const { AppConstants } = ChromeUtils.importESModule(
7 "resource://gre/modules/AppConstants.sys.mjs"
9 const { BrowserUsageTelemetry } = ChromeUtils.importESModule(
10 "resource:///modules/BrowserUsageTelemetry.sys.mjs"
12 const { TelemetryTestUtils } = ChromeUtils.importESModule(
13 "resource://testing-common/TelemetryTestUtils.sys.mjs"
15 ChromeUtils.defineESModuleGetters(this, {
16 FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
19 const TIMESTAMP_PREF = "app.installation.timestamp";
21 function encodeUtf16(str) {
22 const buf = new ArrayBuffer(str.length * 2);
23 const utf16 = new Uint16Array(buf);
24 for (let i = 0; i < str.length; i++) {
25 utf16[i] = str.charCodeAt(i);
27 return new Uint8Array(buf);
31 function writeJsonUtf16(fileName, obj) {
32 const str = JSON.stringify(obj);
33 return IOUtils.write(fileName, encodeUtf16(str));
36 async function runReport(
39 { clearTS, setTS, assertRejects, expectExtra, expectTS, msixPrefixes }
43 Services.prefs.clearUserPref(TIMESTAMP_PREF);
45 if (typeof setTS == "string") {
46 Services.prefs.setStringPref(TIMESTAMP_PREF, setTS);
50 Services.telemetry.clearEvents();
52 // Exercise reportInstallationTelemetry
53 if (typeof assertRejects != "undefined") {
55 BrowserUsageTelemetry.reportInstallationTelemetry(dataFile),
58 } else if (!msixPrefixes) {
59 await BrowserUsageTelemetry.reportInstallationTelemetry(dataFile);
61 await BrowserUsageTelemetry.reportInstallationTelemetry(
68 TelemetryTestUtils.assertEvents(
70 ? [{ object: installType, value: null, extra: expectExtra }]
72 { category: "installation", method: "first_seen" }
76 if (typeof expectTS == "string") {
77 Assert.equal(expectTS, Services.prefs.getStringPref(TIMESTAMP_PREF));
83 AppConstants.platform !== "win" ||
84 !Services.sysinfo.getProperty("hasWinPackageId"),
86 add_task(condition, async function testInstallationTelemetryMSIX() {
87 // Unfortunately, we have no way to inject different installation ping data
88 // into the system in a way that doesn't just completely override the code
89 // under test - so other than a basic test of the happy path, there's
90 // nothing we can do here.
92 version: AppConstants.MOZ_APP_VERSION,
93 build_id: AppConstants.MOZ_BULIDID,
98 install_existed: "false",
100 other_msix_inst: "false",
101 profdir_existed: "false",
104 await runReport("fake", "msix", {
105 expectExtra: msixExtra,
110 AppConstants.platform === "win" &&
111 Services.sysinfo.getProperty("hasWinPackageId"),
113 add_task(condition, async function testInstallationTelemetry() {
114 let dataFilePath = await IOUtils.createUniqueFile(
115 Services.dirsvc.get("TmpD", Ci.nsIFile).path,
116 "installation-telemetry-test-data" + Math.random() + ".json"
118 let dataFile = new FileUtils.File(dataFilePath);
120 registerCleanupFunction(async () => {
122 await IOUtils.remove(dataFilePath);
124 // Ignore remove failure, file may not exist by now
127 Services.prefs.clearUserPref(TIMESTAMP_PREF);
130 // Test with normal stub data
134 installer_type: "stub",
136 install_existed: false,
137 profdir_existed: false,
138 install_timestamp: "0",
144 install_existed: "false",
146 other_msix_inst: "false",
147 profdir_existed: "false",
150 await writeJsonUtf16(dataFilePath, stubData);
151 await runReport(dataFile, "stub", {
153 expectExtra: stubExtra,
157 // Check that it doesn't generate another event when the timestamp is unchanged
158 await runReport(dataFile, "stub", { expectTS: "0" });
161 stubData.install_timestamp = "1";
162 await writeJsonUtf16(dataFilePath, stubData);
163 await runReport(dataFile, "stub", {
164 expectExtra: stubExtra,
168 // Test with normal full data
172 installer_type: "full",
174 install_existed: true,
175 profdir_existed: true,
180 install_timestamp: "1",
186 install_existed: "true",
188 other_msix_inst: "false",
189 profdir_existed: "true",
192 default_path: "true",
195 await writeJsonUtf16(dataFilePath, fullData);
196 await runReport(dataFile, "full", {
198 expectExtra: fullExtra,
202 // Check that it doesn't generate another event when the timestamp is unchanged
203 await runReport(dataFile, "full", { expectTS: "1" });
205 // New timestamp and a check to make sure we can find installed MSIX packages
206 // by overriding the prefixes a bit further down.
207 fullData.install_timestamp = "2";
208 // This check only works on Windows
209 if (AppConstants.platform == "win") {
210 fullExtra.other_msix_inst = "true";
212 await writeJsonUtf16(dataFilePath, fullData);
213 await runReport(dataFile, "full", {
214 expectExtra: fullExtra,
216 msixPrefixes: ["Microsoft"],
220 delete fullData.install_existed;
221 fullData.install_timestamp = "3";
222 await writeJsonUtf16(dataFilePath, fullData);
223 await runReport(dataFile, "full", { assertRejects: /install_existed/ });
226 await IOUtils.write(dataFilePath, encodeUtf16("hello"));
227 await runReport(dataFile, "stub", {
228 assertRejects: /unexpected character/,
231 // Missing file, should return with no exception
232 await IOUtils.remove(dataFilePath);
233 await runReport(dataFile, "stub", { setTS: "3", expectTS: "3" });