mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Bug 942340 - Extracting many Telemetry statistics from sessionstore.js;r=ttaubert,froydnj
This commit is contained in:
parent
8af872bb5f
commit
3270b823df
@ -58,6 +58,22 @@ this.SessionFile = {
|
||||
write: function (aData) {
|
||||
return SessionFileInternal.write(aData);
|
||||
},
|
||||
/**
|
||||
* Gather telemetry statistics.
|
||||
*
|
||||
*
|
||||
* Most of the work is done off the main thread but there is a main
|
||||
* thread cost involved to send data to the worker thread. This method
|
||||
* should therefore be called only when we know that it will not disrupt
|
||||
* the user's experience, e.g. on idle-daily.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @promise {object} An object holding all the information to be submitted
|
||||
* to Telemetry.
|
||||
*/
|
||||
gatherTelemetry: function(aData) {
|
||||
return SessionFileInternal.gatherTelemetry(aData);
|
||||
},
|
||||
/**
|
||||
* Writes the initial state to disk again only to change the session's load
|
||||
* state. This must only be called once, it will throw an error otherwise.
|
||||
@ -122,6 +138,14 @@ let SessionFileInternal = {
|
||||
});
|
||||
},
|
||||
|
||||
gatherTelemetry: function(aStateString) {
|
||||
return Task.spawn(function() {
|
||||
let msg = yield SessionWorker.post("gatherTelemetry", [aStateString]);
|
||||
this._recordTelemetry(msg.telemetry);
|
||||
throw new Task.Result(msg.telemetry);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
write: function (aData) {
|
||||
if (this._isClosed) {
|
||||
return Promise.reject(new Error("SessionFile is closed"));
|
||||
@ -177,8 +201,18 @@ let SessionFileInternal = {
|
||||
},
|
||||
|
||||
_recordTelemetry: function(telemetry) {
|
||||
for (let histogramId in telemetry){
|
||||
Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]);
|
||||
for (let id of Object.keys(telemetry)){
|
||||
let value = telemetry[id];
|
||||
let samples = [];
|
||||
if (Array.isArray(value)) {
|
||||
samples.push(...value);
|
||||
} else {
|
||||
samples.push(value);
|
||||
}
|
||||
let histogram = Telemetry.getHistogramById(id);
|
||||
for (let sample of samples) {
|
||||
histogram.add(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -196,9 +230,12 @@ let SessionWorker = (function () {
|
||||
// Decode any serialized error
|
||||
if (error instanceof PromiseWorker.WorkerError) {
|
||||
throw OS.File.Error.fromMsg(error.data);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
// Extract something meaningful from ErrorEvent
|
||||
if (error instanceof ErrorEvent) {
|
||||
throw new Error(error.message, error.filename, error.lineno);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ const OBSERVING = [
|
||||
"quit-application-requested", "quit-application-granted",
|
||||
"browser-lastwindow-close-granted",
|
||||
"quit-application", "browser:purge-session-history",
|
||||
"browser:purge-domain-data"
|
||||
"browser:purge-domain-data",
|
||||
"gather-telemetry",
|
||||
];
|
||||
|
||||
// XUL Window properties to (re)store
|
||||
@ -587,6 +588,9 @@ let SessionStoreInternal = {
|
||||
case "nsPref:changed": // catch pref changes
|
||||
this.onPrefChange(aData);
|
||||
break;
|
||||
case "gather-telemetry":
|
||||
this.onGatherTelemetry();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1457,6 +1461,16 @@ let SessionStoreInternal = {
|
||||
this.saveStateDelayed(aWindow);
|
||||
},
|
||||
|
||||
onGatherTelemetry: function() {
|
||||
// On the first gather-telemetry notification of the session,
|
||||
// gather telemetry data.
|
||||
Services.obs.removeObserver(this, "gather-telemetry");
|
||||
this.fillTabCachesAsynchronously().then(function() {
|
||||
let stateString = SessionStore.getBrowserState();
|
||||
return SessionFile.gatherTelemetry(stateString);
|
||||
});
|
||||
},
|
||||
|
||||
/* ........ nsISessionStore API .............. */
|
||||
|
||||
getBrowserState: function ssi_getBrowserState() {
|
||||
|
@ -130,6 +130,16 @@ let Agent = {
|
||||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract all sorts of useful statistics from a state string,
|
||||
* for use with Telemetry.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
gatherTelemetry: function (stateString) {
|
||||
return Statistics.collect(stateString);
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes the session state to disk again but changes session.state to
|
||||
* 'running' before doing so. This is intended to be called only once, shortly
|
||||
@ -236,3 +246,144 @@ let Agent = {
|
||||
function isNoSuchFileEx(aReason) {
|
||||
return aReason instanceof OS.File.Error && aReason.becauseNoSuchFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimate the number of bytes that a data structure will use on disk
|
||||
* once serialized.
|
||||
*/
|
||||
function getByteLength(str) {
|
||||
return Encoder.encode(JSON.stringify(str)).byteLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tools for gathering statistics on a state string.
|
||||
*/
|
||||
let Statistics = {
|
||||
collect: function(stateString) {
|
||||
let start = Date.now();
|
||||
let TOTAL_PREFIX = "FX_SESSION_RESTORE_TOTAL_";
|
||||
let INDIVIDUAL_PREFIX = "FX_SESSION_RESTORE_INDIVIDUAL_";
|
||||
let SIZE_SUFFIX = "_SIZE_BYTES";
|
||||
|
||||
let state = JSON.parse(stateString);
|
||||
|
||||
// Gather all data
|
||||
let subsets = {};
|
||||
this.gatherSimpleData(state, subsets);
|
||||
this.gatherComplexData(state, subsets);
|
||||
|
||||
// Extract telemetry
|
||||
let telemetry = {};
|
||||
for (let k of Object.keys(subsets)) {
|
||||
let obj = subsets[k];
|
||||
telemetry[TOTAL_PREFIX + k + SIZE_SUFFIX] = getByteLength(obj);
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
let size = obj.map(getByteLength);
|
||||
telemetry[INDIVIDUAL_PREFIX + k + SIZE_SUFFIX] = size;
|
||||
}
|
||||
}
|
||||
|
||||
let stop = Date.now();
|
||||
telemetry["FX_SESSION_RESTORE_EXTRACTING_STATISTICS_DURATION_MS"] = stop - start;
|
||||
return {
|
||||
telemetry: telemetry
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Collect data that doesn't require a recursive walk through the
|
||||
* data structure.
|
||||
*/
|
||||
gatherSimpleData: function(state, subsets) {
|
||||
// The subset of sessionstore.js dealing with open windows
|
||||
subsets.OPEN_WINDOWS = state.windows;
|
||||
|
||||
// The subset of sessionstore.js dealing with closed windows
|
||||
subsets.CLOSED_WINDOWS = state._closedWindows;
|
||||
|
||||
// The subset of sessionstore.js dealing with closed tabs
|
||||
// in open windows
|
||||
subsets.CLOSED_TABS_IN_OPEN_WINDOWS = [];
|
||||
|
||||
// The subset of sessionstore.js dealing with cookies
|
||||
// in both open and closed windows
|
||||
subsets.COOKIES = [];
|
||||
|
||||
for (let winData of state.windows) {
|
||||
let closedTabs = winData._closedTabs || [];
|
||||
subsets.CLOSED_TABS_IN_OPEN_WINDOWS.push(...closedTabs);
|
||||
|
||||
let cookies = winData.cookies || [];
|
||||
subsets.COOKIES.push(...cookies);
|
||||
}
|
||||
|
||||
for (let winData of state._closedWindows) {
|
||||
let cookies = winData.cookies || [];
|
||||
subsets.COOKIES.push(...cookies);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Walk through a data structure, recursively.
|
||||
*
|
||||
* @param {object} root The object from which to start walking.
|
||||
* @param {function(key, value)} cb Callback, called for each
|
||||
* item except the root. Returns |true| to walk the subtree rooted
|
||||
* at |value|, |false| otherwise */
|
||||
walk: function(root, cb) {
|
||||
if (!root || typeof root !== "object") {
|
||||
return;
|
||||
}
|
||||
for (let k of Object.keys(root)) {
|
||||
let obj = root[k];
|
||||
let stepIn = cb(k, obj);
|
||||
if (stepIn) {
|
||||
this.walk(obj, cb);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Collect data that requires walking through the data structure
|
||||
*/
|
||||
gatherComplexData: function(state, subsets) {
|
||||
// The subset of sessionstore.js dealing with DOM storage
|
||||
subsets.DOM_STORAGE = [];
|
||||
// The subset of sessionstore.js storing form data
|
||||
subsets.FORMDATA = [];
|
||||
// The subset of sessionstore.js storing POST data in history
|
||||
subsets.POSTDATA = [];
|
||||
// The subset of sessionstore.js storing history
|
||||
subsets.HISTORY = [];
|
||||
|
||||
|
||||
this.walk(state, function(k, value) {
|
||||
let dest;
|
||||
switch (k) {
|
||||
case "entries":
|
||||
subsets.HISTORY.push(value);
|
||||
return true;
|
||||
case "storage":
|
||||
subsets.DOM_STORAGE.push(value);
|
||||
// Never visit storage, it's full of weird stuff
|
||||
return false;
|
||||
case "formdata":
|
||||
subsets.FORMDATA.push(value);
|
||||
// Never visit formdata, it's full of weird stuff
|
||||
return false;
|
||||
case "postdata_b64":
|
||||
subsets.POSTDATA.push(value);
|
||||
return false; // Nothing to visit anyway
|
||||
case "cookies": // Don't visit these places, they are full of weird stuff
|
||||
case "extData":
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return subsets;
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -70,6 +70,7 @@ support-files =
|
||||
[browser_sessionStorage.js]
|
||||
[browser_swapDocShells.js]
|
||||
[browser_tabStateCache.js]
|
||||
[browser_telemetry.js]
|
||||
[browser_upgrade_backup.js]
|
||||
[browser_windowRestore_perwindowpb.js]
|
||||
[browser_248970_b_perwindowpb.js]
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const INITIAL_VALUE = "initial-value-" + Date.now();
|
||||
const INITIAL_VALUE = "browser_broadcast.js-initial-value-" + Date.now();
|
||||
|
||||
/**
|
||||
* This test ensures we won't lose tab data queued in the content script when
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
let Imports = {};
|
||||
Cu.import("resource:///modules/sessionstore/SessionSaver.jsm", Imports);
|
||||
let {SessionSaver} = Imports;
|
||||
let {Task, SessionSaver} = Imports;
|
||||
|
||||
add_task(function cleanup() {
|
||||
info("Forgetting closed tabs");
|
||||
|
266
browser/components/sessionstore/test/browser_telemetry.js
Normal file
266
browser/components/sessionstore/test/browser_telemetry.js
Normal file
@ -0,0 +1,266 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/sessionstore/SessionFile.jsm", tmp);
|
||||
Cu.import("resource:///modules/sessionstore/TabStateCache.jsm", tmp);
|
||||
let {SessionFile, TabStateCache} = tmp;
|
||||
|
||||
// Shortcuts for histogram names
|
||||
let Keys = {};
|
||||
for (let k of ["HISTORY", "FORMDATA", "OPEN_WINDOWS", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS", "DOM_STORAGE", "POSTDATA"]) {
|
||||
Keys[k] = "FX_SESSION_RESTORE_TOTAL_" + k + "_SIZE_BYTES";
|
||||
}
|
||||
|
||||
function lt(a, b, message) {
|
||||
isnot(a, undefined, message + " (sanity check)");
|
||||
isnot(b, undefined, message + " (sanity check)");
|
||||
ok(a < b, message + " ( " + a + " < " + b + ")");
|
||||
}
|
||||
function gt(a, b, message) {
|
||||
isnot(a, undefined, message + " (sanity check)");
|
||||
isnot(b, undefined, message + " (sanity check)");
|
||||
ok(a > b, message + " ( " + a + " > " + b + ")");
|
||||
}
|
||||
|
||||
add_task(function init() {
|
||||
for (let i = ss.getClosedWindowCount() - 1; i >= 0; --i) {
|
||||
ss.forgetClosedWindow(i);
|
||||
}
|
||||
for (let i = ss.getClosedTabCount(window) - 1; i >= 0; --i) {
|
||||
ss.forgetClosedTab(window, i);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that Telemetry collection doesn't cause any error.
|
||||
*/
|
||||
add_task(function() {
|
||||
info("Checking a little bit of consistency");
|
||||
let statistics = yield promiseStats();
|
||||
|
||||
for (let k of Object.keys(statistics)) {
|
||||
let data = statistics[k];
|
||||
info("Data for " + k + ": " + data);
|
||||
if (Array.isArray(data)) {
|
||||
ok(data.every(x => x >= 0), "Data for " + k + " is >= 0");
|
||||
} else {
|
||||
ok(data >= 0, "Data for " + k + " is >= 0");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test HISTORY key.
|
||||
*/
|
||||
add_task(function history() {
|
||||
let KEY = Keys.HISTORY;
|
||||
let tab = gBrowser.addTab("http://example.org:80/?");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
try {
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
let statistics = yield promiseStats();
|
||||
|
||||
info("Now changing history");
|
||||
tab.linkedBrowser.contentWindow.history.pushState({foo:1}, "ref");
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
// We have changed history, so it must have increased
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of HISTORY has increased");
|
||||
|
||||
// Almost nothing else should
|
||||
for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
} finally {
|
||||
if (tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test CLOSED_TABS_IN_OPEN_WINDOWS key.
|
||||
*/
|
||||
add_task(function close_tab() {
|
||||
let KEY = Keys.CLOSED_TABS_IN_OPEN_WINDOWS;
|
||||
let tab = gBrowser.addTab("http://example.org:80/?close_tab");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
try {
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
let statistics = yield promiseStats();
|
||||
|
||||
info("Now closing a tab");
|
||||
gBrowser.removeTab(tab);
|
||||
tab = null;
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of CLOSED_TABS_IN_OPEN_WINDOWS has increased");
|
||||
|
||||
// Almost nothing else should change
|
||||
for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test OPEN_WINDOWS key.
|
||||
*/
|
||||
add_task(function open_window() {
|
||||
let KEY = Keys.OPEN_WINDOWS;
|
||||
let win;
|
||||
try {
|
||||
let statistics = yield promiseStats();
|
||||
win = yield promiseNewWindowLoaded("http://example.org:80/?open_window");
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of OPEN_WINDOWS has increased");
|
||||
|
||||
// Almost nothing else should change
|
||||
for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (win) {
|
||||
yield promiseWindowClosed(win);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test CLOSED_WINDOWS key.
|
||||
*/
|
||||
add_task(function close_window() {
|
||||
let KEY = Keys.CLOSED_WINDOWS;
|
||||
let win = yield promiseNewWindowLoaded("http://example.org:80/?close_window");
|
||||
|
||||
// We need to add something to the window, otherwise it won't be saved
|
||||
let tab = win.gBrowser.addTab("http://example.org:80/?close_tab");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
try {
|
||||
let statistics = yield promiseStats();
|
||||
yield promiseWindowClosed(win);
|
||||
win = null;
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of CLOSED_WINDOWS has increased");
|
||||
lt(statistics2[Keys.OPEN_WINDOWS], statistics[Keys.OPEN_WINDOWS], "The total size of OPEN_WINDOWS has decreased");
|
||||
|
||||
// Almost nothing else should change
|
||||
for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (win) {
|
||||
yield promiseWindowClosed(win);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Test DOM_STORAGE key.
|
||||
*/
|
||||
add_task(function dom_storage() {
|
||||
let KEY = Keys.DOM_STORAGE;
|
||||
let tab = gBrowser.addTab("http://example.org:80/?dom_storage");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
try {
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
let statistics = yield promiseStats();
|
||||
|
||||
info("Now adding some storage");
|
||||
yield modifySessionStorage(tab.linkedBrowser, {foo: "bar"});
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of DOM_STORAGE has increased");
|
||||
|
||||
// Almost nothing else should change
|
||||
for (let k of ["CLOSED_TABS_IN_OPEN_WINDOWS", "FORMDATA", "CLOSED_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test FORMDATA key.
|
||||
*/
|
||||
add_task(function formdata() {
|
||||
let KEY = Keys.FORMDATA;
|
||||
let tab = gBrowser.addTab("data:text/html;charset=utf-8,<input%20id='input'>");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
try {
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
let statistics = yield promiseStats();
|
||||
|
||||
info("Now changing form data");
|
||||
|
||||
yield modifyFormData(tab.linkedBrowser, {input: "This is some form data "});
|
||||
SyncHandlers.get(tab.linkedBrowser).flush();
|
||||
TabStateCache.delete(tab.linkedBrowser);
|
||||
|
||||
let statistics2 = yield promiseStats();
|
||||
|
||||
isnot(statistics[KEY], undefined, "Key was defined");
|
||||
isnot(statistics2[KEY], undefined, "Key is still defined");
|
||||
gt(statistics2[KEY], statistics[KEY], "The total size of FORMDATA has increased");
|
||||
|
||||
// Almost nothing else should
|
||||
for (let k of ["DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
|
||||
is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
|
||||
}
|
||||
} finally {
|
||||
if (tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Get the latest statistics.
|
||||
*/
|
||||
function promiseStats() {
|
||||
let state = ss.getBrowserState();
|
||||
info("Stats: " + state);
|
||||
return SessionFile.gatherTelemetry(state);
|
||||
}
|
||||
|
||||
|
||||
function modifySessionStorage(browser, data) {
|
||||
browser.messageManager.sendAsyncMessage("ss-test:modifySessionStorage", data);
|
||||
return promiseContentMessage(browser, "ss-test:MozStorageChanged");
|
||||
}
|
||||
|
||||
function modifyFormData(browser, data) {
|
||||
browser.messageManager.sendAsyncMessage("ss-test:modifyFormData", data);
|
||||
return promiseContentMessage(browser, "ss-test:modifyFormData:done");
|
||||
}
|
||||
|
@ -39,6 +39,13 @@ addMessageListener("ss-test:modifySessionStorage2", function (msg) {
|
||||
}
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:modifyFormData", function (msg) {
|
||||
for (let id of Object.keys(msg.data)) {
|
||||
content.document.getElementById(id).value = msg.data[id];
|
||||
}
|
||||
sendSyncMessage("ss-test:modifyFormData:done");
|
||||
});
|
||||
|
||||
addMessageListener("ss-test:purgeDomainData", function ({data: domain}) {
|
||||
Services.obs.notifyObservers(null, "browser:purge-domain-data", domain);
|
||||
content.setTimeout(() => sendAsyncMessage("ss-test:purgeDomainData"));
|
||||
|
@ -3351,6 +3351,126 @@
|
||||
"n_values": 101,
|
||||
"description": "Session restore: Number of times the tab state cache has been cleared during a session divided by number of total accesses during the session (percentage)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_EXTRACTING_STATISTICS_DURATION_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "3000",
|
||||
"n_buckets": 10,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Session restore: Duration of the off main thread statistics extraction mechanism (ms)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_OPEN_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Session restore: The subset of sessionrestore.js representing open windows (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_CLOSED_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Session restore: The subset of sessionrestore.js representing closed windows (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_CLOSED_TABS_IN_OPEN_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Sessionrestore: The subset of sesionstore.js representing closed tabs in open windows (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_COOKIES_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with cookies (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_DOM_STORAGE_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with DOM storage (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_FORMDATA_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing form data (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_HISTORY_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing history (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_TOTAL_POSTDATA_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing POST data (total size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_OPEN_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Session restore: The subset of sessionrestore.js representing open windows (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_CLOSED_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Session restore: The subset of sessionrestore.js representing closed windows (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_CLOSED_TABS_IN_OPEN_WINDOWS_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "Sessionrestore: The subset of sesionstore.js representing closed tabs in open windows (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_COOKIES_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "50000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with cookies (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_DOM_STORAGE_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with DOM storage (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_FORMDATA_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing form data (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_HISTORY_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing history (item size, in bytes)"
|
||||
},
|
||||
"FX_SESSION_RESTORE_INDIVIDUAL_POSTDATA_SIZE_BYTES": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "5000000",
|
||||
"n_buckets": 30,
|
||||
"description": "The subset of sessionstore.js dealing with storing history POST data (item size, in bytes)"
|
||||
},
|
||||
"INNERWINDOWS_WITH_MUTATION_LISTENERS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
|
Loading…
Reference in New Issue
Block a user