mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1599567 - Add telemetry for when logins store is unusable because of missing or corrupt logins.json file. r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D78477
This commit is contained in:
parent
1c03261951
commit
a7eff183d5
@ -101,6 +101,12 @@ add_task(async function setup_head() {
|
||||
// Ignore warnings and non-errors.
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.errorMessage.includes('Unknown event: ["jsonfile", "load"')) {
|
||||
// Ignore telemetry errors from JSONFile.jsm.
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
msg.errorMessage == "Refreshing device list failed." ||
|
||||
msg.errorMessage == "Skipping device list refresh; not signed in"
|
||||
|
@ -0,0 +1,67 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"LoginStore",
|
||||
"resource://gre/modules/LoginStore.jsm"
|
||||
);
|
||||
const { TelemetryTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/TelemetryTestUtils.jsm"
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests collecting telemetry when login store is missing.
|
||||
*/
|
||||
add_task(async function test_login_store_missing_telemetry() {
|
||||
// Clear events recorded in the jsonfile category during startup.
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
// Check that logins.json does not exist.
|
||||
let loginsStorePath = OS.Path.join(
|
||||
OS.Constants.Path.profileDir,
|
||||
"logins.json"
|
||||
);
|
||||
Assert.equal(false, await OS.File.exists(loginsStorePath));
|
||||
|
||||
// Create a LoginStore.jsm object and try to load logins.json.
|
||||
let store = new LoginStore(loginsStorePath);
|
||||
await store.load();
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[["jsonfile", "load", "logins"]],
|
||||
{},
|
||||
{ clear: true }
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests collecting telemetry when the login store is corrupt.
|
||||
*/
|
||||
add_task(async function test_login_store_corrupt_telemetry() {
|
||||
let loginsStorePath = OS.Path.join(
|
||||
OS.Constants.Path.profileDir,
|
||||
"logins.json"
|
||||
);
|
||||
let store = new LoginStore(loginsStorePath);
|
||||
|
||||
let string = '{"logins":[{"hostname":"http://www.example.com","id":1,';
|
||||
await OS.File.writeAtomic(store.path, new TextEncoder().encode(string));
|
||||
await store.load();
|
||||
|
||||
// A .corrupt file should have been created.
|
||||
Assert.ok(await OS.File.exists(store.path + ".corrupt"));
|
||||
|
||||
TelemetryTestUtils.assertEvents(
|
||||
[
|
||||
["jsonfile", "load", "logins", ""],
|
||||
["jsonfile", "load", "logins", "invalid_json"],
|
||||
],
|
||||
{},
|
||||
{ clear: true }
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
await OS.File.remove(store.path + ".corrupt");
|
||||
await OS.File.remove(store.path);
|
||||
});
|
@ -8,6 +8,8 @@ support-files = data/**
|
||||
skip-if = os == "android"
|
||||
[test_module_LoginStore.js]
|
||||
skip-if = os == "android"
|
||||
[test_module_LoginStoreTelemetry.js]
|
||||
skip-if = os == "android"
|
||||
|
||||
# The following tests apply to any storage back-end that supports add/modify/remove.
|
||||
[test_context_menu.js]
|
||||
|
@ -780,6 +780,18 @@ pwmgr:
|
||||
- "firefox"
|
||||
record_in_processes: [content, main]
|
||||
|
||||
jsonfile:
|
||||
load:
|
||||
description: >
|
||||
Records when JSONFile.jsm consumers are trying to access a missing or corrupt json file.
|
||||
For example, Login Store trying to access logins.json when it has gone missing or corrupt.
|
||||
objects: ["logins", "autofillprofiles"]
|
||||
bug_numbers: [1599567]
|
||||
expiry_version: never
|
||||
products: ["firefox"]
|
||||
record_in_processes: [main]
|
||||
notification_emails: ["prathiksha@mozilla.com", "passwords-dev@mozilla.org"]
|
||||
|
||||
fxa:
|
||||
connect:
|
||||
objects: ["account"]
|
||||
|
@ -72,6 +72,12 @@ const FileInputStream = Components.Constructor(
|
||||
"init"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Services",
|
||||
"resource://gre/modules/Services.jsm"
|
||||
);
|
||||
|
||||
/**
|
||||
* Delay between a change to the data and the related save operation.
|
||||
*/
|
||||
@ -130,6 +136,8 @@ function JSONFile(config) {
|
||||
"JSON store: writing data",
|
||||
this._finalizeInternalBound
|
||||
);
|
||||
|
||||
Services.telemetry.setEventRecordingEnabled("jsonfile", true);
|
||||
}
|
||||
|
||||
JSONFile.prototype = {
|
||||
@ -213,6 +221,16 @@ JSONFile.prototype = {
|
||||
// just start with new data. Other errors may indicate that the file is
|
||||
// corrupt, thus we move it to a backup location before allowing it to
|
||||
// be overwritten by an empty file.
|
||||
let cleansedBasename = OS.Path.basename(this.path)
|
||||
.replace(/\.json$/, "")
|
||||
.replaceAll(/[^a-zA-Z0-9_.]/g, "");
|
||||
let errorNo = ex.winLastError || ex.unixErrno;
|
||||
Services.telemetry.recordEvent(
|
||||
"jsonfile",
|
||||
"load",
|
||||
cleansedBasename,
|
||||
errorNo ? errorNo.toString() : ""
|
||||
);
|
||||
if (!(ex instanceof OS.File.Error && ex.becauseNoSuchFile)) {
|
||||
Cu.reportError(ex);
|
||||
|
||||
@ -223,6 +241,12 @@ JSONFile.prototype = {
|
||||
});
|
||||
await openInfo.file.close();
|
||||
await OS.File.move(this.path, openInfo.path);
|
||||
Services.telemetry.recordEvent(
|
||||
"jsonfile",
|
||||
"load",
|
||||
cleansedBasename,
|
||||
"invalid_json"
|
||||
);
|
||||
} catch (e2) {
|
||||
Cu.reportError(e2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user