Bug 1618849 - Add separate AltSvc for http2 and http3 and prefer http3 if allowed. r=necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D86934
This commit is contained in:
Dragana Damjanovic 2020-09-08 18:30:58 +00:00
Родитель 7c12fdbba9
Коммит 821dfeec6a
14 изменённых файлов: 282 добавлений и 60 удалений

Просмотреть файл

@ -165,7 +165,9 @@ void AltSvcMapping::ProcessHeader(
continue;
}
http3Found = true;
if (isHttp3) {
http3Found = true;
}
RefPtr<AltSvcMapping> mapping = new AltSvcMapping(
gHttpHandler->AltServiceCache()->GetStoragePtr(),
@ -255,7 +257,7 @@ AltSvcMapping::AltSvcMapping(
if (mExpiresAt) {
MakeHashKey(mHashKey, originScheme, mOriginHost, mOriginPort, mPrivate,
mIsolated, mTopWindowOrigin, mOriginAttributes);
mIsolated, mTopWindowOrigin, mOriginAttributes, mIsHttp3);
}
}
@ -265,7 +267,8 @@ void AltSvcMapping::MakeHashKey(nsCString& outKey,
int32_t originPort, bool privateBrowsing,
bool isolated,
const nsACString& topWindowOrigin,
const OriginAttributes& originAttributes) {
const OriginAttributes& originAttributes,
bool aHttp3) {
outKey.Truncate();
if (originPort == -1) {
@ -284,15 +287,16 @@ void AltSvcMapping::MakeHashKey(nsCString& outKey,
nsAutoCString suffix;
originAttributes.CreateSuffix(suffix);
outKey.Append(suffix);
outKey.Append(':');
if (isolated) {
outKey.Append(':');
outKey.Append('I');
outKey.Append(':');
outKey.Append(topWindowOrigin);
outKey.Append(
'|'); // Be careful, the top window origin may contain colons!
}
outKey.Append(aHttp3 ? '3' : '.');
}
int32_t AltSvcMapping::TTL() { return mExpiresAt - NowInSeconds(); }
@ -479,7 +483,7 @@ AltSvcMapping::AltSvcMapping(DataStorage* storage, int32_t epoch,
MakeHashKey(mHashKey, mHttps ? "https"_ns : "http"_ns, mOriginHost,
mOriginPort, mPrivate, mIsolated, mTopWindowOrigin,
mOriginAttributes);
mOriginAttributes, mIsHttp3);
} while (false);
}
@ -1132,7 +1136,8 @@ void AltSvcCache::UpdateAltServiceMapping(
already_AddRefed<AltSvcMapping> AltSvcCache::GetAltServiceMapping(
const nsACString& scheme, const nsACString& host, int32_t port,
bool privateBrowsing, bool isolated, const nsACString& topWindowOrigin,
const OriginAttributes& originAttributes, bool aHttp3Allowed) {
const OriginAttributes& originAttributes, bool aHttp2Allowed,
bool aHttp3Allowed) {
EnsureStorageInited();
bool isHTTPS;
@ -1146,24 +1151,39 @@ already_AddRefed<AltSvcMapping> AltSvcCache::GetAltServiceMapping(
return nullptr;
}
nsAutoCString key;
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
topWindowOrigin, originAttributes);
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
LOG(
("AltSvcCache::GetAltServiceMapping %p key=%s "
"existing=%p validated=%d ttl=%d",
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
existing ? existing->TTL() : 0));
if (existing && !existing->Validated()) {
existing = nullptr;
// First look for HTTP3
if (aHttp3Allowed) {
nsAutoCString key;
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
topWindowOrigin, originAttributes, true);
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
LOG(
("AltSvcCache::GetAltServiceMapping %p key=%s "
"existing=%p validated=%d ttl=%d",
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
existing ? existing->TTL() : 0));
if (existing && existing->Validated()) {
return existing.forget();
}
}
if (existing && existing->IsHttp3() && !aHttp3Allowed) {
existing = nullptr;
// Now look for HTTP2.
if (aHttp2Allowed) {
nsAutoCString key;
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, isolated,
topWindowOrigin, originAttributes, false);
RefPtr<AltSvcMapping> existing = LookupMapping(key, privateBrowsing);
LOG(
("AltSvcCache::GetAltServiceMapping %p key=%s "
"existing=%p validated=%d ttl=%d",
this, key.get(), existing.get(), existing ? existing->Validated() : 0,
existing ? existing->TTL() : 0));
if (existing && existing->Validated()) {
return existing.forget();
}
}
return existing.forget();
return nullptr;
}
class ProxyClearHostMapping : public Runnable {
@ -1213,11 +1233,18 @@ void AltSvcCache::ClearHostMapping(const nsACString& host, int32_t port,
for (int isolate = 0; isolate < 2; ++isolate) {
AltSvcMapping::MakeHashKey(key, scheme, host, port, bool(pb),
bool(isolate), topWindowOrigin,
originAttributes);
originAttributes, false);
RefPtr<AltSvcMapping> existing = LookupMapping(key, bool(pb));
if (existing) {
existing->SetExpired();
}
AltSvcMapping::MakeHashKey(key, scheme, host, port, bool(pb),
bool(isolate), topWindowOrigin,
originAttributes, true);
existing = LookupMapping(key, bool(pb));
if (existing) {
existing->SetExpired();
}
}
}
}

