[tor-commits] [tor-browser/tor-browser-52.8.0esr-7.5-1] Bug 1334776 - Store header names into nsHttpHeaderArray. r=mcmanus

gk at torproject.org gk at torproject.org
Wed Jun 20 11:28:56 UTC 2018


commit cd2dd6a72bef0d0d5d405af3a1913bebb820fc02
Author: Dragana Damjanovic <dd.mozilla at gmail.com>
Date:   Thu Apr 27 16:48:36 2017 +0200

    Bug 1334776 - Store header names into nsHttpHeaderArray. r=mcmanus
    
    Backported to TBB/ESR52 by Arthur Edelstein <arthuredelstein at gmail.com>
---
 dom/security/test/cors/test_CrossSiteXHR.html      |   2 +-
 netwerk/protocol/http/HttpBaseChannel.cpp          |  18 +---
 netwerk/protocol/http/PHttpChannelParams.h         |  15 +++-
 netwerk/protocol/http/nsHttpHeaderArray.cpp        | 100 +++++++++++++++++----
 netwerk/protocol/http/nsHttpHeaderArray.h          |  36 ++++++--
 netwerk/protocol/http/nsHttpRequestHead.cpp        |  23 ++++-
 netwerk/protocol/http/nsHttpRequestHead.h          |   4 +-
 netwerk/protocol/http/nsHttpResponseHead.cpp       |  50 ++++++++---
 netwerk/protocol/http/nsHttpResponseHead.h         |   6 +-
 netwerk/test/unit/test_bug1064258.js               |   2 +-
 .../test/unit/test_original_sent_received_head.js  |  14 +--
 11 files changed, 204 insertions(+), 66 deletions(-)

diff --git a/dom/security/test/cors/test_CrossSiteXHR.html b/dom/security/test/cors/test_CrossSiteXHR.html
index b3cda3b871f3..d9aef5c60cd0 100644
--- a/dom/security/test/cors/test_CrossSiteXHR.html
+++ b/dom/security/test/cors/test_CrossSiteXHR.html
@@ -743,7 +743,7 @@ function runTest() {
             is(res.responseHeaders[header], test.responseHeaders[header],
                "|xhr.getResponseHeader()|wrong response header (" + header + ") in test for " +
                test.toSource());
-            is(res.allResponseHeaders[header], test.responseHeaders[header],
+            is(res.allResponseHeaders[header.toLowerCase()], test.responseHeaders[header],
               "|xhr.getAllResponseHeaderss()|wrong response header (" + header + ") in test for " +
               test.toSource());
           }
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index e68bff1d115e..97120b97a5d3 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1678,13 +1678,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
@@ -1701,13 +1695,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
@@ -1763,7 +1751,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 4df5c7832ee8..b04f57306c58 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/nsHttpHeaderArray.cpp b/netwerk/protocol/http/nsHttpHeaderArray.cpp
index 670300dea50b..98c5a6b9ba47 100644
--- a/netwerk/protocol/http/nsHttpHeaderArray.cpp
+++ b/netwerk/protocol/http/nsHttpHeaderArray.cpp
@@ -18,8 +18,33 @@ 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)
@@ -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,12 @@ 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 +489,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 91b91f04aa1c..4c4b92911a5d 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 094a79457094..b366a8d54264 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 415968083477..b7020d33a0ac 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 6d384c48872e..fa6430b8231f 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 0a912f4b403b..8b51386ea229 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/test/unit/test_bug1064258.js b/netwerk/test/unit/test_bug1064258.js
index 3f76837ae935..da982c2d6f07 100644
--- a/netwerk/test/unit/test_bug1064258.js
+++ b/netwerk/test/unit/test_bug1064258.js
@@ -133,7 +133,7 @@ function cacheCheck2(status, entry)
   do_check_eq(entry.dataSize, 0);
   try {
     do_check_neq(entry.getMetaDataElement("response-head"), null);
-    do_check_true(entry.getMetaDataElement("response-head").match('Etag: testetag'));
+    do_check_true(entry.getMetaDataElement("response-head").match('etag: testetag'));
   }
   catch (ex) {
     do_throw("Missing response head");
diff --git a/netwerk/test/unit/test_original_sent_received_head.js b/netwerk/test/unit/test_original_sent_received_head.js
index c4d02d5d2299..eab359a108ae 100644
--- a/netwerk/test/unit/test_original_sent_received_head.js
+++ b/netwerk/test/unit/test_original_sent_received_head.js
@@ -114,11 +114,11 @@ function checkResponse(request, data, context) {
   var locationHeaderFound = 0;
   request.visitResponseHeaders({
     visitHeader: function visit(aName, aValue) {
-      if (aName == "Link") {
+      if (aName == "link") {
         linkHeaderFound++;
         do_check_eq(aValue, "value1, value2");
       }
-      if (aName == "Location") {
+      if (aName == "location") {
         locationHeaderFound++;
         do_check_eq(aValue, "loc");
       }
@@ -132,7 +132,7 @@ function checkResponse(request, data, context) {
   var locationOrgHeaderFound = 0;
   request.visitOriginalResponseHeaders({
     visitHeader: function visitOrg(aName, aValue) {
-      if (aName == "Link") {
+      if (aName == "link") {
         if (linkOrgHeaderFound == 0) {
           do_check_eq(aValue, "");
         } else if (linkOrgHeaderFound == 1 ) {
@@ -142,7 +142,7 @@ function checkResponse(request, data, context) {
         }
         linkOrgHeaderFound++;
       }
-      if (aName == "Location") {
+      if (aName == "location") {
           locationOrgHeaderFound++;
           do_check_eq(aValue, "loc");
       }
@@ -176,7 +176,7 @@ function checkResponse(request, data, context) {
   var locationOrgHeaderFound2 = 0;
   request.visitOriginalResponseHeaders({
     visitHeader: function visitOrg(aName, aValue) {
-      if (aName == "Link") {
+      if (aName == "link") {
         if (linkOrgHeaderFound2 == 0) {
           do_check_eq(aValue, "");
         } else if (linkOrgHeaderFound2 == 1 ) {
@@ -186,7 +186,7 @@ function checkResponse(request, data, context) {
         }
         linkOrgHeaderFound2++;
       }
-      if (aName == "Location") {
+      if (aName == "location") {
         locationOrgHeaderFound2++;
         do_check_eq(aValue, "loc");
       }
@@ -199,7 +199,7 @@ function checkResponse(request, data, context) {
 
   if (dbg) { print("============== Test GetResponseHeader"); }
   var linkOrgHeaderFound3 = 0;
-  request.getOriginalResponseHeader("Link",{
+  request.getOriginalResponseHeader("link",{
     visitHeader: function visitOrg(aName, aValue) {
       if (linkOrgHeaderFound3 == 0) {
         do_check_eq(aValue, "");





More information about the tor-commits mailing list