Files
palemoon27/netwerk/protocol/http/AlternateServices.cpp
T
roytam1 8a0a002cf2 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1148708: Add missing 'override' annotations in DocAccessibleChild.h. rs=ehsan (d606358545)
- Bug 1210408 - make nsMaiInterfaceAction work with proxies, r=tbsaunde (f7c819c6ae)
- Bug 1210407 - teach nsMaiInterfaceTable to use proxies, r=tbsaunde (4ca4f10b5f)
- bug 1185157 make sure we don't send an event to a destroyed ipc document r=billm (23acf53f75)
- bug 1214864 - make SetCarretOffset() async r=davidb (e3079e9b2d)
- missing of Bug 1139972 - IPC Proxy for charAt, r=tbsaunde (e9593ed752)
- bug 1191598 - Pass MOZ_CURRENT_PROJECT in environment when running post-build automation steps for universal mac builds. r=gps (fc342c6ced)
- Bug 1164596 - Add mach android-emulator command; r=ahal (afeb9b27d1)
- Bug 1223149 - Add basic usage documentation for mach build; r=glandium (bfb802d175)
- Bug 1182301 - Improve 'mach build' notifications. r=gps (2c65a122d1)
- Bug 1184696 - Add clobber targets to |mach clobber|; Ability to clobber compiled python files, r=gps (35d8be292e)
- Bug 1117958 - Allow any debugging options to the run or gtest mach subcommands to automatically enable debugging. r=gps (32f986af4b)
- Bug 1180081 - Properly rebuild gtest/libxul before running gtests. r=gps (80db9a3d49)
- Bug 1171647, part 1 - Define a new function to convert the mode to a string. r=njn (61ad16f5ba)
- Bug 1171647, part 2 - Remove redundant assertion for dark matter mode. r=njn (b5ac9519f3)
- Bug 1058178, part 1 - Implement DMD heap scanning mode. r=njn (60e1079536)
- Bug 1058178, part 2 - Implement address clamping analysis for DMD scan logs. r=njn (45c0326b93)
- Bug 1102388 - Fix DMD static constructor ordering dependency. r=mccr8 (59b87897a1)
- Bug 1128705 - Don't redefine PAGE_SIZE in DMD if it's already defined. r=erahm (49216348ee)
- Bug 1179042 - Add a script for analyzing memory blocks using a heap scan DMD log. r=njn DONTBUILD (1c08d2d66e)
- Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat (1c999d139b)
- Bug 1158772 - fix non-idiomatic memset call in nsDeque.cpp; r=erahm (de6b555245)
- Bug 1199400 - Part 1: Use CheckedInt when growing nsDeque capacity. r=froydnj (dfdf6814a3)
- Bug 1199400 - Part 0: Remove unused nsDequeIterator. r=froydnj (38d69d7f47)
- Bug 1199400 - Part 2: Add tests for possible nsDeque corner cases. r=froydnj (931baff195)
- Bug 1201997 - Part 1 - Converted compiled test to gtest for nsDeque class. Added tests to test untested methods. r=froydn (e893916651)
- Bug 1201997 - Part 2 - Removing unused methods from the nsDeque class. r=froydn (41595a90ac)
- Bug 1201997 - Part 3 - Make internally used methods private. r=froydn (8cd3afd96f)
- Bug 1201997 - Part 4 - Change size and offset variables to size_t.r=froydn (73eabc8d60)
- Bug 1215140 P1 Add an nsIConsoleReportCollector interface to support navigation channel logging. r=bz (8a41535e2b)
- Bug 1215140 P2 Make HttpBaseChannel implement nsIConsoleReportCollector. r=bz (75fca301f2)
- Bug 1197679 - If nsUnknownDecoder is involved in e10s DivertToParent can break. r=jduell (5d94a12504)
- Bug 1178991 - smartptr for http converter r=hurley (8e7fbc8443)
- bug 366559 - patch 2, fix nsHTTPCompressConv indentation r=bagder (ba762da587)
- bug 366559 - patch 3, fix nsHTTPCompressConv bracing style r=bagder (54195ab451)
- bits of  bug 366559 - patch 7, content-encoding brotli for http (f0b4051022)
- Bug 1205112 - Make PushEvent.data nullable. r=mt,smaug (775db32856)
- Bug 1193414 - SharedWorkers thread should be kept alive also when the SharedWorker object is CCed, r=khuey (b77ea8125c)
- Bug 1206520: Add about:config prefs to enable throwing on asm.js validation failures; r=bz (c42126665d)
- Bug 1193414 - Telemetry for SharedWorker spawning. r=bkelly (77984b7bcc)
- Bug 1205676 - Enable WPT service-worker/unregister-then-register-new-script.https.html in e10s, r=nsm (ec24939cf6)
- Bug 1193133 - Throw when calling postMessage from a Service Worker dom object with no global. r=bkelly (526dcacfab)
- Bug 1181871 P1 Only enforce Cache Context shared data destruction on target thread after init. r=ehsan (cdbf3ed3a8)
- Bug 1181871 P2 Fix ServiceWorkerManager usage of stack-based ErrorResult. r=ehsan (c449195d90)
- minor cleanup and missing bit of 1198230 (02f459db05)
- Bug 1143717 - Implement the ServiceWorkerMessageEvent interface. r=baku (027b3465f2)
- fix misspatch (708eee4e84)
- Bug 1188545 - Disentangle service workers from shared workers and refactor event dispatching code into a separate class. r=nsm,mrbkap (fb5b5341c9)
- Bug 1205228 - Change PackagedAppVerifier to notify the verification result asynchronously. r=valentin. (9edda0fa00)
- Bug 1178518 - Packaged App Utils. r=valentin (f60f3b7a93)
- Bug 1213150 - Part 1: Add a nsContentUtils::IsNonSubresourceRequest helper; r=jdm (b509cc3cc9)
- Bug 1213150 - Part 2: Rework ShouldPrepareForIntercept() in terms of subresource requests; r=jdm (2e92fe8780)
- Bug 1213150 - Part 3: Remove nsIInterceptedChannel.isNavigation; r=jdm (becf1cc12f)
- Bug 1213150 follow-up: fix build bustage (8d73d6ca73)
- Bug 1198394 - Part 1: Allow interception of HSTS upgraded connections in non-e10s mode; r=mcmanus (f504c5be08)
- Bug 1198394 - Part 2: Add a test for interception of HSTS upgraded connections; r=jdm (054e984eef)
- Bug 1187011 - Don't allow response body with null body status. r=bkelly (b1860741d1)
- missing bit of 1140788 (29d319712e)
- Bug 1213436 - Reject core dumps with node IDs that don't fit in an IEEE 754 double; r=sfink (3c1f6fdda0)
- Bug 1211006 - Add Debugger.Source.prototype.canonicalId; r=ejpbruel (eef7b79fce)
- Bug 1199218 - Implement JS::ubi::Node::size for js::LazyScript referents; r=sfink (098a48d240)
- Bug 1220031 - Add JS::ubi::Node::scriptFilename; r=sfink (6b824ae680)
- Bug 1143575. Remove unused MediaQueue::Empty. r=cpearce (de737f3433)
- Bug 1209933 - Make sure all parent runtime pointers are the topmost parent, r=billm. (fe824d967d)
- Bug 1197012 - Fix ThrowTypeError in Notification. r=mccr8 (0b1a097526)
- Bug 1197893 - Check the number of arguments for ThrowTypeError() and ThrowRangeError() at compile time. r=peterv (d98c7d78a0)
- Bug 1142083 - Add test for IDN Unicode domain redirect. r=mcmanus (0c8961fe17)
- Bug 1187159 - Add mochitest for loading packaged apps (iframe+fetch+mozapp) r=jduell (ce90ea561b)
- Bug 1186290 - Notify TabParent to switch process when loading a signed package. r=honzab, r=kanru. (c58a14554a)
- fix (15e2df75eb)
- Bug 1206124 P1 Fix "same-origin" CORS credentials in FetchDriver. r=ehsan (fae1bb6ab3)
- Bug 1206124 P2 Test fetch() with credentials and redirects. r=ehsan (ffc6254112)
- Bug 1211751: Remove nsIChannelEventSink-forwarding from EventSource and FetchDriver. It's never needed. r=smaug (adafe5737a)
- Bug 1212433 Fail fetch() calls that require preflight and also redirect. r=sicking a=abillings (c0d6742b9e)
- Bug 1193128 - Fix base64 decoding when fetching data URIs. r=baku (80bafa291a)
- Bug 1195167 part 1: Let necko handle all protocols. r=bkelly (bb932b0ada)
- Bug 1195167 part 2: Remove redundant aCORSFlag argument and instead use mCORSFlagEverSet. r=bkelly (beadafcad0)
- Bug 1195167 part 3: Remove more scheme-specific handling from FetchDriver. r=bkelly (d00b38db9e)
- Bug 1195167 part 4: Remove FetchDriver::BasicFetch since it is empty. r=bkelly (c5ed097267)
- Bug 1210413 P2 Test CORS credentials on cross-origin redirects. r=sicking a=dveditz (b4eeb8aac0)
- Bug 1210413 P1 Propagate new channel load flags from child to parent on redirect. r=jduell a=dveditz (8b329af4fa)
- Bug 1195167 part 5: Make FetchDriver use AsyncOpen2. r=bkelly (cc217c4cc1)
- Bug 1195167 part 6: Some code simplification since necko handles fetch recursion. r=bkelly (f3b6da2262)
- Bug 1195167: Followup to fix test which I forgot to change (81e7439a2e)
- Bug 1215746: Remove RequestMode::Cors_with_forced_preflight. r=bkelly (0336e812b6)
- Bug 1211000: Move CORS preflight logic from nsCORSListenerProxy to nsCORSPreflightListener. r=ehsan (bf2f71cf22)
- missing bit of Bug 1211443 - Drop scheduled update if decoder initialization isn't done yet. r=jya (f6bc074e33)
- Bug 1182571: Fix nsILoadInfo->GetContentPolicyType API to be less ambigious. Audit and fix all users of it. r=ckerschb (5af6fa7442)
- fix (e40c8e7625)
- Bug 1173811 - Part 1: Propagate the response URL to intercepted channels when necessary (non-e10s). r=mayhemer,bkelly (26f4f13c28)
- Bug 1173811 - Part 2: Propagate the response URL to intercepted channels when necessary (e10s). r=mayhemer,bkelly (a603fe1df2)
- Bug 1154309 - Add New Resource Timing Fields r=bz,hurley (1d14eb6bef)
- Bug 1175685 - add OriginAttribute to LoadInfo. r=jonas, r=ckerschb, r=michal (a5d18bb637)
- Bug 1175685 - add OriginAttribute to LoadInfo. r=jonas, r=ckerschb, r=michal (fb07d2c8aa)
- Bug 1212904 P1 Add a LoadTainting enumeration. r=jduell (a1db8a3e99)
- Bug 1212904 P2 Add LoadTainting information to nsILoadInfo. r=jduell (2482e5e334)
- Bug 1221151 - use [infallible] in nsILoadInfo.idl instead of manual %{C++ blocks; r=jduell (aae73129b6)
- Bug 1045891 - CSP 2 child-src implementation r=ckerschb (792920aeb9)
- Bug 1219931 - CSP: Don't allow removing a policy (r=sicking) (9daaab4186)
- Bug 1208661 - Dump client-side layer textures. r=BenWa (1f2d17d515)
2022-10-17 11:08:37 +08:00

589 lines
18 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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/. */
#include "HttpLog.h"
#include "AlternateServices.h"
#include "nsEscape.h"
#include "nsHttpConnectionInfo.h"
#include "nsHttpHandler.h"
#include "nsThreadUtils.h"
#include "NullHttpTransaction.h"
#include "nsISSLStatusProvider.h"
#include "nsISSLStatus.h"
#include "nsISSLSocketControl.h"
namespace mozilla {
namespace net {
// function places true in outIsHTTPS if scheme is https, false if
// http, and returns an error if neither. originScheme passed into
// alternate service should already be normalized to those lower case
// strings by the URI parser (and so there is an assert)- this is an extra check.
static nsresult
SchemeIsHTTPS(const nsACString &originScheme, bool &outIsHTTPS)
{
outIsHTTPS = originScheme.Equals(NS_LITERAL_CSTRING("https"));
if (!outIsHTTPS && !originScheme.Equals(NS_LITERAL_CSTRING("http"))) {
MOZ_ASSERT(false, "unexpected scheme");
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
void
AltSvcMapping::ProcessHeader(const nsCString &buf, const nsCString &originScheme,
const nsCString &originHost, int32_t originPort,
const nsACString &username, bool privateBrowsing,
nsIInterfaceRequestor *callbacks, nsProxyInfo *proxyInfo,
uint32_t caps)
{
MOZ_ASSERT(NS_IsMainThread());
LOG(("AltSvcMapping::ProcessHeader: %s\n", buf.get()));
if (!callbacks) {
return;
}
if (proxyInfo && !proxyInfo->IsDirect()) {
LOG(("AltSvcMapping::ProcessHeader ignoring due to proxy\n"));
return;
}
bool isHTTPS;
if (NS_FAILED(SchemeIsHTTPS(originScheme, isHTTPS))) {
return;
}
if (!isHTTPS && !gHttpHandler->AllowAltSvcOE()) {
LOG(("Alt-Svc Response Header for http:// origin but OE disabled\n"));
return;
}
LOG(("Alt-Svc Response Header %s\n", buf.get()));
ParsedHeaderValueListList parsedAltSvc(buf);
for (uint32_t index = 0; index < parsedAltSvc.mValues.Length(); ++index) {
uint32_t maxage = 86400; // default
nsAutoCString hostname; // Always empty in the header form
nsAutoCString npnToken;
int32_t portno = originPort;
for (uint32_t pairIndex = 0;
pairIndex < parsedAltSvc.mValues[index].mValues.Length();
++pairIndex) {
nsDependentCSubstring &currentName =
parsedAltSvc.mValues[index].mValues[pairIndex].mName;
nsDependentCSubstring &currentValue =
parsedAltSvc.mValues[index].mValues[pairIndex].mValue;
if (!pairIndex) {
// h2=:443
npnToken = currentName;
int32_t colonIndex = currentValue.FindChar(':');
if (colonIndex >= 0) {
portno =
atoi(PromiseFlatCString(currentValue).get() + colonIndex + 1);
} else {
colonIndex = 0;
}
hostname.Assign(currentValue.BeginReading(), colonIndex);
} else if (currentName.Equals(NS_LITERAL_CSTRING("ma"))) {
maxage = atoi(PromiseFlatCString(currentValue).get());
break;
}
}
// unescape modifies a c string in place, so afterwards
// update nsCString length
nsUnescape(npnToken.BeginWriting());
npnToken.SetLength(strlen(npnToken.BeginReading()));
uint32_t spdyIndex;
SpdyInformation *spdyInfo = gHttpHandler->SpdyInfo();
if (!(NS_SUCCEEDED(spdyInfo->GetNPNIndex(npnToken, &spdyIndex)) &&
spdyInfo->ProtocolEnabled(spdyIndex))) {
LOG(("Alt Svc unknown protocol %s, ignoring", npnToken.get()));
continue;
}
RefPtr<AltSvcMapping> mapping = new AltSvcMapping(originScheme,
originHost, originPort,
username, privateBrowsing,
NowInSeconds() + maxage,
hostname, portno, npnToken);
if (mapping->TTL() <= 0) {
LOG(("Alt Svc invalid map"));
mapping = nullptr;
// since this isn't a parse error, let's clear any existing mapping
// as that would have happened if we had accepted the parameters.
gHttpHandler->ConnMgr()->ClearHostMapping(originHost, originPort);
} else {
gHttpHandler->UpdateAltServiceMapping(mapping, proxyInfo, callbacks, caps);
}
}
}
AltSvcMapping::AltSvcMapping(const nsACString &originScheme,
const nsACString &originHost,
int32_t originPort,
const nsACString &username,
bool privateBrowsing,
uint32_t expiresAt,
const nsACString &alternateHost,
int32_t alternatePort,
const nsACString &npnToken)
: mAlternateHost(alternateHost)
, mAlternatePort(alternatePort)
, mOriginHost(originHost)
, mOriginPort(originPort)
, mUsername(username)
, mPrivate(privateBrowsing)
, mExpiresAt(expiresAt)
, mValidated(false)
, mRunning(false)
, mNPNToken(npnToken)
{
if (NS_FAILED(SchemeIsHTTPS(originScheme, mHttps))) {
LOG(("AltSvcMapping ctor %p invalid scheme\n", this));
mExpiresAt = 0; // invalid
}
if (mAlternatePort == -1) {
mAlternatePort = mHttps ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT;
}
if (mOriginPort == -1) {
mOriginPort = mHttps ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT;
}
LOG(("AltSvcMapping ctor %p %s://%s:%d to %s:%d\n", this,
nsCString(originScheme).get(), mOriginHost.get(), mOriginPort,
mAlternateHost.get(), mAlternatePort));
if (mAlternateHost.IsEmpty()) {
mAlternateHost = mOriginHost;
}
if ((mAlternatePort == mOriginPort) &&
mAlternateHost.EqualsIgnoreCase(mOriginHost.get())) {
LOG(("Alt Svc is also origin Svc - ignoring\n"));
mExpiresAt = 0; // invalid
}
if (mExpiresAt) {
MakeHashKey(mHashKey, originScheme, mOriginHost, mOriginPort, mPrivate);
}
}
void
AltSvcMapping::MakeHashKey(nsCString &outKey,
const nsACString &originScheme,
const nsACString &originHost,
int32_t originPort,
bool privateBrowsing)
{
outKey.Truncate();
if (originPort == -1) {
bool isHttps = originScheme.Equals("https");
originPort = isHttps ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT;
}
outKey.Append(originScheme);
outKey.Append(':');
outKey.Append(originHost);
outKey.Append(':');
outKey.AppendInt(originPort);
outKey.Append(':');
outKey.Append(privateBrowsing ? 'P' : '.');
}
int32_t
AltSvcMapping::TTL()
{
return mExpiresAt - NowInSeconds();
}
void
AltSvcMapping::SetExpired()
{
mExpiresAt = NowInSeconds() - 1;
}
bool
AltSvcMapping::RouteEquals(AltSvcMapping *map)
{
MOZ_ASSERT(map->mHashKey.Equals(mHashKey));
return mAlternateHost.Equals(map->mAlternateHost) &&
(mAlternatePort == map->mAlternatePort) &&
mNPNToken.Equals(map->mNPNToken);
}
void
AltSvcMapping::GetConnectionInfo(nsHttpConnectionInfo **outCI,
nsProxyInfo *pi)
{
RefPtr<nsHttpConnectionInfo> ci =
new nsHttpConnectionInfo(mOriginHost, mOriginPort, mNPNToken,
mUsername, pi, mAlternateHost, mAlternatePort);
ci->SetInsecureScheme(!mHttps);
ci->SetPrivate(mPrivate);
ci.forget(outCI);
}
// This is the asynchronous null transaction used to validate
// an alt-svc advertisement
class AltSvcTransaction final : public NullHttpTransaction
{
public:
AltSvcTransaction(AltSvcMapping *map,
nsHttpConnectionInfo *ci,
nsIInterfaceRequestor *callbacks,
uint32_t caps)
: NullHttpTransaction(ci, callbacks, caps)
, mMapping(map)
, mRunning(false)
, mTriedToValidate(false)
, mTriedToWrite(false)
{
MOZ_ASSERT(mMapping);
LOG(("AltSvcTransaction ctor %p map %p [%s -> %s]",
this, map, map->OriginHost().get(), map->AlternateHost().get()));
}
~AltSvcTransaction()
{
LOG(("AltSvcTransaction dtor %p map %p running %d",
this, mMapping.get(), mRunning));
if (mRunning) {
MOZ_ASSERT(mMapping->IsRunning());
MaybeValidate(NS_OK);
}
if (!mMapping->Validated()) {
// try again later
mMapping->SetExpiresAt(NowInSeconds() + 2);
}
LOG(("AltSvcTransaction dtor %p map %p validated %d [%s]",
this, mMapping.get(), mMapping->Validated(),
mMapping->HashKey().get()));
mMapping->SetRunning(false);
}
void StartTransaction()
{
LOG(("AltSvcTransaction::StartTransaction() %p", this));
MOZ_ASSERT(!mRunning);
MOZ_ASSERT(!mMapping->IsRunning());
mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE;
mRunning = true;
mMapping->SetRunning(true);
}
void MaybeValidate(nsresult reason)
{
if (mTriedToValidate) {
return;
}
mTriedToValidate = true;
LOG(("AltSvcTransaction::MaybeValidate() %p reason=%x running=%d conn=%p write=%d",
this, reason, mRunning, mConnection.get(), mTriedToWrite));
if (mTriedToWrite && reason == NS_BASE_STREAM_CLOSED) {
// The normal course of events is to cause the transaction to fail with CLOSED
// on a write - so that's a success that means the HTTP/2 session is setup.
reason = NS_OK;
}
if (NS_FAILED(reason) || !mRunning || !mConnection) {
LOG(("AltSvcTransaction::MaybeValidate %p Failed due to precondition", this));
return;
}
// insist on spdy/3* or >= http/2
uint32_t version = mConnection->Version();
LOG(("AltSvcTransaction::MaybeValidate() %p version %d\n", this, version));
if ((version < HTTP_VERSION_2) && (version != SPDY_VERSION_31)) {
LOG(("AltSvcTransaction::MaybeValidate %p Failed due to protocol version", this));
return;
}
nsCOMPtr<nsISupports> secInfo;
mConnection->GetSecurityInfo(getter_AddRefs(secInfo));
nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(secInfo);
bool bypassAuth = false;
if (!socketControl ||
NS_FAILED(socketControl->GetBypassAuthentication(&bypassAuth))) {
bypassAuth = false;
}
LOG(("AltSvcTransaction::MaybeValidate() %p socketControl=%p bypass=%d",
this, socketControl.get(), bypassAuth));
if (bypassAuth) {
if (mMapping->HTTPS()) {
MOZ_ASSERT(false); // cannot happen but worth the runtime sanity check
LOG(("AltSvcTransaction::MaybeValidate %p"
"somehow indicates bypassAuth on https:// origin\n", this));
return;
}
LOG(("AltSvcTransaction::MaybeValidate() %p "
"validating alternate service because relaxed", this));
mMapping->SetValidated(true);
return;
}
if (socketControl->GetFailedVerification()) {
LOG(("AltSvcTransaction::MaybeValidate() %p "
"not validated due to auth error", this));
return;
}
LOG(("AltSvcTransaction::MaybeValidate() %p "
"validating alternate service with auth check", this));
mMapping->SetValidated(true);
}
void Close(nsresult reason) override
{
LOG(("AltSvcTransaction::Close() %p reason=%x running %d",
this, reason, mRunning));
MaybeValidate(reason);
if (!mMapping->Validated() && mConnection) {
mConnection->DontReuse();
}
NullHttpTransaction::Close(reason);
}
nsresult ReadSegments(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead) override
{
LOG(("AltSvcTransaction::ReadSegements() %p\n"));
mTriedToWrite = true;
return NullHttpTransaction::ReadSegments(reader, count, countRead);
}
private:
RefPtr<AltSvcMapping> mMapping;
uint32_t mRunning : 1;
uint32_t mTriedToValidate : 1;
uint32_t mTriedToWrite : 1;
};
void
AltSvcCache::UpdateAltServiceMapping(AltSvcMapping *map, nsProxyInfo *pi,
nsIInterfaceRequestor *aCallbacks,
uint32_t caps)
{
MOZ_ASSERT(NS_IsMainThread());
AltSvcMapping *existing = mHash.GetWeak(map->mHashKey);
LOG(("AltSvcCache::UpdateAltServiceMapping %p map %p existing %p %s",
this, map, existing, map->AlternateHost().get()));
if (existing && (existing->TTL() <= 0)) {
LOG(("AltSvcCache::UpdateAltServiceMapping %p map %p is expired",
this, map));
existing = nullptr;
mHash.Remove(map->mHashKey);
}
if (existing && existing->mValidated) {
if (existing->RouteEquals(map)) {
// update expires
LOG(("AltSvcCache::UpdateAltServiceMapping %p map %p updates ttl of %p\n",
this, map, existing));
existing->SetExpiresAt(map->GetExpiresAt());
return;
}
LOG(("AltSvcCache::UpdateAltServiceMapping %p map %p overwrites %p\n",
this, map, existing));
existing = nullptr;
mHash.Remove(map->mHashKey);
}
if (existing) {
LOG(("AltSvcCache::UpdateAltServiceMapping %p map %p ignored because %p "
"still in progress\n", this, map, existing));
return;
}
mHash.Put(map->mHashKey, map);
RefPtr<nsHttpConnectionInfo> ci;
map->GetConnectionInfo(getter_AddRefs(ci), pi);
caps |= ci->GetAnonymous() ? NS_HTTP_LOAD_ANONYMOUS : 0;
nsCOMPtr<nsIInterfaceRequestor> callbacks = new AltSvcOverride(aCallbacks);
RefPtr<AltSvcTransaction> nullTransaction =
new AltSvcTransaction(map, ci, aCallbacks, caps);
nullTransaction->StartTransaction();
gHttpHandler->ConnMgr()->SpeculativeConnect(ci, callbacks, caps, nullTransaction);
}
AltSvcMapping *
AltSvcCache::GetAltServiceMapping(const nsACString &scheme, const nsACString &host,
int32_t port, bool privateBrowsing)
{
bool isHTTPS;
MOZ_ASSERT(NS_IsMainThread());
if (NS_FAILED(SchemeIsHTTPS(scheme, isHTTPS))) {
return nullptr;
}
if (!gHttpHandler->AllowAltSvc()) {
return nullptr;
}
if (!gHttpHandler->AllowAltSvcOE() && !isHTTPS) {
return nullptr;
}
nsAutoCString key;
AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing);
AltSvcMapping *existing = mHash.GetWeak(key);
LOG(("AltSvcCache::GetAltServiceMapping %p key=%s "
"existing=%p validated=%d running=%d ttl=%d",
this, key.get(), existing, existing ? existing->mValidated : 0,
existing ? existing->mRunning : 0,
existing ? existing->TTL() : 0));
if (existing && (existing->TTL() <= 0)) {
LOG(("AltSvcCache::GetAltServiceMapping %p map %p is expired", this, existing));
mHash.Remove(existing->mHashKey);
existing = nullptr;
}
if (existing && existing->mValidated)
return existing;
return nullptr;
}
class ProxyClearHostMapping : public nsRunnable {
public:
explicit ProxyClearHostMapping(const nsACString &host, int32_t port)
: mHost(host)
, mPort(port)
{}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
gHttpHandler->ConnMgr()->ClearHostMapping(mHost, mPort);
return NS_OK;
}
private:
nsCString mHost;
int32_t mPort;
};
void
AltSvcCache::ClearHostMapping(const nsACString &host, int32_t port)
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> event = new ProxyClearHostMapping(host, port);
if (event) {
NS_DispatchToMainThread(event);
}
return;
}
nsAutoCString key;
AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, true);
AltSvcMapping *existing = mHash.GetWeak(key);
if (existing) {
existing->SetExpired();
}
AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, true);
existing = mHash.GetWeak(key);
if (existing) {
existing->SetExpired();
}
AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, false);
existing = mHash.GetWeak(key);
if (existing) {
existing->SetExpired();
}
AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, false);
existing = mHash.GetWeak(key);
if (existing) {
existing->SetExpired();
}
}
void
AltSvcCache::ClearHostMapping(nsHttpConnectionInfo *ci)
{
if (!ci->GetOrigin().IsEmpty()) {
ClearHostMapping(ci->GetOrigin(), ci->OriginPort());
}
}
void
AltSvcCache::ClearAltServiceMappings()
{
MOZ_ASSERT(NS_IsMainThread());
mHash.Clear();
}
NS_IMETHODIMP
AltSvcOverride::GetInterface(const nsIID &iid, void **result)
{
if (NS_SUCCEEDED(QueryInterface(iid, result)) && *result) {
return NS_OK;
}
return mCallbacks->GetInterface(iid, result);
}
NS_IMETHODIMP
AltSvcOverride::GetIgnoreIdle(bool *ignoreIdle)
{
*ignoreIdle = true;
return NS_OK;
}
NS_IMETHODIMP
AltSvcOverride::GetIgnorePossibleSpdyConnections(bool *ignorePossibleSpdyConnections)
{
*ignorePossibleSpdyConnections = true;
return NS_OK;
}
NS_IMETHODIMP
AltSvcOverride::GetParallelSpeculativeConnectLimit(
uint32_t *parallelSpeculativeConnectLimit)
{
*parallelSpeculativeConnectLimit = 32;
return NS_OK;
}
NS_IMETHODIMP
AltSvcOverride::GetIsFromPredictor(bool *isFromPredictor)
{
*isFromPredictor = false;
return NS_OK;
}
NS_IMETHODIMP
AltSvcOverride::GetAllow1918(bool *allow)
{
// normally we don't do speculative connects to 1918.. and we use
// speculative connects for the mapping validation, so override
// that default here for alt-svc
*allow = true;
return NS_OK;
}
NS_IMPL_ISUPPORTS(AltSvcOverride, nsIInterfaceRequestor, nsISpeculativeConnectionOverrider)
} // namespace net
} // namespace mozilla