Index: third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp |
diff --git a/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp b/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp |
index bda2352890c71f60de82f7fd2b17d6dfec101d24..7e2a26113c1eac00bedd15748de4a35123a538de 100644 |
--- a/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp |
+++ b/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp |
@@ -4,10 +4,11 @@ |
#include "modules/fetch/FetchHeaderList.h" |
+#include <algorithm> |
+#include <utility> |
#include "platform/loader/fetch/FetchUtils.h" |
#include "platform/network/HTTPParsers.h" |
-#include "wtf/PtrUtil.h" |
-#include <algorithm> |
+#include "wtf/text/StringBuilder.h" |
namespace blink { |
@@ -17,8 +18,8 @@ FetchHeaderList* FetchHeaderList::create() { |
FetchHeaderList* FetchHeaderList::clone() const { |
FetchHeaderList* list = create(); |
- for (size_t i = 0; i < m_headerList.size(); ++i) |
- list->append(m_headerList[i]->first, m_headerList[i]->second); |
+ for (const auto& header : m_headerList) |
+ list->append(header.first, header.second); |
return list; |
} |
@@ -27,34 +28,36 @@ FetchHeaderList::FetchHeaderList() {} |
FetchHeaderList::~FetchHeaderList() {} |
void FetchHeaderList::append(const String& name, const String& value) { |
+ // https://fetch.spec.whatwg.org/#concept-header-list-append |
// "To append a name/value (|name|/|value|) pair to a header list (|list|), |
- // append a new header whose name is |name|, byte lowercased, and value is |
- // |value|, to |list|." |
- m_headerList.push_back(WTF::wrapUnique(new Header(name.lower(), value))); |
+ // run these steps: |
+ // 1. If |list| contains |name|, then set |name| to the first such header’s |
+ // name. This reuses the casing of the name of the header already in the |
+ // header list, if any. If there are multiple matched headers their names |
+ // will all be identical. |
+ // 2. Append a new header whose name is |name| and |value| is |value| to |
+ // |list|." |
+ const auto& header = m_headerList.find(name); |
+ if (header != m_headerList.end()) |
+ m_headerList.insert(std::make_pair(header->first, value)); |
+ else |
+ m_headerList.insert(std::make_pair(name, value)); |
} |
void FetchHeaderList::set(const String& name, const String& value) { |
+ // https://fetch.spec.whatwg.org/#concept-header-list-set |
// "To set a name/value (|name|/|value|) pair in a header list (|list|), run |
// these steps: |
- // 1. Byte lowercase |name|. |
- // 2. If there are any headers in |list| whose name is |name|, set the value |
- // of the first such header to |value| and remove the others. |
- // 3. Otherwise, append a new header whose name is |name| and value is |
- // |value|, to |list|." |
- const String lowercasedName = name.lower(); |
- for (size_t i = 0; i < m_headerList.size(); ++i) { |
- if (m_headerList[i]->first == lowercasedName) { |
- m_headerList[i]->second = value; |
- for (size_t j = i + 1; j < m_headerList.size();) { |
- if (m_headerList[j]->first == lowercasedName) |
- m_headerList.erase(j); |
- else |
- ++j; |
- } |
- return; |
- } |
- } |
- m_headerList.push_back(WTF::makeUnique<Header>(lowercasedName, value)); |
+ // 1. If |list| contains |name|, then set the value of the first such header |
+ // to |value| and remove the others. |
+ // 2. Otherwise, append a new header whose name is |name| and value is |
+ // |value| to |list|." |
+ const auto& existingHeader = m_headerList.find(name); |
+ const FetchHeaderList::Header newHeader = std::make_pair( |
+ existingHeader != m_headerList.end() ? existingHeader->first : name, |
+ value); |
+ m_headerList.erase(name); |
+ m_headerList.insert(newHeader); |
} |
String FetchHeaderList::extractMIMEType() const { |
@@ -74,51 +77,52 @@ size_t FetchHeaderList::size() const { |
} |
void FetchHeaderList::remove(const String& name) { |
- // "To delete a name (|name|) from a header list (|list|), remove all headers |
- // whose name is |name|, byte lowercased, from |list|." |
- const String lowercasedName = name.lower(); |
- for (size_t i = 0; i < m_headerList.size();) { |
- if (m_headerList[i]->first == lowercasedName) |
- m_headerList.erase(i); |
- else |
- ++i; |
- } |
+ // https://fetch.spec.whatwg.org/#concept-header-list-delete |
+ // "To delete a name (name) from a header list (list), remove all headers |
+ // whose name is a byte-case-insensitive match for name from list." |
+ m_headerList.erase(name); |
} |
bool FetchHeaderList::get(const String& name, String& result) const { |
- const String lowercasedName = name.lower(); |
+ // https://fetch.spec.whatwg.org/#concept-header-list-combine |
+ // "To combine a name/value (|name|/|value|) pair in a header list (|list|), |
+ // run these steps: |
+ // 1. If |list| contains |name|, then set the value of the first such header |
+ // to its value, followed by 0x2C 0x20, followed by |value|. |
+ // 2. Otherwise, append a new header whose name is |name| and value is |
+ // |value| to |list|." |
+ StringBuilder resultBuilder; |
bool found = false; |
- for (const auto& header : m_headerList) { |
- if (header->first == lowercasedName) { |
- if (!found) { |
- result = ""; |
- result.append(header->second); |
- found = true; |
- } else { |
- result.append(","); |
- result.append(header->second); |
- } |
+ const auto& range = m_headerList.equal_range(name); |
+ for (auto header = range.first; header != range.second; ++header) { |
+ if (!found) { |
+ resultBuilder.append(header->second); |
+ found = true; |
+ } else { |
+ // TODO(rakuco): This must be ", " instead. crbug.com/700434. |
+ resultBuilder.append(','); |
+ resultBuilder.append(header->second); |
} |
} |
+ if (found) |
+ result = resultBuilder.toString(); |
return found; |
} |
+// This is going to be removed: see crbug.com/645492. |
void FetchHeaderList::getAll(const String& name, Vector<String>& result) const { |
- const String lowercasedName = name.lower(); |
result.clear(); |
- for (size_t i = 0; i < m_headerList.size(); ++i) { |
- if (m_headerList[i]->first == lowercasedName) |
- result.push_back(m_headerList[i]->second); |
+ const auto& range = m_headerList.equal_range(name); |
+ for (auto header = range.first; header != range.second; ++header) { |
+ result.push_back(header->second); |
} |
} |
bool FetchHeaderList::has(const String& name) const { |
- const String lowercasedName = name.lower(); |
- for (size_t i = 0; i < m_headerList.size(); ++i) { |
- if (m_headerList[i]->first == lowercasedName) |
- return true; |
- } |
- return false; |
+ // https://fetch.spec.whatwg.org/#header-list-contains |
+ // "A header list (|list|) contains a name (|name|) if |list| contains a |
+ // header whose name is a byte-case-insensitive match for |name|." |
+ return m_headerList.find(name) != m_headerList.end(); |
} |
void FetchHeaderList::clearList() { |
@@ -126,33 +130,34 @@ void FetchHeaderList::clearList() { |
} |
bool FetchHeaderList::containsNonSimpleHeader() const { |
- for (size_t i = 0; i < m_headerList.size(); ++i) { |
- if (!FetchUtils::isSimpleHeader(AtomicString(m_headerList[i]->first), |
- AtomicString(m_headerList[i]->second))) |
- return true; |
- } |
- return false; |
+ return std::any_of( |
+ m_headerList.begin(), m_headerList.end(), [](const Header& header) { |
+ return !FetchUtils::isSimpleHeader(AtomicString(header.first), |
+ AtomicString(header.second)); |
+ }); |
} |
-void FetchHeaderList::sortAndCombine() { |
+Vector<FetchHeaderList::Header> FetchHeaderList::sortAndCombine() const { |
// https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine |
- // "To sort and combine a header list..." |
- if (m_headerList.isEmpty()) |
- return; |
- |
- std::sort( |
- m_headerList.begin(), m_headerList.end(), |
- [](const std::unique_ptr<Header>& a, const std::unique_ptr<Header>& b) { |
- return WTF::codePointCompareLessThan(a->first, b->first); |
- }); |
- |
- for (size_t index = m_headerList.size() - 1; index > 0; --index) { |
- if (m_headerList[index - 1]->first == m_headerList[index]->first) { |
- m_headerList[index - 1]->second.append(","); |
- m_headerList[index - 1]->second.append(m_headerList[index]->second); |
- m_headerList.erase(index, 1); |
- } |
+ // "To sort and combine a header list (|list|), run these steps: |
+ // 1. Let |headers| be an empty list of name-value pairs with the key being |
+ // the name and value the value. |
+ // 2. Let |names| be all the names of the headers in |list|, byte-lowercased, |
+ // with duplicates removed, and finally sorted lexicographically. |
+ // 3. For each |name| in |names|, run these substeps: |
+ // 1. Let |value| be the combined value given |name| and |list|. |
+ // 2. Append |name-value| to |headers|. |
+ // 4. Return |headers|." |
+ Vector<FetchHeaderList::Header> ret; |
+ for (auto it = m_headerList.begin(); it != m_headerList.end();) { |
+ const String& headerName = it->first.lower(); |
+ String combinedValue; |
+ get(headerName, combinedValue); |
+ ret.emplace_back(std::make_pair(headerName, combinedValue)); |
+ // Skip to the next distinct key. |
+ it = m_headerList.upper_bound(headerName); |
} |
+ return ret; |
} |
bool FetchHeaderList::isValidHeaderName(const String& name) { |