| 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) {
|
|
|