--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -111,18 +111,21 @@ AltSvcMapping::ProcessHeader(const nsCSt
maxage = atoi(PromiseFlatCString(currentValue).get());
break;
} else {
LOG(("Alt Svc ignoring parameter %s", currentName.BeginReading()));
}
}
if (clearEntry) {
- LOG(("Alt Svc clearing mapping for %s:%d", originHost.get(), originPort));
- gHttpHandler->ConnMgr()->ClearHostMapping(originHost, originPort);
+ nsCString suffix;
+ originAttributes.CreateSuffix(suffix);
+ LOG(("Alt Svc clearing mapping for %s:%d:%s", originHost.get(),
+ originPort, suffix.get()));
+ gHttpHandler->ConnMgr()->ClearHostMapping(originHost, originPort, originAttributes);
continue;
}
// unescape modifies a c string in place, so afterwards
// update nsCString length
nsUnescape(npnToken.BeginWriting());
npnToken.SetLength(strlen(npnToken.BeginReading()));
@@ -135,52 +138,55 @@ AltSvcMapping::ProcessHeader(const nsCSt
}
RefPtr<AltSvcMapping> mapping = new AltSvcMapping(gHttpHandler->ConnMgr()->GetStoragePtr(),
gHttpHandler->ConnMgr()->StorageEpoch(),
originScheme,
originHost, originPort,
username, privateBrowsing,
NowInSeconds() + maxage,
- hostname, portno, npnToken);
+ hostname, portno, npnToken,
+ originAttributes);
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);
+ gHttpHandler->ConnMgr()->ClearHostMapping(originHost, originPort, originAttributes);
} else {
gHttpHandler->UpdateAltServiceMapping(mapping, proxyInfo, callbacks, caps,
originAttributes);
}
}
}
AltSvcMapping::AltSvcMapping(DataStorage *storage, int32_t epoch,
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)
+ const nsACString &npnToken,
+ const OriginAttributes &originAttributes)
: mStorage(storage)
, mStorageEpoch(epoch)
, mAlternateHost(alternateHost)
, mAlternatePort(alternatePort)
, mOriginHost(originHost)
, mOriginPort(originPort)
, mUsername(username)
, mPrivate(privateBrowsing)
, mExpiresAt(expiresAt)
, mValidated(false)
, mMixedScheme(false)
, mNPNToken(npnToken)
+ , mOriginAttributes(originAttributes)
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_FAILED(SchemeIsHTTPS(originScheme, mHttps))) {
LOG(("AltSvcMapping ctor %p invalid scheme\n", this));
mExpiresAt = 0; // invalid
}
@@ -201,41 +207,47 @@ AltSvcMapping::AltSvcMapping(DataStorage
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);
+ MakeHashKey(mHashKey, originScheme, mOriginHost, mOriginPort, mPrivate,
+ mOriginAttributes);
}
}
void
AltSvcMapping::MakeHashKey(nsCString &outKey,
const nsACString &originScheme,
const nsACString &originHost,
int32_t originPort,
- bool privateBrowsing)
+ bool privateBrowsing,
+ const OriginAttributes &originAttributes)
{
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' : '.');
+ outKey.Append(':');
+ nsAutoCString suffix;
+ originAttributes.CreateSuffix(suffix);
+ outKey.Append(suffix);
}
int32_t
AltSvcMapping::TTL()
{
return mExpiresAt - NowInSeconds();
}
@@ -348,16 +360,20 @@ AltSvcMapping::Serialize(nsCString &out)
out.Append(mNPNToken);
out.Append(':');
out.Append(mValidated ? 'y' : 'n');
out.Append(':');
out.AppendInt(mStorageEpoch);
out.Append(':');
out.Append(mMixedScheme ? 'y' : 'n');
out.Append(':');
+ nsAutoCString suffix;
+ mOriginAttributes.CreateSuffix(suffix);
+ out.Append(suffix);
+ out.Append(':');
}
AltSvcMapping::AltSvcMapping(DataStorage *storage, int32_t epoch, const nsCString &str)
: mStorage(storage)
, mStorageEpoch(epoch)
{
mValidated = false;
nsresult code;
@@ -389,20 +405,22 @@ COMPILER ERROR
_NS_NEXT_TOKEN;
mNPNToken = Substring(str, start, idx - start);
_NS_NEXT_TOKEN;
mValidated = Substring(str, start, idx - start).Equals(NS_LITERAL_CSTRING("y"));
_NS_NEXT_TOKEN;
mStorageEpoch = nsCString(Substring(str, start, idx - start)).ToInteger(&code);
_NS_NEXT_TOKEN;
mMixedScheme = Substring(str, start, idx - start).Equals(NS_LITERAL_CSTRING("y"));
+ _NS_NEXT_TOKEN;
+ Unused << mOriginAttributes.PopulateFromSuffix(Substring(str, start, idx - start));
#undef _NS_NEXT_TOKEN
MakeHashKey(mHashKey, mHttps ? NS_LITERAL_CSTRING("https") : NS_LITERAL_CSTRING("http"),
- mOriginHost, mOriginPort, mPrivate);
+ mOriginHost, mOriginPort, mPrivate, mOriginAttributes);
} while (false);
}
// This is the asynchronous null transaction used to validate
// an alt-svc advertisement only for https://
class AltSvcTransaction final : public NullHttpTransaction
{
public:
@@ -908,17 +926,18 @@ AltSvcCache::UpdateAltServiceMapping(Alt
// object deletes itself when done if started
LOG(("AltSvcCache::UpdateAltServiceMapping %p .wk checker started %p\n", this, checker));
}
}
}
already_AddRefed<AltSvcMapping>
AltSvcCache::GetAltServiceMapping(const nsACString &scheme, const nsACString &host,
- int32_t port, bool privateBrowsing)
+ int32_t port, bool privateBrowsing,
+ const OriginAttributes &originAttributes)
{
bool isHTTPS;
MOZ_ASSERT(NS_IsMainThread());
if (!mStorage) {
// DataStorage gives synchronous access to a memory based hash table
// that is backed by disk where those writes are done asynchronously
// on another thread
mStorage = DataStorage::Get(NS_LITERAL_STRING("AlternateServices.txt"));
@@ -940,87 +959,95 @@ AltSvcCache::GetAltServiceMapping(const
if (!gHttpHandler->AllowAltSvc()) {
return nullptr;
}
if (!gHttpHandler->AllowAltSvcOE() && !isHTTPS) {
return nullptr;
}
nsAutoCString key;
- AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing);
+ AltSvcMapping::MakeHashKey(key, scheme, host, port, privateBrowsing, 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;
}
return existing.forget();
}
class ProxyClearHostMapping : public Runnable {
public:
- explicit ProxyClearHostMapping(const nsACString &host, int32_t port)
+ explicit ProxyClearHostMapping(const nsACString &host, int32_t port,
+ const OriginAttributes &originAttributes)
: mHost(host)
, mPort(port)
+ , mOriginAttributes(originAttributes)
{}
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
- gHttpHandler->ConnMgr()->ClearHostMapping(mHost, mPort);
+ gHttpHandler->ConnMgr()->ClearHostMapping(mHost, mPort, mOriginAttributes);
return NS_OK;
}
private:
nsCString mHost;
int32_t mPort;
+ OriginAttributes mOriginAttributes;
};
void
-AltSvcCache::ClearHostMapping(const nsACString &host, int32_t port)
+AltSvcCache::ClearHostMapping(const nsACString &host, int32_t port,
+ const OriginAttributes &originAttributes)
{
if (!NS_IsMainThread()) {
- nsCOMPtr<nsIRunnable> event = new ProxyClearHostMapping(host, port);
+ nsCOMPtr<nsIRunnable> event = new ProxyClearHostMapping(host, port, originAttributes);
if (event) {
NS_DispatchToMainThread(event);
}
return;
}
nsAutoCString key;
- AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, true);
+ AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, true,
+ originAttributes);
RefPtr<AltSvcMapping> existing = LookupMapping(key, true);
if (existing) {
existing->SetExpired();
}
- AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, true);
+ AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, true,
+ originAttributes);
existing = LookupMapping(key, true);
if (existing) {
existing->SetExpired();
}
- AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, false);
+ AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("http"), host, port, false,
+ originAttributes);
existing = LookupMapping(key, false);
if (existing) {
existing->SetExpired();
}
- AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, false);
+ AltSvcMapping::MakeHashKey(key, NS_LITERAL_CSTRING("https"), host, port, false,
+ originAttributes);
existing = LookupMapping(key, false);
if (existing) {
existing->SetExpired();
}
}
void
AltSvcCache::ClearHostMapping(nsHttpConnectionInfo *ci)
{
if (!ci->GetOrigin().IsEmpty()) {
- ClearHostMapping(ci->GetOrigin(), ci->OriginPort());
+ ClearHostMapping(ci->GetOrigin(), ci->OriginPort(), ci->GetOriginAttributes());
}
}
void
AltSvcCache::ClearAltServiceMappings()
{
MOZ_ASSERT(NS_IsMainThread());
if (mStorage) {
--- a/netwerk/protocol/http/AlternateServices.h
+++ b/netwerk/protocol/http/AlternateServices.h
@@ -50,17 +50,18 @@ private: // ctor from ProcessHeader
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);
+ const nsACString &npnToken,
+ const OriginAttributes &originAttributes);
public:
AltSvcMapping(DataStorage *storage, int32_t storageEpoch, const nsCString &serialized);
static void 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, const OriginAttributes &originAttributes);
@@ -87,17 +88,18 @@ public:
void SetExpiresAt(int32_t val);
void SetExpired();
void Sync();
static void MakeHashKey(nsCString &outKey,
const nsACString &originScheme,
const nsACString &originHost,
int32_t originPort,
- bool privateBrowsing);
+ bool privateBrowsing,
+ const OriginAttributes &originAttributes);
private:
virtual ~AltSvcMapping() {};
void SyncString(const nsCString& val);
RefPtr<DataStorage> mStorage;
int32_t mStorageEpoch;
void Serialize (nsCString &out);
@@ -115,16 +117,18 @@ private:
MOZ_INIT_OUTSIDE_CTOR uint32_t mExpiresAt; // alt-svc mappping
MOZ_INIT_OUTSIDE_CTOR bool mValidated;
MOZ_INIT_OUTSIDE_CTOR bool mHttps; // origin is https://
MOZ_INIT_OUTSIDE_CTOR bool mMixedScheme; // .wk allows http and https on same con
nsCString mNPNToken;
+
+ OriginAttributes mOriginAttributes;
};
class AltSvcOverride : public nsIInterfaceRequestor
, public nsISpeculativeConnectionOverrider
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
@@ -167,19 +171,20 @@ class AltSvcCache
public:
AltSvcCache() : mStorageEpoch(0) {}
virtual ~AltSvcCache () {};
void UpdateAltServiceMapping(AltSvcMapping *map, nsProxyInfo *pi,
nsIInterfaceRequestor *, uint32_t caps,
const OriginAttributes &originAttributes); // main thread
already_AddRefed<AltSvcMapping> GetAltServiceMapping(const nsACString &scheme,
const nsACString &host,
- int32_t port, bool pb);
+ int32_t port, bool pb,
+ const OriginAttributes &originAttributes);
void ClearAltServiceMappings();
- void ClearHostMapping(const nsACString &host, int32_t port);
+ void ClearHostMapping(const nsACString &host, int32_t port, const OriginAttributes &originAttributes);
void ClearHostMapping(nsHttpConnectionInfo *ci);
DataStorage *GetStoragePtr() { return mStorage.get(); }
int32_t StorageEpoch() { return mStorageEpoch; }
private:
already_AddRefed<AltSvcMapping> LookupMapping(const nsCString &key, bool privateBrowsing);
RefPtr<DataStorage> mStorage;
int32_t mStorageEpoch;