mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
f22ef05113
HTTP/2 Push was involved in several web-compat issues recently. See bug 1915830 for known H2-push bugs. As such it's best to turn off the feature and align with Chrome in order to avoid future push bugs only affecting Firefox. Differential Revision: https://phabricator.services.mozilla.com/D220699
321 lines
8.1 KiB
JavaScript
321 lines
8.1 KiB
JavaScript
"use strict";
|
|
|
|
var h2Port;
|
|
var prefs;
|
|
var http2pref;
|
|
var loadGroup;
|
|
|
|
function run_test() {
|
|
h2Port = Services.env.get("MOZHTTP2_PORT");
|
|
Assert.notEqual(h2Port, null);
|
|
Assert.notEqual(h2Port, "");
|
|
|
|
// Set to allow the cert presented by our H2 server
|
|
do_get_profile();
|
|
prefs = Services.prefs;
|
|
|
|
http2pref = prefs.getBoolPref("network.http.http2.enabled");
|
|
Services.prefs.setBoolPref("network.http.http2.allow-push", true);
|
|
|
|
prefs.setBoolPref("network.http.http2.enabled", true);
|
|
prefs.setCharPref(
|
|
"network.dns.localDomains",
|
|
"foo.example.com, alt1.example.com"
|
|
);
|
|
|
|
// The moz-http2 cert is for {foo, alt1, alt2}.example.com and is signed by http2-ca.pem
|
|
// so add that cert to the trust list as a signing cert.
|
|
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
|
Ci.nsIX509CertDB
|
|
);
|
|
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
|
|
|
|
doTest1();
|
|
}
|
|
|
|
function resetPrefs() {
|
|
prefs.setBoolPref("network.http.http2.enabled", http2pref);
|
|
prefs.clearUserPref("network.dns.localDomains");
|
|
}
|
|
|
|
function makeChan(origin) {
|
|
return NetUtil.newChannel({
|
|
uri: origin,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
}
|
|
|
|
let origin;
|
|
var nextTest;
|
|
var nextPortExpectedToBeSame = false;
|
|
var currentPort = 0;
|
|
var forceReload = false;
|
|
var forceFailListener = false;
|
|
|
|
var Listener = function () {};
|
|
Listener.prototype.clientPort = 0;
|
|
Listener.prototype = {
|
|
onStartRequest: function testOnStartRequest(request) {
|
|
Assert.ok(request instanceof Ci.nsIHttpChannel);
|
|
|
|
if (!Components.isSuccessCode(request.status)) {
|
|
do_throw("Channel should have a success code! (" + request.status + ")");
|
|
}
|
|
Assert.equal(request.responseStatus, 200);
|
|
this.clientPort = parseInt(request.getResponseHeader("x-client-port"));
|
|
},
|
|
|
|
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
|
|
read_stream(stream, cnt);
|
|
},
|
|
|
|
onStopRequest: function testOnStopRequest(request, status) {
|
|
Assert.ok(Components.isSuccessCode(status));
|
|
if (nextPortExpectedToBeSame) {
|
|
Assert.equal(currentPort, this.clientPort);
|
|
} else {
|
|
Assert.notEqual(currentPort, this.clientPort);
|
|
}
|
|
currentPort = this.clientPort;
|
|
nextTest();
|
|
do_test_finished();
|
|
},
|
|
};
|
|
|
|
var FailListener = function () {};
|
|
FailListener.prototype = {
|
|
onStartRequest: function testOnStartRequest(request) {
|
|
Assert.ok(request instanceof Ci.nsIHttpChannel);
|
|
Assert.ok(!Components.isSuccessCode(request.status));
|
|
},
|
|
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
|
|
read_stream(stream, cnt);
|
|
},
|
|
onStopRequest: function testOnStopRequest(request) {
|
|
Assert.ok(!Components.isSuccessCode(request.status));
|
|
nextTest();
|
|
do_test_finished();
|
|
},
|
|
};
|
|
|
|
function testsDone() {
|
|
dump("testsDone\n");
|
|
resetPrefs();
|
|
}
|
|
|
|
function doTest() {
|
|
dump("execute doTest " + origin + "\n");
|
|
var chan = makeChan(origin);
|
|
var listener;
|
|
if (!forceFailListener) {
|
|
listener = new Listener();
|
|
} else {
|
|
listener = new FailListener();
|
|
}
|
|
forceFailListener = false;
|
|
|
|
if (!forceReload) {
|
|
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
} else {
|
|
chan.loadFlags =
|
|
Ci.nsIRequest.LOAD_FRESH_CONNECTION |
|
|
Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
}
|
|
forceReload = false;
|
|
chan.asyncOpen(listener);
|
|
}
|
|
|
|
function doTest1() {
|
|
dump("doTest1()\n");
|
|
origin = "https://foo.example.com:" + h2Port + "/origin-1";
|
|
nextTest = doTest2;
|
|
nextPortExpectedToBeSame = false;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest2() {
|
|
// plain connection reuse
|
|
dump("doTest2()\n");
|
|
origin = "https://foo.example.com:" + h2Port + "/origin-2";
|
|
nextTest = doTest3;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest3() {
|
|
// 7540 style coalescing
|
|
dump("doTest3()\n");
|
|
origin = "https://alt1.example.com:" + h2Port + "/origin-3";
|
|
nextTest = doTest4;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest4() {
|
|
// forces an empty origin frame to be omitted
|
|
dump("doTest4()\n");
|
|
origin = "https://foo.example.com:" + h2Port + "/origin-4";
|
|
nextTest = doTest5;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest5() {
|
|
// 7540 style coalescing should not work due to empty origin set
|
|
dump("doTest5()\n");
|
|
origin = "https://alt1.example.com:" + h2Port + "/origin-5";
|
|
nextTest = doTest6;
|
|
nextPortExpectedToBeSame = false;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest6() {
|
|
// get a fresh connection with alt1 and alt2 in origin set
|
|
// note that there is no dns for alt2
|
|
dump("doTest6()\n");
|
|
origin = "https://foo.example.com:" + h2Port + "/origin-6";
|
|
nextTest = doTest7;
|
|
nextPortExpectedToBeSame = false;
|
|
forceReload = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest7() {
|
|
// check conn reuse to ensure sni is implicit in origin set
|
|
dump("doTest7()\n");
|
|
origin = "https://foo.example.com:" + h2Port + "/origin-7";
|
|
nextTest = doTest8;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest8() {
|
|
// alt1 is in origin set (and is 7540 eligible)
|
|
dump("doTest8()\n");
|
|
origin = "https://alt1.example.com:" + h2Port + "/origin-8";
|
|
nextTest = doTest9;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest9() {
|
|
// alt2 is in origin set but does not have dns
|
|
dump("doTest9()\n");
|
|
origin = "https://alt2.example.com:" + h2Port + "/origin-9";
|
|
nextTest = doTest10;
|
|
nextPortExpectedToBeSame = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
function doTest10() {
|
|
// bar is in origin set but does not have dns like alt2
|
|
// but the cert is not valid for bar. so expect a failure
|
|
dump("doTest10()\n");
|
|
origin = "https://bar.example.com:" + h2Port + "/origin-10";
|
|
nextTest = doTest11;
|
|
nextPortExpectedToBeSame = false;
|
|
forceFailListener = true;
|
|
do_test_pending();
|
|
doTest();
|
|
}
|
|
|
|
var Http2PushApiListener = function () {};
|
|
|
|
Http2PushApiListener.prototype = {
|
|
fooOK: false,
|
|
alt1OK: false,
|
|
|
|
getInterface(aIID) {
|
|
return this.QueryInterface(aIID);
|
|
},
|
|
|
|
QueryInterface: ChromeUtils.generateQI([
|
|
"nsIHttpPushListener",
|
|
"nsIStreamListener",
|
|
]),
|
|
|
|
// nsIHttpPushListener
|
|
onPush: function onPush(associatedChannel, pushChannel) {
|
|
dump(
|
|
"push api onpush " +
|
|
pushChannel.originalURI.spec +
|
|
" associated to " +
|
|
associatedChannel.originalURI.spec +
|
|
"\n"
|
|
);
|
|
|
|
Assert.equal(
|
|
associatedChannel.originalURI.spec,
|
|
"https://foo.example.com:" + h2Port + "/origin-11-a"
|
|
);
|
|
Assert.equal(pushChannel.getRequestHeader("x-pushed-request"), "true");
|
|
|
|
if (
|
|
pushChannel.originalURI.spec ===
|
|
"https://foo.example.com:" + h2Port + "/origin-11-b"
|
|
) {
|
|
this.fooOK = true;
|
|
} else if (
|
|
pushChannel.originalURI.spec ===
|
|
"https://alt1.example.com:" + h2Port + "/origin-11-e"
|
|
) {
|
|
this.alt1OK = true;
|
|
} else {
|
|
// any push of bar or madeup should not end up in onPush()
|
|
Assert.equal(true, false);
|
|
}
|
|
pushChannel.cancel(Cr.NS_ERROR_ABORT);
|
|
},
|
|
|
|
// normal Channel listeners
|
|
onStartRequest: function pushAPIOnStart(request) {
|
|
dump("push api onstart " + request.originalURI.spec + "\n");
|
|
},
|
|
|
|
onDataAvailable: function pushAPIOnDataAvailable(
|
|
request,
|
|
stream,
|
|
offset,
|
|
cnt
|
|
) {
|
|
read_stream(stream, cnt);
|
|
},
|
|
|
|
onStopRequest: function test_onStopR(request) {
|
|
dump("push api onstop " + request.originalURI.spec + "\n");
|
|
Assert.ok(this.fooOK);
|
|
Assert.ok(this.alt1OK);
|
|
nextTest();
|
|
do_test_finished();
|
|
},
|
|
};
|
|
|
|
function doTest11() {
|
|
// we are connected with an SNI of foo from test6
|
|
// but the origin set is alt1, alt2, bar - foo is implied
|
|
// and bar is not actually covered by the cert
|
|
//
|
|
// the server will push foo (b-OK), bar (c-NOT OK), madeup (d-NOT OK), alt1 (e-OK),
|
|
|
|
dump("doTest11()\n");
|
|
do_test_pending();
|
|
loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(
|
|
Ci.nsILoadGroup
|
|
);
|
|
var chan = makeChan("https://foo.example.com:" + h2Port + "/origin-11-a");
|
|
chan.loadGroup = loadGroup;
|
|
var listener = new Http2PushApiListener();
|
|
nextTest = testsDone;
|
|
chan.notificationCallbacks = listener;
|
|
chan.asyncOpen(listener);
|
|
}
|