1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
ChromeUtils.defineESModuleGetters(this, {
TelemetryTestUtils: "resource://testing-common/TelemetryTestUtils.sys.mjs",
});
const { AttributionIOUtils } = ChromeUtils.importESModule(
"resource:///modules/AttributionCode.sys.mjs"
);
add_task(async function test_parse_error() {
if (AppConstants.platform == "macosx") {
// On macOS, the underlying data is the OS-level quarantine
// database. We need to start from nothing to isolate the cache.
const { MacAttribution } = ChromeUtils.importESModule(
"resource:///modules/MacAttribution.sys.mjs"
);
let attributionSvc = Cc["@mozilla.org/mac-attribution;1"].getService(
Ci.nsIMacAttributionService
);
attributionSvc.setReferrerUrl(MacAttribution.applicationPath, "", true);
}
registerCleanupFunction(async () => {
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
});
const histogram = Services.telemetry.getHistogramById(
"BROWSER_ATTRIBUTION_ERRORS"
);
// Delete the file to trigger a read error
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
// Clear any existing telemetry
histogram.clear();
let result = await AttributionCode.getAttrDataAsync();
Assert.deepEqual(
result,
{},
"Shouldn't be able to get a result if the file doesn't exist"
);
// Write an invalid file to trigger a decode error
// Skip this for MSIX packages though - we can't write or delete
// the attribution file there, everything happens in memory instead.
if (
AppConstants.platform === "win" &&
!Services.sysinfo.getProperty("hasWinPackageId")
) {
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
// Empty string is valid on macOS.
await AttributionCode.writeAttributionFile(
AppConstants.platform == "macosx" ? "invalid" : ""
);
result = await AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, {}, "Should have failed to parse");
// `assertHistogram` also ensures that `read_error` index 0 is 0
// as we should not have recorded telemetry from the previous `getAttrDataAsync` call
TelemetryTestUtils.assertHistogram(histogram, INDEX_DECODE_ERROR, 1);
// Reset
histogram.clear();
}
});
add_task(async function test_read_error() {
registerCleanupFunction(async () => {
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
});
const histogram = Services.telemetry.getHistogramById(
"BROWSER_ATTRIBUTION_ERRORS"
);
// Delete the file to trigger a read error
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
// Clear any existing telemetry
histogram.clear();
// Force the file to exist but then cause a read error
let oldExists = AttributionIOUtils.exists;
AttributionIOUtils.exists = () => true;
let oldRead = AttributionIOUtils.read;
AttributionIOUtils.read = () => {
throw new Error("read_error");
};
registerCleanupFunction(() => {
AttributionIOUtils.exists = oldExists;
AttributionIOUtils.read = oldRead;
});
// Try to read the file
await AttributionCode.getAttrDataAsync();
// It should record the read error
TelemetryTestUtils.assertHistogram(histogram, INDEX_READ_ERROR, 1);
// Clear any existing telemetry
histogram.clear();
});
|