diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /services/settings/test/unit/test_remote_settings_utils.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'services/settings/test/unit/test_remote_settings_utils.js')
-rw-r--r-- | services/settings/test/unit/test_remote_settings_utils.js | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/services/settings/test/unit/test_remote_settings_utils.js b/services/settings/test/unit/test_remote_settings_utils.js new file mode 100644 index 0000000000..de372b3e44 --- /dev/null +++ b/services/settings/test/unit/test_remote_settings_utils.js @@ -0,0 +1,166 @@ +/* import-globals-from ../../../common/tests/unit/head_helpers.js */ + +const { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); +const { Utils } = ChromeUtils.importESModule( + "resource://services-settings/Utils.sys.mjs" +); + +const BinaryOutputStream = Components.Constructor( + "@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream" +); + +const server = new HttpServer(); +server.start(-1); +registerCleanupFunction(() => server.stop(() => {})); +const SERVER_BASE_URL = `http://localhost:${server.identity.primaryPort}`; + +const proxyServer = new HttpServer(); +proxyServer.identity.add("http", "localhost", server.identity.primaryPort); +proxyServer.start(-1); +registerCleanupFunction(() => proxyServer.stop(() => {})); +const PROXY_PORT = proxyServer.identity.primaryPort; + +// A sequence of bytes that would become garbage if it were to be read as UTF-8: +// - 0xEF 0xBB 0xBF is a byte order mark. +// - 0xC0 on its own is invalid (it's the first byte of a 2-byte encoding). +const INVALID_UTF_8_BYTES = [0xef, 0xbb, 0xbf, 0xc0]; + +server.registerPathHandler("/binary.dat", (request, response) => { + response.setStatusLine(null, 201, "StatusLineHere"); + response.setHeader("headerName", "HeaderValue: HeaderValueEnd"); + let binaryOut = new BinaryOutputStream(response.bodyOutputStream); + binaryOut.writeByteArray([0xef, 0xbb, 0xbf, 0xc0]); +}); + +// HTTPS requests are proxied with CONNECT, but our test server is HTTP, +// which means that the proxy will receive GET http://localhost:port. +var proxiedCount = 0; +proxyServer.registerPrefixHandler("/", (request, response) => { + ++proxiedCount; + Assert.equal(request.path, "/binary.dat", `Proxy request ${proxiedCount}`); + // Close connection without sending any response. + response.seizePower(); + response.finish(); +}); + +add_task(async function test_utils_fetch_binary() { + let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`); + + Assert.equal(res.status, 201, "res.status"); + Assert.equal(res.statusText, "StatusLineHere", "res.statusText"); + Assert.equal( + res.headers.get("headerName"), + "HeaderValue: HeaderValueEnd", + "Utils.fetch should return the header" + ); + + Assert.deepEqual( + Array.from(new Uint8Array(await res.arrayBuffer())), + INVALID_UTF_8_BYTES, + "Binary response body should be returned as is" + ); +}); + +add_task(async function test_utils_fetch_binary_as_text() { + let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`); + Assert.deepEqual( + Array.from(await res.text(), c => c.charCodeAt(0)), + [65533], + "Interpreted as UTF-8, the response becomes garbage" + ); +}); + +add_task(async function test_utils_fetch_binary_as_json() { + let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`); + await Assert.rejects( + res.json(), + /SyntaxError: JSON.parse: unexpected character/, + "Binary data is invalid JSON" + ); +}); + +add_task(async function test_utils_fetch_has_conservative() { + let channelPromise = TestUtils.topicObserved("http-on-modify-request"); + await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`); + + let channel = (await channelPromise)[0].QueryInterface(Ci.nsIHttpChannel); + + Assert.equal(channel.URI.spec, `${SERVER_BASE_URL}/binary.dat`, "URL OK"); + + let internalChannel = channel.QueryInterface(Ci.nsIHttpChannelInternal); + Assert.ok(internalChannel.beConservative, "beConservative flag is set"); +}); + +add_task(async function test_utils_fetch_has_conservative() { + let channelPromise = TestUtils.topicObserved("http-on-modify-request"); + await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`); + + let channel = (await channelPromise)[0].QueryInterface(Ci.nsIHttpChannel); + + Assert.equal(channel.URI.spec, `${SERVER_BASE_URL}/binary.dat`, "URL OK"); + + let internalChannel = channel.QueryInterface(Ci.nsIHttpChannelInternal); + Assert.ok(internalChannel.beConservative, "beConservative flag is set"); +}); + +add_task(async function test_utils_fetch_with_bad_proxy() { + Services.prefs.setIntPref("network.proxy.type", 1); + Services.prefs.setStringPref("network.proxy.http", "127.0.0.1"); + Services.prefs.setIntPref("network.proxy.http_port", PROXY_PORT); + Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); + + // The URL that we're going to request. + const DESTINATION_URL = `${SERVER_BASE_URL}/binary.dat`; + + Assert.equal(proxiedCount, 0, "Proxy not used yet"); + { + info("Bad proxy, default prefs"); + let res = await Utils.fetch(DESTINATION_URL); + Assert.equal(res.status, 201, "Bypassed bad proxy"); + // 10 instead of 1 because of reconnect attempts after a dropped request. + Assert.equal(proxiedCount, 10, "Proxy was used by HttpChannel"); + } + + // Disables the failover logic from HttpChannel. + Services.prefs.setBoolPref("network.proxy.failover_direct", false); + proxiedCount = 0; + { + info("Bad proxy, disabled network.proxy.failover_direct"); + let res = await Utils.fetch(DESTINATION_URL); + Assert.equal(res.status, 201, "Bypassed bad proxy"); + // 10 instead of 1 because of reconnect attempts after a dropped request. + Assert.equal(proxiedCount, 10, "Proxy was used by ServiceRequest"); + } + + proxiedCount = 0; + { + info("Using internal option of Utils.fetch: bypassProxy=true"); + let res = await Utils.fetch(DESTINATION_URL, { bypassProxy: true }); + Assert.equal(res.status, 201, "Bypassed bad proxy"); + Assert.equal(proxiedCount, 0, "Not using proxy when bypassProxy=true"); + } + + // Disables the failover logic from ServiceRequest/Utils.fetch + Services.prefs.setBoolPref("network.proxy.allow_bypass", false); + proxiedCount = 0; + + info("Bad proxy, disabled network.proxy.allow_bypass"); + await Assert.rejects( + Utils.fetch(DESTINATION_URL), + /NetworkError/, + "Bad proxy request should fail without failover" + ); + // 10 instead of 1 because of reconnect attempts after a dropped request. + Assert.equal(proxiedCount, 10, "Attempted to use proxy again"); + + Services.prefs.clearUserPref("network.proxy.type"); + Services.prefs.clearUserPref("network.proxy.http"); + Services.prefs.clearUserPref("network.proxy.http_port"); + Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); + Services.prefs.clearUserPref("network.proxy.failover_direct"); + Services.prefs.clearUserPref("network.proxy.allow_bypass"); +}); |