From d555b51fa2b1ac545aaf55695f25dc04b1f56119 Mon Sep 17 00:00:00 2001 From: Andrew Creskey Date: Wed, 19 Jul 2023 13:12:16 +0000 Subject: [PATCH] Bug 1843606 - Add test api that can make use of the dev tools network throttler r=necko-reviewers,jdescottes,kershaw To create network tests that capture various codepaths and optimizations we need to fix network particulars such as latency and bandwidth. This module provides access to the dev tools throttler for use in browsertime pageload tests. Differential Revision: https://phabricator.services.mozilla.com/D183618 --- netwerk/test/moz.build | 4 + .../test/perf/NetworkThrottlingUtils.sys.mjs | 106 ++++++++++++++++++ tools/esmify/map.json | 1 + 3 files changed, 111 insertions(+) create mode 100644 netwerk/test/perf/NetworkThrottlingUtils.sys.mjs diff --git a/netwerk/test/moz.build b/netwerk/test/moz.build index 07895c8f436d..a74f38356d97 100644 --- a/netwerk/test/moz.build +++ b/netwerk/test/moz.build @@ -18,6 +18,10 @@ XPCSHELL_TESTS_MANIFESTS += [ "unit_ipc/xpcshell.ini", ] +EXTRA_JS_MODULES["netwerk-perf"] += [ + "perf/NetworkThrottlingUtils.sys.mjs", +] + TESTING_JS_MODULES += [ "browser/cookie_filtering_helper.sys.mjs", "browser/early_hint_preload_test_helper.sys.mjs", diff --git a/netwerk/test/perf/NetworkThrottlingUtils.sys.mjs b/netwerk/test/perf/NetworkThrottlingUtils.sys.mjs new file mode 100644 index 000000000000..1385b263db7b --- /dev/null +++ b/netwerk/test/perf/NetworkThrottlingUtils.sys.mjs @@ -0,0 +1,106 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + NetworkObserver: + "resource://devtools/shared/network-observer/NetworkObserver.sys.mjs", +}); + +/** + * The NetworkThrottler uses the dev tools NetworkObserver to provide api to throttle all network activity. + * + * This can be used to fix network conditions in browsertime pageload tests, e.g. + * + * const script = ` + * var {NetworkThrottler} = ChromeUtils.importESModule("resource://gre/modules/netwerk-perf/NetworkThrottlingUtils.sys.mjs"); + * + * let networkThrottler = new NetworkThrottler(); + * + * let throttleData = { + * latencyMean: 200, + * latencyMax: 200, + * downloadBPSMean: 125000, + * downloadBPSMax: 125000, + * uploadBPSMean: 125000, + * uploadBPSMax: 125000 + * }; + * networkThrottler.start(throttleData); + * + * ... run throttled tests ... + * + * networkThrottler.stop(); + * `; + * commands.js.runPrivileged(script); + * + */ + +// A minimal struct for onNetworkEvent handling +class NetworkEventRecord { + addRequestPostData() {} + addResponseStart() {} + addSecurityInfo() {} + addEventTimings() {} + addResponseCache() {} + addResponseContent() {} + addServerTimings() {} +} + +export class NetworkThrottler { + #devtoolsNetworkObserver; + #throttling; + + constructor() { + this.#throttling = false; + } + + destroy() { + this.stop(); + } + + start(throttleData) { + if (this.#throttling) { + console.error("NetworkThrottler already started"); + return; + } + + this.#devtoolsNetworkObserver = new lazy.NetworkObserver({ + ignoreChannelFunction: this.#ignoreChannelFunction, + onNetworkEvent: this.#onNetworkEvent, + }); + + this.#devtoolsNetworkObserver.setThrottleData(throttleData); + + this.#throttling = true; + } + + stop() { + if (!this.#throttling) { + return; + } + + this.#devtoolsNetworkObserver.destroy(); + this.#devtoolsNetworkObserver = null; + + this.#throttling = false; + } + + #ignoreChannelFunction = channel => { + // Ignore chrome-privileged or DevTools-initiated requests + if ( + channel.loadInfo?.loadingDocument === null && + (channel.loadInfo.loadingPrincipal === + Services.scriptSecurityManager.getSystemPrincipal() || + channel.loadInfo.isInDevToolsContext) + ) { + return true; + } + return false; + }; + + #onNetworkEvent = (networkEvent, channel) => { + return new NetworkEventRecord(networkEvent, channel, this); + }; +} diff --git a/tools/esmify/map.json b/tools/esmify/map.json index dd260e4317f2..0a6ad4bc4fce 100644 --- a/tools/esmify/map.json +++ b/tools/esmify/map.json @@ -852,6 +852,7 @@ "resource://gre/modules/narrate/Narrator.jsm": "toolkit/components/narrate/Narrator.jsm", "resource://gre/modules/narrate/VoiceSelect.jsm": "toolkit/components/narrate/VoiceSelect.jsm", "resource://gre/modules/netwerk-dns/PublicSuffixList.jsm": "netwerk/dns/PublicSuffixList.jsm", + "resource://gre/modules/netwerk-perf/NetworkThrottlingUtils.jsm": "netwerk/test/perf/NetworkThrottlingUtils.jsm", "resource://gre/modules/nsAsyncShutdown.jsm": "toolkit/components/asyncshutdown/nsAsyncShutdown.jsm", "resource://gre/modules/nsCrashMonitor.jsm": "toolkit/components/crashmonitor/nsCrashMonitor.jsm", "resource://gre/modules/nsFormAutoCompleteResult.jsm": "toolkit/components/satchel/nsFormAutoCompleteResult.jsm",