зеркало из https://github.com/mozilla/gecko-dev.git
320 строки
9.2 KiB
JavaScript
320 строки
9.2 KiB
JavaScript
"use strict";
|
|
|
|
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
|
|
trr_test_setup();
|
|
let httpServerIPv4 = new HttpServer();
|
|
let httpServerIPv6 = new HttpServer();
|
|
let trrServer;
|
|
let testpath = "/simple";
|
|
let httpbody = "0123456789";
|
|
let CC_IPV4 = "example_cc_ipv4.com";
|
|
let CC_IPV6 = "example_cc_ipv6.com";
|
|
Services.prefs.clearUserPref("network.dns.native-is-localhost");
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "URL_CC_IPV4", function() {
|
|
return `http://${CC_IPV4}:${httpServerIPv4.identity.primaryPort}${testpath}`;
|
|
});
|
|
XPCOMUtils.defineLazyGetter(this, "URL_CC_IPV6", function() {
|
|
return `http://${CC_IPV6}:${httpServerIPv6.identity.primaryPort}${testpath}`;
|
|
});
|
|
XPCOMUtils.defineLazyGetter(this, "URL6a", function() {
|
|
return `http://example6a.com:${httpServerIPv6.identity.primaryPort}${testpath}`;
|
|
});
|
|
XPCOMUtils.defineLazyGetter(this, "URL6b", function() {
|
|
return `http://example6b.com:${httpServerIPv6.identity.primaryPort}${testpath}`;
|
|
});
|
|
|
|
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
|
|
Ci.nsIDNSService
|
|
);
|
|
const ncs = Cc[
|
|
"@mozilla.org/network/network-connectivity-service;1"
|
|
].getService(Ci.nsINetworkConnectivityService);
|
|
const { TestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/TestUtils.sys.mjs"
|
|
);
|
|
|
|
registerCleanupFunction(async () => {
|
|
Services.prefs.clearUserPref("network.http.speculative-parallel-limit");
|
|
Services.prefs.clearUserPref("network.captive-portal-service.testMode");
|
|
Services.prefs.clearUserPref("network.connectivity-service.IPv6.url");
|
|
Services.prefs.clearUserPref("network.connectivity-service.IPv4.url");
|
|
Services.prefs.clearUserPref("network.dns.localDomains");
|
|
|
|
trr_clear_prefs();
|
|
await httpServerIPv4.stop();
|
|
await httpServerIPv6.stop();
|
|
await trrServer.stop();
|
|
});
|
|
|
|
function makeChan(url) {
|
|
let chan = NetUtil.newChannel({
|
|
uri: url,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
chan.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
|
chan.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
|
chan.setTRRMode(Ci.nsIRequest.TRR_DEFAULT_MODE);
|
|
return chan;
|
|
}
|
|
|
|
function serverHandler(metadata, response) {
|
|
response.setHeader("Content-Type", "text/plain", false);
|
|
response.bodyOutputStream.write(httpbody, httpbody.length);
|
|
}
|
|
|
|
add_task(async function test_setup() {
|
|
httpServerIPv4.registerPathHandler(testpath, serverHandler);
|
|
httpServerIPv4.start(-1);
|
|
httpServerIPv6.registerPathHandler(testpath, serverHandler);
|
|
httpServerIPv6.start_ipv6(-1);
|
|
Services.prefs.setCharPref(
|
|
"network.dns.localDomains",
|
|
`foo.example.com, ${CC_IPV4}, ${CC_IPV6}`
|
|
);
|
|
|
|
trrServer = new TRRServer();
|
|
await trrServer.start();
|
|
|
|
if (mozinfo.socketprocess_networking) {
|
|
await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched);
|
|
}
|
|
|
|
Services.prefs.setIntPref("network.trr.mode", 3);
|
|
Services.prefs.setCharPref(
|
|
"network.trr.uri",
|
|
`https://foo.example.com:${trrServer.port}/dns-query`
|
|
);
|
|
|
|
await registerDoHAnswers(true, true);
|
|
});
|
|
|
|
async function registerDoHAnswers(ipv4, ipv6) {
|
|
let hosts = ["example6a.com", "example6b.com"];
|
|
for (const host of hosts) {
|
|
let ipv4answers = [];
|
|
if (ipv4) {
|
|
ipv4answers = [
|
|
{
|
|
name: host,
|
|
ttl: 55,
|
|
type: "A",
|
|
flush: false,
|
|
data: "127.0.0.1",
|
|
},
|
|
];
|
|
}
|
|
await trrServer.registerDoHAnswers(host, "A", {
|
|
answers: ipv4answers,
|
|
});
|
|
|
|
let ipv6answers = [];
|
|
if (ipv6) {
|
|
ipv6answers = [
|
|
{
|
|
name: host,
|
|
ttl: 55,
|
|
type: "AAAA",
|
|
flush: false,
|
|
data: "::1",
|
|
},
|
|
];
|
|
}
|
|
|
|
await trrServer.registerDoHAnswers(host, "AAAA", {
|
|
answers: ipv6answers,
|
|
});
|
|
}
|
|
|
|
dns.clearCache(true);
|
|
}
|
|
|
|
let StatusCounter = function() {
|
|
this._statusCount = {};
|
|
};
|
|
StatusCounter.prototype = {
|
|
QueryInterface: ChromeUtils.generateQI([
|
|
"nsIInterfaceRequestor",
|
|
"nsIProgressEventSink",
|
|
]),
|
|
|
|
getInterface(iid) {
|
|
return this.QueryInterface(iid);
|
|
},
|
|
|
|
onProgress(request, progress, progressMax) {},
|
|
onStatus(request, status, statusArg) {
|
|
this._statusCount[status] = 1 + (this._statusCount[status] || 0);
|
|
},
|
|
};
|
|
|
|
let HttpListener = function(finish, succeeded) {
|
|
this.finish = finish;
|
|
this.succeeded = succeeded;
|
|
};
|
|
|
|
HttpListener.prototype = {
|
|
onStartRequest: function testOnStartRequest(request) {},
|
|
|
|
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
|
|
read_stream(stream, cnt);
|
|
},
|
|
|
|
onStopRequest: function testOnStopRequest(request, status) {
|
|
equal(this.succeeded, status == Cr.NS_OK);
|
|
this.finish();
|
|
},
|
|
};
|
|
|
|
function promiseObserverNotification(topic, matchFunc) {
|
|
return new Promise((resolve, reject) => {
|
|
Services.obs.addObserver(function observe(subject, topic, data) {
|
|
let matches = typeof matchFunc != "function" || matchFunc(subject, data);
|
|
if (!matches) {
|
|
return;
|
|
}
|
|
Services.obs.removeObserver(observe, topic);
|
|
resolve({ subject, data });
|
|
}, topic);
|
|
});
|
|
}
|
|
|
|
async function make_request(uri, check_events, succeeded) {
|
|
let chan = makeChan(uri);
|
|
let statusCounter = new StatusCounter();
|
|
chan.notificationCallbacks = statusCounter;
|
|
await new Promise(resolve =>
|
|
chan.asyncOpen(new HttpListener(resolve, succeeded))
|
|
);
|
|
|
|
if (check_events) {
|
|
equal(
|
|
statusCounter._statusCount[0x804b000b] || 0,
|
|
1,
|
|
"Expecting only one instance of NS_NET_STATUS_RESOLVED_HOST"
|
|
);
|
|
equal(
|
|
statusCounter._statusCount[0x804b0007] || 0,
|
|
1,
|
|
"Expecting only one instance of NS_NET_STATUS_CONNECTING_TO"
|
|
);
|
|
}
|
|
}
|
|
|
|
async function setup_connectivity(ipv6, ipv4) {
|
|
Services.prefs.setBoolPref("network.captive-portal-service.testMode", true);
|
|
|
|
if (ipv6) {
|
|
Services.prefs.setCharPref(
|
|
"network.connectivity-service.IPv6.url",
|
|
URL_CC_IPV6 + testpath
|
|
);
|
|
} else {
|
|
Services.prefs.setCharPref(
|
|
"network.connectivity-service.IPv6.url",
|
|
"http://donotexist.example.com"
|
|
);
|
|
}
|
|
|
|
if (ipv4) {
|
|
Services.prefs.setCharPref(
|
|
"network.connectivity-service.IPv4.url",
|
|
URL_CC_IPV4 + testpath
|
|
);
|
|
} else {
|
|
Services.prefs.setCharPref(
|
|
"network.connectivity-service.IPv4.url",
|
|
"http://donotexist.example.com"
|
|
);
|
|
}
|
|
|
|
let topic = "network:connectivity-service:ip-checks-complete";
|
|
if (mozinfo.socketprocess_networking) {
|
|
topic += "-from-socket-process";
|
|
}
|
|
let observerNotification = promiseObserverNotification(topic);
|
|
ncs.recheckIPConnectivity();
|
|
await observerNotification;
|
|
|
|
if (!ipv6) {
|
|
equal(
|
|
ncs.IPv6,
|
|
Ci.nsINetworkConnectivityService.NOT_AVAILABLE,
|
|
"Check IPv6 support"
|
|
);
|
|
} else {
|
|
equal(ncs.IPv6, Ci.nsINetworkConnectivityService.OK, "Check IPv6 support");
|
|
}
|
|
|
|
if (!ipv4) {
|
|
equal(
|
|
ncs.IPv4,
|
|
Ci.nsINetworkConnectivityService.NOT_AVAILABLE,
|
|
"Check IPv4 support"
|
|
);
|
|
} else {
|
|
equal(ncs.IPv4, Ci.nsINetworkConnectivityService.OK, "Check IPv4 support");
|
|
}
|
|
}
|
|
|
|
// This test that we retry to connect using IPv4 when IPv6 connecivity is not
|
|
// present, but a ConnectionEntry have IPv6 prefered set.
|
|
// Speculative connections are disabled.
|
|
add_task(async function test_prefer_address_version_fail_trr3_1() {
|
|
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
|
|
await registerDoHAnswers(true, true);
|
|
|
|
// Make a request to setup the address version preference to a ConnectionEntry.
|
|
await make_request(URL6a, true, true);
|
|
|
|
// connect again using the address version preference from the ConnectionEntry.
|
|
await make_request(URL6a, true, true);
|
|
|
|
// Make IPv6 connectivity check fail
|
|
await setup_connectivity(false, true);
|
|
|
|
dns.clearCache(true);
|
|
|
|
// This will succeed as we query both DNS records
|
|
await make_request(URL6a, true, true);
|
|
|
|
// Now make the DNS server only return IPv4 records
|
|
await registerDoHAnswers(true, false);
|
|
// This will fail, because the server is not lisenting to IPv4 address as well,
|
|
// We should still get NS_NET_STATUS_RESOLVED_HOST and
|
|
// NS_NET_STATUS_CONNECTING_TO notification.
|
|
await make_request(URL6a, true, false);
|
|
|
|
// Make IPv6 connectivity check succeed again
|
|
await setup_connectivity(true, true);
|
|
});
|
|
|
|
// This test that we retry to connect using IPv4 when IPv6 connecivity is not
|
|
// present, but a ConnectionEntry have IPv6 prefered set.
|
|
// Speculative connections are enabled.
|
|
add_task(async function test_prefer_address_version_fail_trr3_2() {
|
|
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 6);
|
|
await registerDoHAnswers(true, true);
|
|
|
|
// Make a request to setup the address version preference to a ConnectionEntry.
|
|
await make_request(URL6b, false, true);
|
|
|
|
// connect again using the address version preference from the ConnectionEntry.
|
|
await make_request(URL6b, false, true);
|
|
|
|
// Make IPv6 connectivity check fail
|
|
await setup_connectivity(false, true);
|
|
|
|
dns.clearCache(true);
|
|
|
|
// This will succeed as we query both DNS records
|
|
await make_request(URL6b, false, true);
|
|
|
|
// Now make the DNS server only return IPv4 records
|
|
await registerDoHAnswers(true, false);
|
|
// This will fail, because the server is not lisenting to IPv4 address as well,
|
|
// We should still get NS_NET_STATUS_RESOLVED_HOST and
|
|
// NS_NET_STATUS_CONNECTING_TO notification.
|
|
await make_request(URL6b, true, false);
|
|
});
|