Skip to content

Commit b7ba2ef

Browse files
committed
Backed out 3 changesets (bug 1865845) for bc failures on browser_AttributionCode_telemetry.js . CLOSED TREE
Backed out changeset 4f799b89c628 (bug 1865845) Backed out changeset e825fb03ff56 (bug 1865845) Backed out changeset 9a8c396a22db (bug 1865845)
1 parent a8c700a commit b7ba2ef

13 files changed

+243
-169
lines changed

browser/components/attribution/AttributionCode.sys.mjs

Lines changed: 133 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
1616
const lazy = {};
1717
ChromeUtils.defineESModuleGetters(lazy, {
1818
MacAttribution: "resource:///modules/MacAttribution.sys.mjs",
19+
UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
1920
});
2021
ChromeUtils.defineLazyGetter(lazy, "log", () => {
2122
let { ConsoleAPI } = ChromeUtils.importESModule(
@@ -81,6 +82,49 @@ export var AttributionCode = {
8182
let file = Services.dirsvc.get("GreD", Ci.nsIFile);
8283
file.append("postSigningData");
8384
return file;
85+
} else if (AppConstants.platform == "macosx") {
86+
// There's no `UpdRootD` in xpcshell tests. Some existing tests override
87+
// it, which is onerous and difficult to share across tests. When testing,
88+
// if it's not defined, fallback to a nested subdirectory of the xpcshell
89+
// temp directory. Nesting more closely replicates the situation where the
90+
// update directory does not (yet) exist, testing a scenario witnessed in
91+
// development.
92+
let file;
93+
try {
94+
file = Services.dirsvc.get("UpdRootD", Ci.nsIFile);
95+
} catch (ex) {
96+
// It's most common to test for the profile dir, even though we actually
97+
// are using the temp dir.
98+
if (
99+
ex instanceof Ci.nsIException &&
100+
ex.result == Cr.NS_ERROR_FAILURE &&
101+
Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")
102+
) {
103+
let path = Services.env.get("XPCSHELL_TEST_TEMP_DIR");
104+
file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
105+
file.initWithPath(path);
106+
file.append("nested_UpdRootD_1");
107+
file.append("nested_UpdRootD_2");
108+
} else {
109+
throw ex;
110+
}
111+
}
112+
// Note: this file is in a location that includes the absolute path
113+
// to the running install, and the filename includes the update channel.
114+
// To ensure consistency regardless of when `attributionFile` is accessed we
115+
// explicitly do not include partner IDs that may be part of the full update channel.
116+
// These are not necessarily applied when this is first accessed, and we want to
117+
// ensure consistency between early and late accesses.
118+
// Partner builds never contain attribution information, so this has no known
119+
// consequences.
120+
// For example:
121+
// ~/Library/Caches/Mozilla/updates/Applications/Firefox/macAttributionDataCache-release
122+
// This is done to ensure that attribution data is preserved through a
123+
// pave over install of an install on the same channel.
124+
file.append(
125+
"macAttributionDataCache-" + lazy.UpdateUtils.getUpdateChannel(false)
126+
);
127+
return file;
84128
}
85129

86130
return null;
@@ -91,8 +135,8 @@ export var AttributionCode = {
91135
* @param {String} code to write.
92136
*/
93137
async writeAttributionFile(code) {
94-
// Writing attribution files is only used as part of test code
95-
// so bailing here for MSIX builds is no big deal.
138+
// Writing attribution files is only used as part of test code, and Mac
139+
// attribution, so bailing here for MSIX builds is no big deal.
96140
if (
97141
AppConstants.platform === "win" &&
98142
Services.sysinfo.getProperty("hasWinPackageId")
@@ -183,58 +227,6 @@ export var AttributionCode = {
183227
return s;
184228
},
185229

186-
async _getMacAttrDataAsync() {
187-
// On macOS, we fish the attribution data from an extended attribute on
188-
// the .app bundle directory.
189-
try {
190-
let attrStr = await lazy.MacAttribution.getAttributionString();
191-
lazy.log.debug(
192-
`_getMacAttrDataAsync: getAttributionString: "${attrStr}"`
193-
);
194-
195-
gCachedAttrData = this.parseAttributionCode(attrStr);
196-
} catch (ex) {
197-
// Avoid partial attribution data.
198-
gCachedAttrData = {};
199-
200-
// No attributions. Just `warn` 'cuz this isn't necessarily an error.
201-
lazy.log.warn("Caught exception fetching macOS attribution codes!", ex);
202-
203-
if (
204-
ex instanceof Ci.nsIException &&
205-
ex.result == Cr.NS_ERROR_UNEXPECTED
206-
) {
207-
// Bad quarantine data.
208-
Services.telemetry
209-
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
210-
.add("quarantine_error");
211-
}
212-
}
213-
214-
lazy.log.debug(
215-
`macOS attribution data is ${JSON.stringify(gCachedAttrData)}`
216-
);
217-
218-
return gCachedAttrData;
219-
},
220-
221-
async _getWindowsNSISAttrDataAsync() {
222-
return AttributionIOUtils.read(this.attributionFile.path);
223-
},
224-
225-
async _getWindowsMSIXAttrDataAsync() {
226-
// This comes out of windows-package-manager _not_ URL encoded or in an ArrayBuffer,
227-
// but the parsing code wants it that way. It's easier to just provide that
228-
// than have the parsing code support both.
229-
lazy.log.debug(
230-
`winPackageFamilyName is: ${Services.sysinfo.getProperty(
231-
"winPackageFamilyName"
232-
)}`
233-
);
234-
let encoder = new TextEncoder();
235-
return encoder.encode(encodeURIComponent(await this.msixCampaignId));
236-
},
237-
238230
/**
239231
* Reads the attribution code, either from disk or a cached version.
240232
* Returns a promise that fulfills with an object containing the parsed
@@ -246,10 +238,6 @@ export var AttributionCode = {
246238
* strip "utm_" while retrieving the params.
247239
*/
248240
async getAttrDataAsync() {
249-
if (AppConstants.platform != "win" && AppConstants.platform != "macosx") {
250-
// This platform doesn't support attribution.
251-
return gCachedAttrData;
252-
}
253241
if (gCachedAttrData != null) {
254242
lazy.log.debug(
255243
`getAttrDataAsync: attribution is cached: ${JSON.stringify(
@@ -271,26 +259,98 @@ export var AttributionCode = {
271259
}
272260

273261
gCachedAttrData = {};
262+
let attributionFile = this.attributionFile;
263+
if (!attributionFile) {
264+
// This platform doesn't support attribution.
265+
lazy.log.debug(
266+
`getAttrDataAsync: no attribution (attributionFile is null)`
267+
);
268+
return gCachedAttrData;
269+
}
274270

275-
if (AppConstants.platform == "macosx") {
276-
lazy.log.debug(`getAttrDataAsync: macOS`);
277-
return this._getMacAttrDataAsync();
271+
if (
272+
AppConstants.platform == "macosx" &&
273+
!(await AttributionIOUtils.exists(attributionFile.path))
274+
) {
275+
lazy.log.debug(
276+
`getAttrDataAsync: macOS && !exists("${attributionFile.path}")`
277+
);
278+
279+
// On macOS, we fish the attribution data from an extended attribute on
280+
// the .app bundle directory.
281+
try {
282+
let attrStr = await lazy.MacAttribution.getAttributionString();
283+
lazy.log.debug(
284+
`getAttrDataAsync: macOS attribution getAttributionString: "${attrStr}"`
285+
);
286+
287+
gCachedAttrData = this.parseAttributionCode(attrStr);
288+
} catch (ex) {
289+
// Avoid partial attribution data.
290+
gCachedAttrData = {};
291+
292+
// No attributions. Just `warn` 'cuz this isn't necessarily an error.
293+
lazy.log.warn("Caught exception fetching macOS attribution codes!", ex);
294+
295+
if (
296+
ex instanceof Ci.nsIException &&
297+
ex.result == Cr.NS_ERROR_UNEXPECTED
298+
) {
299+
// Bad quarantine data.
300+
Services.telemetry
301+
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
302+
.add("quarantine_error");
303+
}
304+
}
305+
306+
lazy.log.debug(
307+
`macOS attribution data is ${JSON.stringify(gCachedAttrData)}`
308+
);
309+
310+
// We only want to try to fetch the attribution string once on macOS
311+
try {
312+
let code = this.serializeAttributionData(gCachedAttrData);
313+
lazy.log.debug(`macOS attribution data serializes as "${code}"`);
314+
await this.writeAttributionFile(code);
315+
} catch (ex) {
316+
lazy.log.debug(
317+
`Caught exception writing "${attributionFile.path}"`,
318+
ex
319+
);
320+
Services.telemetry
321+
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
322+
.add("write_error");
323+
return gCachedAttrData;
324+
}
325+
326+
lazy.log.debug(
327+
`Returning after successfully writing "${attributionFile.path}"`
328+
);
329+
return gCachedAttrData;
278330
}
279331

280-
lazy.log.debug("getAttrDataAsync: !macOS");
332+
lazy.log.debug(
333+
`getAttrDataAsync: !macOS || !exists("${attributionFile.path}")`
334+
);
281335

282-
let attributionFile = this.attributionFile;
283336
let bytes;
284337
try {
285338
if (
286339
AppConstants.platform === "win" &&
287340
Services.sysinfo.getProperty("hasWinPackageId")
288341
) {
289-
lazy.log.debug("getAttrDataAsync: MSIX");
290-
bytes = await this._getWindowsMSIXAttrDataAsync();
342+
// This comes out of windows-package-manager _not_ URL encoded or in an ArrayBuffer,
343+
// but the parsing code wants it that way. It's easier to just provide that
344+
// than have the parsing code support both.
345+
lazy.log.debug(
346+
`winPackageFamilyName is: ${Services.sysinfo.getProperty(
347+
"winPackageFamilyName"
348+
)}`
349+
);
350+
let encoder = new TextEncoder();
351+
bytes = encoder.encode(encodeURIComponent(await this.msixCampaignId()));
291352
} else {
292-
lazy.log.debug("getAttrDataAsync: NSIS");
293-
bytes = await this._getWindowsNSISAttrDataAsync();
353+
bytes = await AttributionIOUtils.read(attributionFile.path);
294354
}
295355
} catch (ex) {
296356
if (DOMException.isInstance(ex) && ex.name == "NotFoundError") {
@@ -359,15 +419,12 @@ export var AttributionCode = {
359419
* or if the file couldn't be deleted (the promise is never rejected).
360420
*/
361421
async deleteFileAsync() {
362-
// There is no cache file on macOS
363-
if (AppConstants.platform == "win") {
364-
try {
365-
await IOUtils.remove(this.attributionFile.path);
366-
} catch (ex) {
367-
// The attribution file may already have been deleted,
368-
// or it may have never been installed at all;
369-
// failure to delete it isn't an error.
370-
}
422+
try {
423+
await IOUtils.remove(this.attributionFile.path);
424+
} catch (ex) {
425+
// The attribution file may already have been deleted,
426+
// or it may have never been installed at all;
427+
// failure to delete it isn't an error.
371428
}
372429
},
373430

browser/components/attribution/MacAttribution.sys.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export var MacAttribution = {
1818
return IOUtils.setMacXAttr(
1919
path,
2020
"com.apple.application-instance",
21-
new TextEncoder().encode(`__MOZCUSTOM__${aAttrStr}`)
21+
new TextEncoder().encode(aAttrStr)
2222
);
2323
},
2424

browser/components/attribution/test/browser/browser.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ prefs = ["browser.attribution.macos.enabled=true"]
66
skip-if = ["toolkit != 'cocoa'"] # macOS only telemetry.
77

88
["browser_AttributionCode_telemetry.js"]
9-
# These tests only cover the attribution cache file - which only exists on
10-
# Windows.
11-
skip-if = ["os != 'win'"]
9+
skip-if = ["(os != 'win' && toolkit != 'cocoa')"] # Windows and macOS only telemetry.

0 commit comments

Comments
 (0)