Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(921)

Unified Diff: third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp

Issue 2787003002: Fetch API: Stop lowercasing header names. (Closed)
Patch Set: Fix failing tests Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698