Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* 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/. */
"use strict";
const { MockRegistrar } = ChromeUtils.importESModule(
);
const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(
Ci.nsIProtocolProxyService
);
const prefs = Services.prefs;
function resolveProxy(uri = "http://www.example.com/") {
const channel = NetUtil.newChannel({ uri, loadUsingSystemPrincipal: true });
return new Promise(resolve => {
pps.asyncResolve(channel, 0, {
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyCallback"]),
onProxyAvailable(_req, _channel, pi) {
resolve(pi);
},
});
});
}
add_setup(function () {
const originalProxyType = prefs.getIntPref("network.proxy.type");
registerCleanupFunction(() => {
prefs.setIntPref("network.proxy.type", originalProxyType);
prefs.clearUserPref("network.proxy.fast_path_system_direct");
});
});
// With PROXYCONFIG_DIRECT (type=0), proxy resolution should return null.
add_task(async function test_direct_no_proxy() {
prefs.setIntPref("network.proxy.type", 0);
const pi = await resolveProxy();
Assert.equal(
pi,
null,
"PROXYCONFIG_DIRECT should resolve to null proxy info"
);
});
// With fast_path_system_direct disabled, DIRECT should still resolve to null.
add_task(async function test_direct_fast_path_disabled() {
prefs.setIntPref("network.proxy.type", 0);
prefs.setBoolPref("network.proxy.fast_path_system_direct", false);
const pi = await resolveProxy();
Assert.equal(
pi,
null,
"PROXYCONFIG_DIRECT with fast-path disabled should still return null"
);
});
// With a registered proxy filter and type=0, the filter must still be invoked.
// (IsEffectivelyDirect returns false when filters are registered.)
add_task(async function test_direct_with_filter_respected() {
prefs.setIntPref("network.proxy.type", 0);
let filterCalled = false;
const filter = {
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyFilter"]),
applyFilter(_channel, defaultProxy, callback) {
filterCalled = true;
// Return the default (null for DIRECT).
callback.onProxyFilterResult(defaultProxy);
},
};
pps.registerFilter(filter, 0);
try {
const pi = await resolveProxy();
Assert.ok(
filterCalled,
"Proxy filter must be called even when proxy type is DIRECT"
);
Assert.equal(pi, null, "Filter returning default should still yield null");
} finally {
pps.unregisterFilter(filter);
}
});
// A filter that overrides to a real proxy must be respected (not fast-pathed).
add_task(async function test_direct_filter_can_override() {
prefs.setIntPref("network.proxy.type", 0);
const filter = {
QueryInterface: ChromeUtils.generateQI(["nsIProtocolProxyFilter"]),
applyFilter(_channel, _defaultProxy, callback) {
callback.onProxyFilterResult(
pps.newProxyInfo(
"http",
"myproxy.example.com",
8080,
"",
"",
0,
0xffffffff,
null
)
);
},
};
pps.registerFilter(filter, 0);
try {
const pi = await resolveProxy();
Assert.ok(pi, "Filter-provided proxy info should not be null");
Assert.equal(pi.type, "http");
Assert.equal(pi.host, "myproxy.example.com");
Assert.equal(pi.port, 8080);
} finally {
pps.unregisterFilter(filter);
}
});
// Registers a mock nsISystemProxySettings, sets PROXYCONFIG_SYSTEM, and runs
// the callback. Cleans up on completion.
async function withMockSystemProxy({ systemProxyDirect, proxyResult }, fn) {
const mockSettings = {
QueryInterface: ChromeUtils.generateQI(["nsISystemProxySettings"]),
mainThreadOnly: true,
PACURI: null,
systemWPADSetting: false,
systemProxyDirect,
getProxyForURI() {
return proxyResult;
},
};
const cid = MockRegistrar.register(
"@mozilla.org/system-proxy-settings;1",
mockSettings
);
const savedProxyType = prefs.getIntPref("network.proxy.type");
prefs.setIntPref(
"network.proxy.type",
Ci.nsIProtocolProxyService.PROXYCONFIG_SYSTEM
);
pps.notifyProxyConfigChangedInternal();
try {
await fn();
} finally {
MockRegistrar.unregister(cid);
prefs.setIntPref("network.proxy.type", savedProxyType);
pps.notifyProxyConfigChangedInternal();
}
}
// With PROXYCONFIG_SYSTEM and a mock that reports systemProxyDirect=true,
// proxy resolution should return null (fast-path taken via Resolve_Internal).
add_task(async function test_system_proxy_direct() {
await withMockSystemProxy(
{ systemProxyDirect: true, proxyResult: "DIRECT" },
async () => {
const pi = await resolveProxy();
Assert.equal(
pi,
null,
"PROXYCONFIG_SYSTEM with systemProxyDirect=true should resolve to null"
);
}
);
});
// With PROXYCONFIG_SYSTEM and a mock that reports systemProxyDirect=false,
// getProxyForURI is called and its result is used.
add_task(async function test_system_proxy_not_direct() {
await withMockSystemProxy(
{ systemProxyDirect: false, proxyResult: "PROXY proxy.example.com:8080" },
async () => {
const pi = await resolveProxy();
Assert.ok(
pi,
"PROXYCONFIG_SYSTEM with a configured proxy should not be null"
);
Assert.equal(pi.host, "proxy.example.com");
Assert.equal(pi.port, 8080);
}
);
});