Commit c4d32c23 authored by Tsuyoshi Horo's avatar Tsuyoshi Horo Committed by Commit Bot

Introduce ResourceResponse::AddHttpHeaderFieldWithMultipleValues

To avoid inefficient AtomicString concatting when the header value has
multiple commas.

Bug: 930150
Change-Id: I33439d188be20d130278a961ec6ad82d2ba7fa7b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1893608Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712480}
parent 13bb448d
......@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
......@@ -263,6 +264,26 @@ void ResourceResponse::AddHttpHeaderField(const AtomicString& name,
result.stored_value->value = result.stored_value->value + ", " + value;
}
void ResourceResponse::AddHttpHeaderFieldWithMultipleValues(
const AtomicString& name,
const Vector<AtomicString>& values) {
if (values.IsEmpty())
return;
UpdateHeaderParsedState(name);
StringBuilder value_builder;
const auto it = http_header_fields_.Find(name);
if (it != http_header_fields_.end())
value_builder.Append(it->value);
for (const auto& value : values) {
if (!value_builder.IsEmpty())
value_builder.Append(", ");
value_builder.Append(value);
}
http_header_fields_.Set(name, value_builder.ToAtomicString());
}
void ResourceResponse::ClearHttpHeaderField(const AtomicString& name) {
http_header_fields_.Remove(name);
}
......
......@@ -223,6 +223,8 @@ class PLATFORM_EXPORT ResourceResponse final {
const AtomicString& HttpHeaderField(const AtomicString& name) const;
void SetHttpHeaderField(const AtomicString& name, const AtomicString& value);
void AddHttpHeaderField(const AtomicString& name, const AtomicString& value);
void AddHttpHeaderFieldWithMultipleValues(const AtomicString& name,
const Vector<AtomicString>& values);
void ClearHttpHeaderField(const AtomicString& name);
const HTTPHeaderMap& HttpHeaderFields() const;
......
......@@ -84,4 +84,22 @@ TEST(ResourceResponseTest, CrossThreadAtomicStrings) {
thread.reset();
}
TEST(ResourceResponseTest, AddHttpHeaderFieldWithMultipleValues) {
ResourceResponse response(CreateTestResponse());
Vector<AtomicString> empty_values;
response.AddHttpHeaderFieldWithMultipleValues("set-cookie", empty_values);
EXPECT_EQ(AtomicString(), response.HttpHeaderField("set-cookie"));
response.AddHttpHeaderField("set-cookie", "a=1");
EXPECT_EQ("a=1", response.HttpHeaderField("set-cookie"));
Vector<AtomicString> values;
values.push_back("b=2");
values.push_back("c=3");
response.AddHttpHeaderFieldWithMultipleValues("set-cookie", values);
EXPECT_EQ("a=1, b=2, c=3", response.HttpHeaderField("set-cookie"));
}
} // namespace blink
......@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
......@@ -497,10 +498,13 @@ bool ParseMultipartHeadersFromBody(const char* bytes,
size_t iterator = 0;
response->ClearHttpHeaderField(header);
Vector<AtomicString> values;
while (response_headers->EnumerateHeader(&iterator, header_string_piece,
&value)) {
response->AddHttpHeaderField(header, WebString::FromLatin1(value));
const AtomicString atomic_value = WebString::FromLatin1(value);
values.push_back(atomic_value);
}
response->AddHttpHeaderFieldWithMultipleValues(header, values);
}
return true;
}
......
......@@ -320,8 +320,14 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) {
response.AddHttpHeaderField("foo", "bar");
response.AddHttpHeaderField("range", "piyo");
response.AddHttpHeaderField("content-length", "999");
const char kData[] = "content-type: image/png\ncontent-length: 10\n\n";
response.AddHttpHeaderField("set-cookie", "a=1");
const char kData[] =
"content-type: image/png\n"
"content-length: 10\n"
"set-cookie: x=2\n"
"set-cookie: y=3\n"
"\n";
wtf_size_t end = 0;
bool result =
ParseMultipartHeadersFromBody(kData, strlen(kData), &response, &end);
......@@ -332,6 +338,7 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) {
EXPECT_EQ("10", response.HttpHeaderField("content-length"));
EXPECT_EQ("bar", response.HttpHeaderField("foo"));
EXPECT_EQ(AtomicString(), response.HttpHeaderField("range"));
EXPECT_EQ("x=2, y=3", response.HttpHeaderField("set-cookie"));
}
TEST(HTTPParsersTest, ParseMultipartHeadersContentCharset) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment