summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-11-07 12:47:12 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-11-07 12:47:12 +0100
commit8240fb9c736f91044cabbdde8c537b179fc4921e (patch)
tree49a4cc8dc683cf955d61b6618ad471860554ccb5 /netwerk/protocol
parentf9e04b54c2ccbc1f8e24b511003de09b4565193c (diff)
parent5c83a18cde404b5c0c9fba1d35f003d951ea32e2 (diff)
downloadUXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.gz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.lz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.xz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.zip
Merge branch 'master' into Pale_Moon-release
# Conflicts: # application/palemoon/config/version.txt
Diffstat (limited to 'netwerk/protocol')
-rw-r--r--netwerk/protocol/http/Http2Compression.cpp26
-rw-r--r--netwerk/protocol/http/HttpBaseChannel.cpp18
-rw-r--r--netwerk/protocol/http/PHttpChannelParams.h15
-rw-r--r--netwerk/protocol/http/nsHttpChannel.cpp9
-rw-r--r--netwerk/protocol/http/nsHttpChannel.h4
-rw-r--r--netwerk/protocol/http/nsHttpConnectionInfo.cpp22
-rw-r--r--netwerk/protocol/http/nsHttpHeaderArray.cpp99
-rw-r--r--netwerk/protocol/http/nsHttpHeaderArray.h36
-rw-r--r--netwerk/protocol/http/nsHttpRequestHead.cpp23
-rw-r--r--netwerk/protocol/http/nsHttpRequestHead.h4
-rw-r--r--netwerk/protocol/http/nsHttpResponseHead.cpp50
-rw-r--r--netwerk/protocol/http/nsHttpResponseHead.h6
-rw-r--r--netwerk/protocol/http/nsHttpTransaction.cpp4
13 files changed, 239 insertions, 77 deletions
diff --git a/netwerk/protocol/http/Http2Compression.cpp b/netwerk/protocol/http/Http2Compression.cpp
index 64fd05a17..9206f8b4c 100644
--- a/netwerk/protocol/http/Http2Compression.cpp
+++ b/netwerk/protocol/http/Http2Compression.cpp
@@ -402,7 +402,7 @@ Http2Decompressor::DecodeHeaderBlock(const uint8_t *data, uint32_t datalen,
nsresult rv = NS_OK;
nsresult softfail_rv = NS_OK;
- while (NS_SUCCEEDED(rv) && (mOffset < datalen)) {
+ while (NS_SUCCEEDED(rv) && (mOffset < mDataLen)) {
bool modifiesTable = true;
if (mData[mOffset] & 0x80) {
rv = DoIndexed();
@@ -684,6 +684,11 @@ nsresult
Http2Decompressor::DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table,
uint8_t &c, uint8_t &bitsLeft)
{
+ MOZ_ASSERT(mOffset <= mDataLen);
+ if (mOffset > mDataLen) {
+ NS_WARNING("DecodeFinalHuffmanCharacter trying to read beyond end of buffer");
+ return NS_ERROR_FAILURE;
+ }
uint8_t mask = (1 << bitsLeft) - 1;
uint8_t idx = mData[mOffset - 1] & mask;
idx <<= (8 - bitsLeft);
@@ -721,6 +726,7 @@ Http2Decompressor::DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table
uint8_t
Http2Decompressor::ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed)
{
+ MOZ_DIAGNOSTIC_ASSERT(mOffset < mDataLen);
uint8_t rv;
if (bitsLeft) {
@@ -750,8 +756,8 @@ Http2Decompressor::DecodeHuffmanCharacter(const HuffmanIncomingTable *table,
uint8_t idx = ExtractByte(bitsLeft, bytesConsumed);
if (table->IndexHasANextTable(idx)) {
- if (bytesConsumed >= mDataLen) {
- if (!bitsLeft || (bytesConsumed > mDataLen)) {
+ if (mOffset >= mDataLen) {
+ if (!bitsLeft || (mOffset > mDataLen)) {
// TODO - does this get me into trouble in the new world?
// No info left in input to try to consume, we're done
LOG(("DecodeHuffmanCharacter all out of bits to consume, can't chain"));
@@ -892,6 +898,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value,
return rv;
}
+ // sanity check
+ if (mOffset >= mDataLen) {
+ NS_WARNING("Http2 Decompressor ran out of data");
+ // This is session-fatal
+ return NS_ERROR_FAILURE;
+ }
+
bool isHuffmanEncoded;
if (!index) {
@@ -919,6 +932,13 @@ Http2Decompressor::DoLiteralInternal(nsACString &name, nsACString &value,
return rv;
}
+ // sanity check
+ if (mOffset >= mDataLen) {
+ NS_WARNING("Http2 Decompressor ran out of data");
+ // This is session-fatal
+ return NS_ERROR_FAILURE;
+ }
+
// now the value
uint32_t valueLen;
isHuffmanEncoded = mData[mOffset] & (1 << 7);
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index c4e764d26..03123ceb0 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1665,13 +1665,7 @@ HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
return NS_ERROR_INVALID_ARG;
}
- nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
- if (!atom) {
- NS_WARNING("failed to resolve atom");
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return mRequestHead.SetHeader(atom, flatValue, aMerge);
+ return mRequestHead.SetHeader(aHeader, flatValue, aMerge);
}
NS_IMETHODIMP
@@ -1688,13 +1682,7 @@ HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader)
return NS_ERROR_INVALID_ARG;
}
- nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
- if (!atom) {
- NS_WARNING("failed to resolve atom");
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- return mRequestHead.SetEmptyHeader(atom);
+ return mRequestHead.SetEmptyHeader(aHeader);
}
NS_IMETHODIMP
@@ -1750,7 +1738,7 @@ HttpBaseChannel::SetResponseHeader(const nsACString& header,
mResponseHeadersModified = true;
- return mResponseHead->SetHeader(atom, value, merge);
+ return mResponseHead->SetHeader(header, value, merge);
}
NS_IMETHODIMP
diff --git a/netwerk/protocol/http/PHttpChannelParams.h b/netwerk/protocol/http/PHttpChannelParams.h
index 4df5c7832..b04f57306 100644
--- a/netwerk/protocol/http/PHttpChannelParams.h
+++ b/netwerk/protocol/http/PHttpChannelParams.h
@@ -98,7 +98,11 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry>
static void Write(Message* aMsg, const paramType& aParam)
{
- WriteParam(aMsg, aParam.header);
+ if (aParam.headerNameOriginal.IsEmpty()) {
+ WriteParam(aMsg, aParam.header);
+ } else {
+ WriteParam(aMsg, aParam.headerNameOriginal);
+ }
WriteParam(aMsg, aParam.value);
switch (aParam.variety) {
case mozilla::net::nsHttpHeaderArray::eVarietyUnknown:
@@ -124,11 +128,18 @@ struct ParamTraits<mozilla::net::nsHttpHeaderArray::nsEntry>
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
uint8_t variety;
- if (!ReadParam(aMsg, aIter, &aResult->header) ||
+ nsAutoCString header;
+ if (!ReadParam(aMsg, aIter, &header) ||
!ReadParam(aMsg, aIter, &aResult->value) ||
!ReadParam(aMsg, aIter, &variety))
return false;
+ mozilla::net::nsHttpAtom atom = mozilla::net::nsHttp::ResolveAtom(header);
+ aResult->header = atom;
+ if (!header.Equals(atom.get())) {
+ aResult->headerNameOriginal = header;
+ }
+
switch (variety) {
case 0:
aResult->variety = mozilla::net::nsHttpHeaderArray::eVarietyUnknown;
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index bb0b3ca77..be5539a02 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -313,11 +313,15 @@ nsHttpChannel::nsHttpChannel()
, mPushedStream(nullptr)
, mLocalBlocklist(false)
, mWarningReporter(nullptr)
+ , mSendUpgradeRequest(false)
, mDidReval(false)
{
LOG(("Creating nsHttpChannel [this=%p]\n", this));
mChannelCreationTime = PR_Now();
mChannelCreationTimestamp = TimeStamp::Now();
+
+ mSendUpgradeRequest =
+ Preferences::GetBool("network.http.upgrade-insecure-requests", false);
}
nsHttpChannel::~nsHttpChannel()
@@ -377,8 +381,9 @@ nsHttpChannel::Connect()
mLoadInfo->GetExternalContentPolicyType() :
nsIContentPolicy::TYPE_OTHER;
- if (type == nsIContentPolicy::TYPE_DOCUMENT ||
- type == nsIContentPolicy::TYPE_SUBDOCUMENT) {
+ if (mSendUpgradeRequest &&
+ (type == nsIContentPolicy::TYPE_DOCUMENT ||
+ type == nsIContentPolicy::TYPE_SUBDOCUMENT)) {
rv = SetRequestHeader(NS_LITERAL_CSTRING("Upgrade-Insecure-Requests"),
NS_LITERAL_CSTRING("1"), false);
NS_ENSURE_SUCCESS(rv, rv);
diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h
index 2e24d6e81..152cf1503 100644
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -597,6 +597,10 @@ private:
HttpChannelSecurityWarningReporter* mWarningReporter;
RefPtr<ADivertableParentChannel> mParentChannel;
+
+ // Whether we send opportunistic encryption requests.
+ bool mSendUpgradeRequest;
+
protected:
virtual void DoNotifyListenerCleanup() override;
diff --git a/netwerk/protocol/http/nsHttpConnectionInfo.cpp b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
index e965fd1cc..93a40843c 100644
--- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
@@ -15,32 +15,26 @@
#include "nsHttpConnectionInfo.h"
#include "mozilla/net/DNS.h"
-#include "prnetdb.h"
-#include "nsICryptoHash.h"
#include "nsComponentManagerUtils.h"
+#include "nsICryptoHash.h"
#include "nsIProtocolProxyService.h"
+#include "nsNetCID.h"
+#include "prnetdb.h"
static nsresult
SHA256(const char* aPlainText, nsAutoCString& aResult)
{
- static nsICryptoHash* hasher = nullptr;
nsresult rv;
- if (!hasher) {
- rv = CallCreateInstance("@mozilla.org/security/hash;1", &hasher);
- if (NS_FAILED(rv)) {
- LOG(("nsHttpDigestAuth: no crypto hash!\n"));
- return rv;
- }
+ nsCOMPtr<nsICryptoHash> hasher = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) {
+ LOG(("nsHttpDigestAuth: no crypto hash!\n"));
+ return rv;
}
-
rv = hasher->Init(nsICryptoHash::SHA256);
NS_ENSURE_SUCCESS(rv, rv);
-
rv = hasher->Update((unsigned char*) aPlainText, strlen(aPlainText));
NS_ENSURE_SUCCESS(rv, rv);
-
- rv = hasher->Finish(false, aResult);
- return rv;
+ return hasher->Finish(false, aResult);
}
namespace mozilla {
diff --git a/netwerk/protocol/http/nsHttpHeaderArray.cpp b/netwerk/protocol/http/nsHttpHeaderArray.cpp
index 670300dea..1030bc91e 100644
--- a/netwerk/protocol/http/nsHttpHeaderArray.cpp
+++ b/netwerk/protocol/http/nsHttpHeaderArray.cpp
@@ -18,12 +18,37 @@ namespace net {
//-----------------------------------------------------------------------------
// nsHttpHeaderArray <public>
//-----------------------------------------------------------------------------
+
+nsresult
+nsHttpHeaderArray::SetHeader(const nsACString &headerName,
+ const nsACString &value,
+ bool merge,
+ nsHttpHeaderArray::HeaderVariety variety)
+{
+ nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get());
+ if (!header) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return SetHeader(header, headerName, value, merge, variety);
+}
+
nsresult
nsHttpHeaderArray::SetHeader(nsHttpAtom header,
const nsACString &value,
bool merge,
nsHttpHeaderArray::HeaderVariety variety)
{
+ return SetHeader(header, EmptyCString(), value, merge, variety);
+}
+
+nsresult
+nsHttpHeaderArray::SetHeader(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
+ bool merge,
+ nsHttpHeaderArray::HeaderVariety variety)
+{
MOZ_ASSERT((variety == eVarietyResponse) ||
(variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride),
@@ -51,7 +76,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
MOZ_ASSERT(!entry || variety != eVarietyRequestDefault,
"Cannot set default entry which overrides existing entry!");
if (!entry) {
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerName, value, variety);
} else if (merge && !IsSingletonHeader(header)) {
return MergeHeader(header, entry, value, variety);
} else {
@@ -59,7 +84,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal;
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerName, value, variety);
} else {
entry->value = value;
entry->variety = variety;
@@ -71,6 +96,7 @@ nsHttpHeaderArray::SetHeader(nsHttpAtom header,
nsresult
nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header,
+ const nsACString &headerName,
const nsACString &value,
nsHttpHeaderArray::HeaderVariety variety)
{
@@ -79,14 +105,26 @@ nsHttpHeaderArray::SetHeader_internal(nsHttpAtom header,
return NS_ERROR_OUT_OF_MEMORY;
}
entry->header = header;
+ // Only save original form of a header if it is different than the header
+ // atom string.
+ if (!headerName.Equals(header.get())) {
+ entry->headerNameOriginal = headerName;
+ }
entry->value = value;
entry->variety = variety;
return NS_OK;
}
nsresult
-nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety)
+nsHttpHeaderArray::SetEmptyHeader(const nsACString &headerName,
+ HeaderVariety variety)
{
+ nsHttpAtom header = nsHttp::ResolveAtom(PromiseFlatCString(headerName).get());
+ if (!header) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
MOZ_ASSERT((variety == eVarietyResponse) ||
(variety == eVarietyRequestDefault) ||
(variety == eVarietyRequestOverride),
@@ -104,11 +142,12 @@ nsHttpHeaderArray::SetEmptyHeader(nsHttpAtom header, HeaderVariety variety)
entry->variety = eVarietyResponseNetOriginal;
}
- return SetHeader_internal(header, EmptyCString(), variety);
+ return SetHeader_internal(header, headerName, EmptyCString(), variety);
}
nsresult
nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
const nsACString &value,
bool response)
{
@@ -125,7 +164,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
LOG(("Ignoring Empty Header: %s\n", header.get()));
if (response) {
// Set header as original but not as response header.
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
return NS_OK; // ignore empty headers by default
@@ -135,7 +174,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
if (response) {
variety = eVarietyResponseNetOriginalAndResponse;
}
- return SetHeader_internal(header, value, variety);
+ return SetHeader_internal(header, headerNameOriginal, value, variety);
} else if (!IsSingletonHeader(header)) {
HeaderVariety variety = eVarietyRequestOverride;
@@ -147,7 +186,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
return rv;
}
if (response) {
- rv = SetHeader_internal(header, value,
+ rv = SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
return rv;
@@ -164,7 +203,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
}
if (response) {
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
}
}
@@ -174,6 +213,7 @@ nsHttpHeaderArray::SetHeaderFromNet(nsHttpAtom header,
nsresult
nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
const nsACString &value,
nsHttpHeaderArray::HeaderVariety variety)
{
@@ -183,7 +223,7 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
"eVarietyResponseNetOriginal");
if (variety == eVarietyResponseNetOriginal) {
- return SetHeader_internal(header, value,
+ return SetHeader_internal(header, headerNameOriginal, value,
eVarietyResponseNetOriginal);
} else {
nsTArray<nsEntry>::index_type index = 0;
@@ -203,7 +243,8 @@ nsHttpHeaderArray::SetResponseHeaderFromCache(nsHttpAtom header,
}
} while (index != mHeaders.NoIndex);
// If we are here, we have not found an entry so add a new one.
- return SetHeader_internal(header, value, eVarietyResponse);
+ return SetHeader_internal(header, headerNameOriginal, value,
+ eVarietyResponse);
}
}
@@ -260,8 +301,16 @@ nsHttpHeaderArray::GetOriginalHeader(nsHttpAtom aHeader,
if (entry.variety == eVarietyResponse) {
continue;
}
+
+ nsAutoCString hdr;
+ if (entry.headerNameOriginal.IsEmpty()) {
+ hdr = nsDependentCString(entry.header);
+ } else {
+ hdr = entry.headerNameOriginal;
+ }
+
rv = NS_OK;
- if (NS_FAILED(aVisitor->VisitHeader(nsDependentCString(entry.header),
+ if (NS_FAILED(aVisitor->VisitHeader(hdr,
entry.value))) {
break;
}
@@ -298,8 +347,14 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray
} else if (filter == eFilterResponseOriginal && entry.variety == eVarietyResponse) {
continue;
}
- rv = visitor->VisitHeader(
- nsDependentCString(entry.header), entry.value);
+
+ nsAutoCString hdr;
+ if (entry.headerNameOriginal.IsEmpty()) {
+ hdr = nsDependentCString(entry.header);
+ } else {
+ hdr = entry.headerNameOriginal;
+ }
+ rv = visitor->VisitHeader(hdr, entry.value);
if NS_FAILED(rv) {
return rv;
}
@@ -310,6 +365,7 @@ nsHttpHeaderArray::VisitHeaders(nsIHttpHeaderVisitor *visitor, nsHttpHeaderArray
/*static*/ nsresult
nsHttpHeaderArray::ParseHeaderLine(const nsACString& line,
nsHttpAtom *hdr,
+ nsACString *headerName,
nsACString *val)
{
//
@@ -360,6 +416,7 @@ nsHttpHeaderArray::ParseHeaderLine(const nsACString& line,
// assign return values
if (hdr) *hdr = atom;
if (val) val->Assign(p, p2 - p + 1);
+ if (headerName) headerName->Assign(sub);
return NS_OK;
}
@@ -397,7 +454,11 @@ nsHttpHeaderArray::Flatten(nsACString &buf, bool pruneProxyHeaders,
continue;
}
- buf.Append(entry.header);
+ if (entry.headerNameOriginal.IsEmpty()) {
+ buf.Append(entry.header);
+ } else {
+ buf.Append(entry.headerNameOriginal);
+ }
buf.AppendLiteral(": ");
buf.Append(entry.value);
buf.AppendLiteral("\r\n");
@@ -415,7 +476,11 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf)
continue;
}
- buf.Append(entry.header);
+ if (entry.headerNameOriginal.IsEmpty()) {
+ buf.Append(entry.header);
+ } else {
+ buf.Append(entry.headerNameOriginal);
+ }
buf.AppendLiteral(": ");
buf.Append(entry.value);
buf.AppendLiteral("\r\n");
@@ -423,11 +488,13 @@ nsHttpHeaderArray::FlattenOriginalHeader(nsACString &buf)
}
const char *
-nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header) const
+nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom &header,
+ nsACString &headerNameOriginal) const
{
const nsEntry &entry = mHeaders[index];
header = entry.header;
+ headerNameOriginal = entry.headerNameOriginal;
return entry.value.get();
}
diff --git a/netwerk/protocol/http/nsHttpHeaderArray.h b/netwerk/protocol/http/nsHttpHeaderArray.h
index 91b91f04a..3ffdfa814 100644
--- a/netwerk/protocol/http/nsHttpHeaderArray.h
+++ b/netwerk/protocol/http/nsHttpHeaderArray.h
@@ -49,19 +49,30 @@ public:
};
// Used by internal setters: to set header from network use SetHeaderFromNet
+ nsresult SetHeader(const nsACString &headerName,
+ const nsACString &value,
+ bool merge, HeaderVariety variety);
nsresult SetHeader(nsHttpAtom header, const nsACString &value,
bool merge, HeaderVariety variety);
+ nsresult SetHeader(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
+ bool merge, HeaderVariety variety);
// Used by internal setters to set an empty header
- nsresult SetEmptyHeader(nsHttpAtom header, HeaderVariety variety);
+ nsresult SetEmptyHeader(const nsACString &headerName, HeaderVariety variety);
// Merges supported headers. For other duplicate values, determines if error
// needs to be thrown or 1st value kept.
// For the response header we keep the original headers as well.
- nsresult SetHeaderFromNet(nsHttpAtom header, const nsACString &value,
+ nsresult SetHeaderFromNet(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
+ const nsACString &value,
bool response);
- nsresult SetResponseHeaderFromCache(nsHttpAtom header, const nsACString &value,
+ nsresult SetResponseHeaderFromCache(nsHttpAtom header,
+ const nsACString &headerNameOriginal,
+ const nsACString &value,
HeaderVariety variety);
nsresult GetHeader(nsHttpAtom header, nsACString &value) const;
@@ -97,15 +108,17 @@ public:
// parse a header line, return the header atom and a pointer to the
// header value (the substring of the header line -- do not free).
static nsresult ParseHeaderLine(const nsACString& line,
- nsHttpAtom *header=nullptr,
- nsACString* value=nullptr);
+ nsHttpAtom *header = nullptr,
+ nsACString *headerNameOriginal = nullptr,
+ nsACString *value = nullptr);
void Flatten(nsACString &, bool pruneProxyHeaders, bool pruneTransients);
void FlattenOriginalHeader(nsACString &);
uint32_t Count() const { return mHeaders.Length(); }
- const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const;
+ const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header,
+ nsACString &headerNameOriginal) const;
void Clear();
@@ -113,6 +126,7 @@ public:
struct nsEntry
{
nsHttpAtom header;
+ nsCString headerNameOriginal;
nsCString value;
HeaderVariety variety = eVarietyUnknown;
@@ -140,7 +154,9 @@ private:
int32_t LookupEntry(nsHttpAtom header, nsEntry **);
nsresult MergeHeader(nsHttpAtom header, nsEntry *entry,
const nsACString &value, HeaderVariety variety);
- nsresult SetHeader_internal(nsHttpAtom header, const nsACString &value,
+ nsresult SetHeader_internal(nsHttpAtom header,
+ const nsACString &headerName,
+ const nsACString &value,
HeaderVariety variety);
// Header cannot be merged: only one value possible
@@ -257,7 +273,11 @@ nsHttpHeaderArray::MergeHeader(nsHttpAtom header,
if (entry->variety == eVarietyResponseNetOriginalAndResponse) {
MOZ_ASSERT(variety == eVarietyResponse);
entry->variety = eVarietyResponseNetOriginal;
- nsresult rv = SetHeader_internal(header, newValue, eVarietyResponse);
+ // Copy entry->headerNameOriginal because in SetHeader_internal we are going
+ // to a new one and a realocation can happen.
+ nsCString headerNameOriginal = entry->headerNameOriginal;
+ nsresult rv = SetHeader_internal(header, headerNameOriginal,
+ newValue, eVarietyResponse);
if (NS_FAILED(rv)) {
return rv;
}
diff --git a/netwerk/protocol/http/nsHttpRequestHead.cpp b/netwerk/protocol/http/nsHttpRequestHead.cpp
index 094a79457..b366a8d54 100644
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -131,6 +131,20 @@ nsHttpRequestHead::Origin(nsACString &aOrigin)
}
nsresult
+nsHttpRequestHead::SetHeader(const nsACString &h, const nsACString &v,
+ bool m /*= false*/)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mInVisitHeaders) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return mHeaders.SetHeader(h, v, m,
+ nsHttpHeaderArray::eVarietyRequestOverride);
+}
+
+nsresult
nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v,
bool m /*= false*/)
{
@@ -158,7 +172,7 @@ nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m,
}
nsresult
-nsHttpRequestHead::SetEmptyHeader(nsHttpAtom h)
+nsHttpRequestHead::SetEmptyHeader(const nsACString &h)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
@@ -253,6 +267,7 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
nsHttpAtom hdr;
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
while (buffer) {
const char *eof = strchr(buffer, '\r');
@@ -262,9 +277,13 @@ nsHttpRequestHead::ParseHeaderSet(const char *buffer)
if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine(
nsDependentCSubstring(buffer, eof - buffer),
&hdr,
+ &headerNameOriginal,
&val))) {
- mHeaders.SetHeaderFromNet(hdr, val, false);
+ mHeaders.SetHeaderFromNet(hdr,
+ headerNameOriginal,
+ val,
+ false);
}
buffer = eof + 1;
if (*buffer == '\n') {
diff --git a/netwerk/protocol/http/nsHttpRequestHead.h b/netwerk/protocol/http/nsHttpRequestHead.h
index 415968083..b7020d33a 100644
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -57,10 +57,12 @@ public:
int32_t port);
void Origin(nsACString &aOrigin);
+ nsresult SetHeader(const nsACString &h, const nsACString &v,
+ bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m,
nsHttpHeaderArray::HeaderVariety variety);
- nsresult SetEmptyHeader(nsHttpAtom h);
+ nsresult SetEmptyHeader(const nsACString &h);
nsresult GetHeader(nsHttpAtom h, nsACString &v);
nsresult ClearHeader(nsHttpAtom h);
diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp
index 6d384c488..fa6430b82 100644
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -137,6 +137,26 @@ nsHttpResponseHead::Immutable()
}
nsresult
+nsHttpResponseHead::SetHeader(const nsACString &hdr,
+ const nsACString &val,
+ bool merge)
+{
+ ReentrantMonitorAutoEnter monitor(mReentrantMonitor);
+
+ if (mInVisitHeaders) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsHttpAtom atom = nsHttp::ResolveAtom(PromiseFlatCString(hdr).get());
+ if (!atom) {
+ NS_WARNING("failed to resolve atom");
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ return SetHeader_locked(atom, hdr, val, merge);
+}
+
+nsresult
nsHttpResponseHead::SetHeader(nsHttpAtom hdr,
const nsACString &val,
bool merge)
@@ -147,24 +167,25 @@ nsHttpResponseHead::SetHeader(nsHttpAtom hdr,
return NS_ERROR_FAILURE;
}
- return SetHeader_locked(hdr, val, merge);
+ return SetHeader_locked(hdr, EmptyCString(), val, merge);
}
nsresult
-nsHttpResponseHead::SetHeader_locked(nsHttpAtom hdr,
+nsHttpResponseHead::SetHeader_locked(nsHttpAtom atom,
+ const nsACString &hdr,
const nsACString &val,
bool merge)
{
- nsresult rv = mHeaders.SetHeader(hdr, val, merge,
+ nsresult rv = mHeaders.SetHeader(atom, hdr, val, merge,
nsHttpHeaderArray::eVarietyResponse);
if (NS_FAILED(rv)) return rv;
// respond to changes in these headers. we need to reparse the entire
// header since the change may have merged in additional values.
- if (hdr == nsHttp::Cache_Control)
- ParseCacheControl(mHeaders.PeekHeader(hdr));
- else if (hdr == nsHttp::Pragma)
- ParsePragma(mHeaders.PeekHeader(hdr));
+ if (atom == nsHttp::Cache_Control)
+ ParseCacheControl(mHeaders.PeekHeader(atom));
+ else if (atom == nsHttp::Pragma)
+ ParsePragma(mHeaders.PeekHeader(atom));
return NS_OK;
}
@@ -316,6 +337,7 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block)
char *p = block;
nsHttpAtom hdr = {0};
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
nsresult rv;
@@ -331,12 +353,13 @@ nsHttpResponseHead::ParseCachedOriginalHeaders(char *block)
*p = 0;
if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(
- nsDependentCString(block, p - block), &hdr, &val))) {
+ nsDependentCString(block, p - block), &hdr, &headerNameOriginal, &val))) {
return NS_OK;
}
rv = mHeaders.SetResponseHeaderFromCache(hdr,
+ headerNameOriginal,
val,
nsHttpHeaderArray::eVarietyResponseNetOriginal);
@@ -567,18 +590,21 @@ nsresult
nsHttpResponseHead::ParseHeaderLine_locked(const nsACString &line, bool originalFromNetHeaders)
{
nsHttpAtom hdr = {0};
+ nsAutoCString headerNameOriginal;
nsAutoCString val;
- if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &val))) {
+ if (NS_FAILED(nsHttpHeaderArray::ParseHeaderLine(line, &hdr, &headerNameOriginal, &val))) {
return NS_OK;
}
nsresult rv;
if (originalFromNetHeaders) {
rv = mHeaders.SetHeaderFromNet(hdr,
+ headerNameOriginal,
val,
true);
} else {
rv = mHeaders.SetResponseHeaderFromCache(hdr,
+ headerNameOriginal,
val,
nsHttpHeaderArray::eVarietyResponse);
}
@@ -856,7 +882,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther)
uint32_t i, count = aOther->mHeaders.Count();
for (i=0; i<count; ++i) {
nsHttpAtom header;
- const char *val = aOther->mHeaders.PeekHeaderAt(i, header);
+ nsAutoCString headerNameOriginal;
+ const char *val = aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal);
if (!val) {
continue;
@@ -890,7 +917,8 @@ nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead *aOther)
LOG(("new response header [%s: %s]\n", header.get(), val));
// overwrite the current header value with the new value...
- SetHeader_locked(header, nsDependentCString(val));
+ SetHeader_locked(header, headerNameOriginal,
+ nsDependentCString(val));
}
}
diff --git a/netwerk/protocol/http/nsHttpResponseHead.h b/netwerk/protocol/http/nsHttpResponseHead.h
index 0a912f4b4..8b51386ea 100644
--- a/netwerk/protocol/http/nsHttpResponseHead.h
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -65,6 +65,8 @@ public:
*/
int64_t TotalEntitySize();
+ nsresult SetHeader(const nsACString &h, const nsACString &v,
+ bool m=false);
nsresult SetHeader(nsHttpAtom h, const nsACString &v, bool m=false);
nsresult GetHeader(nsHttpAtom h, nsACString &v);
void ClearHeader(nsHttpAtom h);
@@ -137,8 +139,8 @@ public:
bool HasContentType();
bool HasContentCharset();
private:
- nsresult SetHeader_locked(nsHttpAtom h, const nsACString &v,
- bool m=false);
+ nsresult SetHeader_locked(nsHttpAtom atom, const nsACString &h,
+ const nsACString &v, bool m=false);
void AssignDefaultStatusText();
void ParseVersion(const char *);
void ParseCacheControl(const char *);
diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp
index 8d837d172..76e0a4ad9 100644
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -1164,7 +1164,9 @@ nsHttpTransaction::Close(nsresult reason)
}
// closing this pipe triggers the channel's OnStopRequest method.
- mPipeOut->CloseWithStatus(reason);
+ if (mPipeOut) {
+ mPipeOut->CloseWithStatus(reason);
+ }
#ifdef WIN32 // bug 1153929
MOZ_DIAGNOSTIC_ASSERT(mPipeOut);