merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-02-02 13:10:48 +01:00
commit 4f8b724cf4
4 changed files with 242 additions and 18 deletions

View File

@ -20,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
const MS_PER_DAY = 24 * 60 * 60 * 1000;
var debug = false;
function log(...pieces) {
function generateLogMessage(args) {
@ -201,34 +203,65 @@ LoginManager.prototype = {
"passwordmgr-storage-replace-complete", null);
}.bind(this));
} else if (topic == "gather-telemetry") {
this._pwmgr._gatherTelemetry();
// When testing, the "data" parameter is a string containing the
// reference time in milliseconds for time-based statistics.
this._pwmgr._gatherTelemetry(data ? parseInt(data)
: new Date().getTime());
} else {
log("Oops! Unexpected notification:", topic);
}
}
},
_gatherTelemetry : function() {
let numPasswordsBlocklist = Services.telemetry.getHistogramById("PWMGR_BLOCKLIST_NUM_SITES");
numPasswordsBlocklist.clear();
numPasswordsBlocklist.add(this.getAllDisabledHosts({}).length);
/**
* Collects statistics about the current logins and settings. The telemetry
* histograms used here are not accumulated, but are reset each time this
* function is called, since it can be called multiple times in a session.
*
* This function might also not be called at all in the current session.
*
* @param referenceTimeMs
* Current time used to calculate time-based statistics, expressed as
* the number of milliseconds since January 1, 1970, 00:00:00 UTC.
* This is set to a fake value during unit testing.
*/
_gatherTelemetry : function (referenceTimeMs) {
function clearAndGetHistogram(histogramId) {
let histogram = Services.telemetry.getHistogramById(histogramId);
histogram.clear();
return histogram;
}
let numPasswordsHist = Services.telemetry.getHistogramById("PWMGR_NUM_SAVED_PASSWORDS");
numPasswordsHist.clear();
numPasswordsHist.add(this.countLogins("", "", ""));
clearAndGetHistogram("PWMGR_BLOCKLIST_NUM_SITES").add(
this.getAllDisabledHosts({}).length
);
clearAndGetHistogram("PWMGR_NUM_SAVED_PASSWORDS").add(
this.countLogins("", "", "")
);
let isPwdSavedEnabledHist = Services.telemetry.getHistogramById("PWMGR_SAVING_ENABLED");
isPwdSavedEnabledHist.clear();
isPwdSavedEnabledHist.add(this._remember);
// This is a boolean histogram, and not a flag, because we don't want to
// record any value if _gatherTelemetry is not called.
clearAndGetHistogram("PWMGR_SAVING_ENABLED").add(this._remember);
// Don't try to get logins if MP is enabled, since we don't want to show a MP prompt.
if (this.isLoggedIn) {
let logins = this.getAllLogins({});
if (!this.isLoggedIn) {
return;
}
let usernameHist = Services.telemetry.getHistogramById("PWMGR_USERNAME_PRESENT");
usernameHist.clear();
for (let login of logins) {
usernameHist.add(!!login.username);
let logins = this.getAllLogins({});
let usernamePresentHistogram = clearAndGetHistogram("PWMGR_USERNAME_PRESENT");
let loginLastUsedDaysHistogram = clearAndGetHistogram("PWMGR_LOGIN_LAST_USED_DAYS");
for (let login of logins) {
usernamePresentHistogram.add(!!login.username);
login.QueryInterface(Ci.nsILoginMetaInfo);
let timeLastUsedAgeMs = referenceTimeMs - login.timeLastUsed;
if (timeLastUsedAgeMs > 0) {
loginLastUsedDaysHistogram.add(
Math.floor(timeLastUsedAgeMs / MS_PER_DAY)
);
}
}
},

View File

@ -0,0 +1,183 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests the statistics and other counters reported through telemetry.
*/
"use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
const MS_PER_DAY = 24 * 60 * 60 * 1000;
// To prevent intermittent failures when the test is executed at a time that is
// very close to a day boundary, we make it deterministic by using a static
// reference date for all the time-based statistics.
const gReferenceTimeMs = new Date("2000-01-01T00:00:00").getTime();
// Returns a milliseconds value to use with nsILoginMetaInfo properties, falling
// approximately in the middle of the specified number of days before the
// reference time, where zero days indicates a time within the past 24 hours.
let daysBeforeMs = days => gReferenceTimeMs - (days + 0.5) * MS_PER_DAY;
/**
* Contains metadata that will be attached to test logins in order to verify
* that the statistics collection is working properly. Most properties of the
* logins are initialized to the default test values already.
*
* If you update this data or any of the telemetry histograms it checks, you'll
* probably need to update the expected statistics in the test below.
*/
const StatisticsTestData = [
{
timeLastUsed: daysBeforeMs(0),
},
{
timeLastUsed: daysBeforeMs(1),
},
{
timeLastUsed: daysBeforeMs(7),
},
{
username: "",
timeLastUsed: daysBeforeMs(7),
},
{
username: "",
timeLastUsed: daysBeforeMs(30),
},
{
username: "",
timeLastUsed: daysBeforeMs(31),
},
{
timeLastUsed: daysBeforeMs(365),
},
{
username: "",
timeLastUsed: daysBeforeMs(366),
},
{
// If the login was saved in the future, it is ignored for statistiscs.
timeLastUsed: daysBeforeMs(-1),
},
{
timeLastUsed: daysBeforeMs(1000),
},
];
/**
* Triggers the collection of those statistics that are not accumulated each
* time an action is taken, but are a static snapshot of the current state.
*/
function triggerStatisticsCollection() {
Services.obs.notifyObservers(null, "gather-telemetry", "" + gReferenceTimeMs);
}
/**
* Tests the telemetry histogram with the given ID contains only the specified
* non-zero ranges, expressed in the format { range1: value1, range2: value2 }.
*/
function testHistogram(histogramId, expectedNonZeroRanges) {
let snapshot = Services.telemetry.getHistogramById(histogramId).snapshot();
// Compute the actual ranges in the format { range1: value1, range2: value2 }.
let actualNonZeroRanges = {};
for (let [index, range] of snapshot.ranges.entries()) {
let value = snapshot.counts[index];
if (value > 0) {
actualNonZeroRanges[range] = value;
}
}
// These are stringified to visualize the differences between the values.
do_print("Testing histogram: " + histogramId);
do_check_eq(JSON.stringify(actualNonZeroRanges),
JSON.stringify(expectedNonZeroRanges));
}
////////////////////////////////////////////////////////////////////////////////
//// Tests
/**
* Enable local telemetry recording for the duration of the tests, and prepare
* the test data that will be used by the following tests.
*/
add_task(function test_initialize() {
let oldCanRecord = Services.telemetry.canRecord;
Services.telemetry.canRecord = true;
do_register_cleanup(function () {
Services.telemetry.canRecord = oldCanRecord;
});
let uniqueNumber = 1;
for (let loginModifications of StatisticsTestData) {
loginModifications.hostname = `http://${uniqueNumber++}.example.com`;
Services.logins.addLogin(TestData.formLogin(loginModifications));
}
});
/**
* Tests the collection of statistics related to login metadata.
*/
add_task(function test_logins_statistics() {
// Repeat the operation twice to test that histograms are not accumulated.
for (let repeating of [false, true]) {
triggerStatisticsCollection();
// Should record 1 in the bucket corresponding to the number of passwords.
testHistogram("PWMGR_NUM_SAVED_PASSWORDS",
{ 10: 1 });
// For each saved login, should record 1 in the bucket corresponding to the
// age in days since the login was last used.
testHistogram("PWMGR_LOGIN_LAST_USED_DAYS",
{ 0: 1, 1: 1, 7: 2, 29: 2, 356: 2, 750: 1 });
// Should record the number of logins without a username in bucket 0, and
// the number of logins with a username in bucket 1.
testHistogram("PWMGR_USERNAME_PRESENT",
{ 0: 4, 1: 6 });
}
});
/**
* Tests the collection of statistics related to hosts for which passowrd saving
* has been explicitly disabled.
*/
add_task(function test_disabledHosts_statistics() {
// Should record 1 in the bucket corresponding to the number of sites for
// which password saving is disabled.
Services.logins.setLoginSavingEnabled("http://www.example.com", false);
triggerStatisticsCollection();
testHistogram("PWMGR_BLOCKLIST_NUM_SITES", { 1: 1 });
Services.logins.setLoginSavingEnabled("http://www.example.com", true);
triggerStatisticsCollection();
testHistogram("PWMGR_BLOCKLIST_NUM_SITES", { 0: 1 });
});
/**
* Tests the collection of statistics related to general settings.
*/
add_task(function test_settings_statistics() {
let oldRememberSignons = Services.prefs.getBoolPref("signon.rememberSignons");
do_register_cleanup(function () {
Services.prefs.setBoolPref("signon.rememberSignons", oldRememberSignons);
});
// Repeat the operation twice per value to test that histograms are reset.
for (let remember of [false, true, false, true]) {
// This change should be observed immediately by the login service.
Services.prefs.setBoolPref("signon.rememberSignons", remember);
triggerStatisticsCollection();
// Should record 1 in either bucket 0 or bucket 1 based on the preference.
testHistogram("PWMGR_SAVING_ENABLED", remember ? { 1: 1 } : { 0: 1 });
}
});

View File

@ -24,3 +24,4 @@ skip-if = os != "android"
[test_logins_search.js]
[test_notifications.js]
[test_storage.js]
[test_telemetry.js]

View File

@ -7268,7 +7268,14 @@
"high": 750,
"n_buckets" : 50,
"extended_statistics_ok": true,
"description": "The number of saved signons in storage"
"description": "Total number of saved logins, including those that cannot be decrypted"
},
"PWMGR_LOGIN_LAST_USED_DAYS": {
"expires_in_version": "never",
"kind": "exponential",
"high": 750,
"n_buckets" : 40,
"description": "Time in days each saved login was last used"
},
"PWMGR_SAVING_ENABLED": {
"expires_in_version": "never",