Просмотреть файл

@ -102,7 +102,7 @@ class AltSvcMapping {
const nsACString& originHost, int32_t originPort,
bool privateBrowsing, bool isolated,
const nsACString& topWindowOrigin,
const OriginAttributes& originAttributes);
const OriginAttributes& originAttributes, bool aIsHttp3);
bool IsHttp3() { return mIsHttp3; }
const nsCString& NPNToken() const { return mNPNToken; }
@ -198,7 +198,8 @@ class AltSvcCache {
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
bool isolated, const nsACString& topWindowOrigin,
const OriginAttributes& originAttributes, bool aHttp3Allowed);
const OriginAttributes& originAttributes, bool aHttp2Allowed,
bool aHttp3Allowed);
void ClearAltServiceMappings();
void ClearHostMapping(const nsACString& host, int32_t port,
const OriginAttributes& originAttributes,

Просмотреть файл

@ -3118,7 +3118,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
// Don't allow any more h2 connections to this host
RefPtr<nsHttpConnectionInfo> ci = ConnectionInfo();
if (ci) {
gHttpHandler->BlacklistSpdy(ci);
gHttpHandler->ExcludeHttp2(ci);
}
// Go through and re-start all of our transactions with h2 disabled.

Просмотреть файл

@ -241,8 +241,12 @@ nsresult HttpConnectionMgrParent::VerifyTraffic() {
return NS_OK;
}
void HttpConnectionMgrParent::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT_UNREACHABLE("BlacklistSpdy should not be called");
void HttpConnectionMgrParent::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT_UNREACHABLE("ExcludeHttp2 should not be called");
}
void HttpConnectionMgrParent::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT_UNREACHABLE("ExcludeHttp3 should not be called");
}
nsresult HttpConnectionMgrParent::ClearConnectionHistory() {

Просмотреть файл

@ -153,7 +153,8 @@ class HttpConnectionMgrShell : public nsISupports {
// that connection.
[[nodiscard]] virtual nsresult VerifyTraffic() = 0;
virtual void BlacklistSpdy(const nsHttpConnectionInfo* ci) = 0;
virtual void ExcludeHttp2(const nsHttpConnectionInfo* ci) = 0;
virtual void ExcludeHttp3(const nsHttpConnectionInfo* ci) = 0;
// clears the connection history mCT
[[nodiscard]] virtual nsresult ClearConnectionHistory() = 0;
@ -216,7 +217,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(HttpConnectionMgrShell,
nsHttpConnectionInfo*, nsIInterfaceRequestor*, uint32_t caps = 0, \
NullHttpTransaction* = nullptr) override; \
virtual nsresult VerifyTraffic() override; \
virtual void BlacklistSpdy(const nsHttpConnectionInfo* ci) override; \
virtual void ExcludeHttp2(const nsHttpConnectionInfo* ci) override; \
virtual void ExcludeHttp3(const nsHttpConnectionInfo* ci) override; \
virtual nsresult ClearConnectionHistory() override; \
virtual nsresult CompleteUpgrade(HttpTransactionShell* aTrans, \
nsIHttpUpgradeListener* aUpgradeListener) \

Просмотреть файл

@ -392,17 +392,21 @@ nsresult TRRServiceChannel::BeginConnect() {
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
OriginAttributes(), isHttps);
// TODO: Bug 1622778 for using AltService in socket process.
mAllowAltSvc = XRE_IsParentProcess() &&
(mAllowAltSvc && !gHttpHandler->IsSpdyBlacklisted(connInfo));
mAllowAltSvc = XRE_IsParentProcess() && mAllowAltSvc;
bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
!gHttpHandler->IsHttp3Excluded(connInfo);
RefPtr<AltSvcMapping> mapping;
if (!mConnectionInfo && mAllowAltSvc && // per channel
(http2Allowed || http3Allowed) &&
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
AltSvcMapping::AcceptableProxy(proxyInfo) &&
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
(mapping = gHttpHandler->GetAltServiceMapping(
scheme, host, port, mPrivateBrowsing, IsIsolated(),
GetTopWindowOrigin(), OriginAttributes(), false))) {
GetTopWindowOrigin(), OriginAttributes(), http2Allowed, http3Allowed))) {
LOG(("TRRServiceChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n",
this, scheme.get(), mapping->AlternateHost().get(),
mapping->AlternatePort(), mapping->HashKey().get()));
@ -438,7 +442,7 @@ nsresult TRRServiceChannel::BeginConnect() {
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
// we used earlier
if (gHttpHandler->IsSpdyBlacklisted(mConnectionInfo)) {
if (gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
mAllowSpdy = 0;
mCaps |= NS_HTTP_DISALLOW_SPDY;
mConnectionInfo->SetNoSpdy(true);

Просмотреть файл

@ -6895,9 +6895,10 @@ nsresult nsHttpChannel::BeginConnect() {
RefPtr<nsHttpConnectionInfo> connInfo = new nsHttpConnectionInfo(
host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
originAttributes, isHttps);
mAllowAltSvc = (mAllowAltSvc && !gHttpHandler->IsSpdyBlacklisted(connInfo));
bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
bool http3Allowed = !mUpgradeProtocolCallback && !mProxyInfo &&
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative;
!(mCaps & NS_HTTP_BE_CONSERVATIVE) && !mBeConservative &&
!gHttpHandler->IsHttp3Excluded(connInfo);
// No need to lookup HTTPSSVC record if we already have one.
mUseHTTPSSVC =
@ -6905,12 +6906,13 @@ nsresult nsHttpChannel::BeginConnect() {
RefPtr<AltSvcMapping> mapping;
if (!mConnectionInfo && mAllowAltSvc && // per channel
(http2Allowed || http3Allowed) &&
!(mLoadFlags & LOAD_FRESH_CONNECTION) &&
AltSvcMapping::AcceptableProxy(proxyInfo) &&
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
(mapping = gHttpHandler->GetAltServiceMapping(
scheme, host, port, mPrivateBrowsing, IsIsolated(),
GetTopWindowOrigin(), originAttributes, http3Allowed))) {
GetTopWindowOrigin(), originAttributes, http2Allowed, http3Allowed))) {
LOG(("nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n", this,
scheme.get(), mapping->AlternateHost().get(), mapping->AlternatePort(),
mapping->HashKey().get()));
@ -6966,7 +6968,7 @@ nsresult nsHttpChannel::BeginConnect() {
// Need to re-ask the handler, since mConnectionInfo may not be the connInfo
// we used earlier
if (gHttpHandler->IsSpdyBlacklisted(mConnectionInfo)) {
if (gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
mAllowSpdy = 0;
mCaps |= NS_HTTP_DISALLOW_SPDY;
mConnectionInfo->SetNoSpdy(true);

Просмотреть файл

@ -2060,7 +2060,7 @@ nsresult nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction* trans) {
trans->SetConnection(nullptr);
rv = DispatchTransaction(ent, trans, conn);
} else {
if (!ent->AllowSpdy()) {
if (!ent->AllowHttp2()) {
trans->DisableSpdy();
}
pendingTransInfo = new PendingTransactionInfo(trans);
@ -5263,7 +5263,7 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport* trans,
if (status == NS_NET_STATUS_CONNECTING_TO && gHttpHandler->IsSpdyEnabled() &&
gHttpHandler->CoalesceSpdy() && mEnt && mEnt->mConnInfo &&
mEnt->mConnInfo->EndToEndSSL() && mEnt->AllowSpdy() &&
mEnt->mConnInfo->EndToEndSSL() && mEnt->AllowHttp2() &&
!mEnt->mConnInfo->UsingProxy() && mEnt->mCoalescingKeys.IsEmpty()) {
nsCOMPtr<nsIDNSAddrRecord> dnsRecord(do_GetInterface(mSocketTransport));
nsTArray<NetAddr> addressSet;
@ -5544,19 +5544,31 @@ void nsHttpConnectionMgr::nsConnectionEntry::RemoveHalfOpen(
}
}
void nsHttpConnectionMgr::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
LOG(("nsHttpConnectionMgr::BlacklistSpdy blacklisting ci %s",
void nsHttpConnectionMgr::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
LOG(("nsHttpConnectionMgr::ExcludeHttp2 excluding ci %s",
ci->HashKey().BeginReading()));
nsConnectionEntry* ent = mCT.GetWeak(ci->HashKey());
if (!ent) {
LOG(("nsHttpConnectionMgr::BlacklistSpdy no entry found?!"));
LOG(("nsHttpConnectionMgr::ExcludeHttp2 no entry found?!"));
return;
}
ent->DisallowSpdy();
ent->DisallowHttp2();
}
void nsHttpConnectionMgr::nsConnectionEntry::DisallowSpdy() {
void nsHttpConnectionMgr::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
LOG(("nsHttpConnectionMgr::ExcludeHttp3 exclude ci %s",
ci->HashKey().BeginReading()));
nsConnectionEntry* ent = mCT.GetWeak(ci->HashKey());
if (!ent) {
LOG(("nsHttpConnectionMgr::ExcludeHttp3 no entry found?!"));
return;
}
ent->DontReuseHttp3Conn();
}
void nsHttpConnectionMgr::nsConnectionEntry::DisallowHttp2() {
mCanUseSpdy = false;
// If we have any spdy connections, we want to go ahead and close them when
@ -5576,6 +5588,19 @@ void nsHttpConnectionMgr::nsConnectionEntry::DisallowSpdy() {
mCoalescingKeys.Clear();
}
void nsHttpConnectionMgr::nsConnectionEntry::DontReuseHttp3Conn() {
MOZ_ASSERT(mConnInfo->IsHttp3());
// If we have any spdy connections, we want to go ahead and close them when
// they're done so we can free up some connections.
for (uint32_t i = 0; i < mActiveConns.Length(); ++i) {
mActiveConns[i]->DontReuse();
}
// Can't coalesce if we're not using http3
mCoalescingKeys.Clear();
}
void nsHttpConnectionMgr::nsConnectionEntry::RecordIPFamilyPreference(
uint16_t family) {
LOG(("nsConnectionEntry::RecordIPFamilyPreference %p, af=%u", this, family));

Просмотреть файл

@ -235,8 +235,9 @@ class nsHttpConnectionMgr final : public HttpConnectionMgrShell,
bool mDoNotDestroy : 1;
bool AllowSpdy() const { return mCanUseSpdy; }
void DisallowSpdy();
bool AllowHttp2() const { return mCanUseSpdy; }
void DisallowHttp2();
void DontReuseHttp3Conn();
// Set the IP family preference flags according the connected family
void RecordIPFamilyPreference(uint16_t family);

Просмотреть файл

@ -316,7 +316,7 @@ nsHttpHandler::nsHttpHandler()
mNextChannelId(1),
mLastActiveTabLoadOptimizationLock(
"nsHttpConnectionMgr::LastActiveTabLoadOptimization"),
mSpdyBlacklistLock("nsHttpHandler::SpdyBlacklist"),
mHttpExclusionLock("nsHttpHandler::HttpExclusion"),
mThroughCaptivePortal(false) {
LOG(("Creating nsHttpHandler [this=%p].\n", this));
@ -2796,19 +2796,34 @@ bool nsHttpHandler::IsBeforeLastActiveTabLoadOptimization(
when <= mLastActiveTabLoadOptimizationHit;
}
void nsHttpHandler::BlacklistSpdy(const nsHttpConnectionInfo* ci) {
void nsHttpHandler::ExcludeHttp2(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
mConnMgr->BlacklistSpdy(ci);
if (!mBlacklistedSpdyOrigins.Contains(ci->GetOrigin())) {
MutexAutoLock lock(mSpdyBlacklistLock);
mBlacklistedSpdyOrigins.PutEntry(ci->GetOrigin());
mConnMgr->ExcludeHttp2(ci);
if (!mExcludedHttp2Origins.Contains(ci->GetOrigin())) {
MutexAutoLock lock(mHttpExclusionLock);
mExcludedHttp2Origins.PutEntry(ci->GetOrigin());
}
}
bool nsHttpHandler::IsSpdyBlacklisted(const nsHttpConnectionInfo* ci) {
MutexAutoLock lock(mSpdyBlacklistLock);
return mBlacklistedSpdyOrigins.Contains(ci->GetOrigin());
bool nsHttpHandler::IsHttp2Excluded(const nsHttpConnectionInfo* ci) {
MutexAutoLock lock(mHttpExclusionLock);
return mExcludedHttp2Origins.Contains(ci->GetOrigin());
}
void nsHttpHandler::ExcludeHttp3(const nsHttpConnectionInfo* ci) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
mConnMgr->ExcludeHttp3(ci);
if (!mExcludedHttp3Origins.Contains(ci->GetOrigin())) {
MutexAutoLock lock(mHttpExclusionLock);
mExcludedHttp3Origins.PutEntry(ci->GetOrigin());
}
}
bool nsHttpHandler::IsHttp3Excluded(const nsHttpConnectionInfo* ci) {
MutexAutoLock lock(mHttpExclusionLock);
return mExcludedHttp3Origins.Contains(ci->GetOrigin());
}
HttpTrafficAnalyzer* nsHttpHandler::GetHttpTrafficAnalyzer() {

Просмотреть файл

@ -359,10 +359,11 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
already_AddRefed<AltSvcMapping> GetAltServiceMapping(
const nsACString& scheme, const nsACString& host, int32_t port, bool pb,
bool isolated, const nsACString& topWindowOrigin,
const OriginAttributes& originAttributes, bool aHttp3Allowed) {
const OriginAttributes& originAttributes, bool aHttp2Allowed,
bool aHttp3Allowed) {
return mAltSvcCache->GetAltServiceMapping(scheme, host, port, pb, isolated,
topWindowOrigin, originAttributes,
aHttp3Allowed);
aHttp2Allowed, aHttp3Allowed);
}
//
@ -833,7 +834,7 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
Mutex mLastActiveTabLoadOptimizationLock;
TimeStamp mLastActiveTabLoadOptimizationHit;
Mutex mSpdyBlacklistLock;
Mutex mHttpExclusionLock;
public:
[[nodiscard]] nsresult NewChannelId(uint64_t& channelId);
@ -841,11 +842,14 @@ class nsHttpHandler final : public nsIHttpProtocolHandler,
void RemoveHttpChannel(uint64_t aId);
nsWeakPtr GetWeakHttpChannel(uint64_t aId);
void BlacklistSpdy(const nsHttpConnectionInfo* ci);
[[nodiscard]] bool IsSpdyBlacklisted(const nsHttpConnectionInfo* ci);
void ExcludeHttp2(const nsHttpConnectionInfo* ci);
[[nodiscard]] bool IsHttp2Excluded(const nsHttpConnectionInfo* ci);
void ExcludeHttp3(const nsHttpConnectionInfo* ci);
[[nodiscard]] bool IsHttp3Excluded(const nsHttpConnectionInfo* ci);
private:
nsTHashtable<nsCStringHashKey> mBlacklistedSpdyOrigins;
nsTHashtable<nsCStringHashKey> mExcludedHttp2Origins;
nsTHashtable<nsCStringHashKey> mExcludedHttp3Origins;
bool mThroughCaptivePortal;

Просмотреть файл

@ -0,0 +1,125 @@
"use strict";
let httpsOrigin;
let h3AltSvc;
let h3Port;
let h3Route;
let prefs;
let tests = [test_https_alt_svc, testsDone];
let current_test = 0;
function run_next_test() {
if (current_test < tests.length) {
dump("starting test number " + current_test + "\n");
tests[current_test]();
current_test++;
}
}
function run_test() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
let h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
let h3Port = env.get("MOZHTTP3_PORT");
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
h3AltSvc = ":" + h3Port;
h3Route = "foo.example.com:" + h3Port;
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.http3.enabled", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com");
// The certificate for the http3server server is for foo.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");
httpsOrigin = "https://foo.example.com:" + h2Port + "/";
run_next_test();
}
function makeChan(uri) {
let chan = NetUtil.newChannel({
uri,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
return chan;
}
let WaitForHttp3Listener = function() {};
WaitForHttp3Listener.prototype = {
onDataAvailableFired: false,
expectedRoute: "",
onStartRequest: function testOnStartRequest(request) {
Assert.ok(request instanceof Ci.nsIHttpChannel);
Assert.equal(request.responseStatus, 200);
},
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
this.onDataAvailableFired = true;
read_stream(stream, cnt);
},
onStopRequest: function testOnStopRequest(request, status) {
let routed = "NA";
try {
routed = request.getRequestHeader("Alt-Used");
} catch (e) {}
dump("routed is " + routed + "\n");
if (routed == this.expectedRoute) {
let httpVersion = "";
try {
httpVersion = request.protocolVersion;
} catch (e) {}
Assert.equal(httpVersion, "h3");
run_next_test();
} else {
dump("poll later for alt svc mapping\n");
do_test_pending();
do_timeout(500, () => {
doTest(this.uri, this.expectedRoute, this.h3AltSvc);
});
}
do_test_finished();
},
};
function doTest(uri, expectedRoute, altSvc) {
let chan = makeChan(uri);
let listener = new WaitForHttp3Listener();
listener.uri = uri;
listener.expectedRoute = expectedRoute;
listener.h3AltSvc = altSvc;
chan.setRequestHeader("x-altsvc", altSvc, false);
chan.asyncOpen(listener);
}
// Test Alt-Svc for http3.
// H2 server returns alt-svc=h2=foo2.example.com:8000,h3-27=:h3port,h3-29=foo2.example.com:8443
function test_https_alt_svc() {
dump("test_https_alt_svc()\n");
do_test_pending();
doTest(httpsOrigin + "http3-test2", h3Route, h3AltSvc);
}
function testsDone() {
prefs.clearUserPref("network.http.http3.enabled");
prefs.clearUserPref("network.dns.localDomains");
dump("testDone\n");
}

Просмотреть файл

@ -447,5 +447,7 @@ skip-if = os == "android"
[test_blob_channelname.js]
[test_altsvc_pref.js]
skip-if = asan || tsan || os == 'win' || os =='android'
[test_http3_alt_svc.js]
skip-if = asan || tsan || os == 'win' || os =='android'
[test_use_httpssvc.js]
skip-if = os == "android"

Просмотреть файл

@ -553,6 +553,16 @@ function handleRequest(req, res) {
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Alt-Svc", "h3-27=" + req.headers["x-altsvc"]);
}
// for use with test_http3.js
else if (u.pathname === "/http3-test2") {
res.setHeader("Cache-Control", "no-cache");
res.setHeader(
"Alt-Svc",
"h2=foo2.example.com:8000,h3-27=" +
req.headers["x-altsvc"] +
",h3-29=foo2.example.com:8443"
);
}
// for use with test_trr.js
else if (u.pathname === "/dns-cname") {
// asking for cname.example.com