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 @@ ...@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/platform/network/http_parsers.h" #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/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.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 { namespace blink {
...@@ -263,6 +264,26 @@ void ResourceResponse::AddHttpHeaderField(const AtomicString& name, ...@@ -263,6 +264,26 @@ void ResourceResponse::AddHttpHeaderField(const AtomicString& name,
result.stored_value->value = result.stored_value->value + ", " + value; 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) { void ResourceResponse::ClearHttpHeaderField(const AtomicString& name) {
http_header_fields_.Remove(name); http_header_fields_.Remove(name);
} }
......
...@@ -223,6 +223,8 @@ class PLATFORM_EXPORT ResourceResponse final { ...@@ -223,6 +223,8 @@ class PLATFORM_EXPORT ResourceResponse final {
const AtomicString& HttpHeaderField(const AtomicString& name) const; const AtomicString& HttpHeaderField(const AtomicString& name) const;
void SetHttpHeaderField(const AtomicString& name, const AtomicString& value); void SetHttpHeaderField(const AtomicString& name, const AtomicString& value);
void AddHttpHeaderField(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); void ClearHttpHeaderField(const AtomicString& name);
const HTTPHeaderMap& HttpHeaderFields() const; const HTTPHeaderMap& HttpHeaderFields() const;
......
...@@ -84,4 +84,22 @@ TEST(ResourceResponseTest, CrossThreadAtomicStrings) { ...@@ -84,4 +84,22 @@ TEST(ResourceResponseTest, CrossThreadAtomicStrings) {
thread.reset(); 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 } // namespace blink
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/network/http_names.h" #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/date_math.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.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/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h" #include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
...@@ -497,10 +498,13 @@ bool ParseMultipartHeadersFromBody(const char* bytes, ...@@ -497,10 +498,13 @@ bool ParseMultipartHeadersFromBody(const char* bytes,
size_t iterator = 0; size_t iterator = 0;
response->ClearHttpHeaderField(header); response->ClearHttpHeaderField(header);
Vector<AtomicString> values;
while (response_headers->EnumerateHeader(&iterator, header_string_piece, while (response_headers->EnumerateHeader(&iterator, header_string_piece,
&value)) { &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; return true;
} }
......
...@@ -320,8 +320,14 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) { ...@@ -320,8 +320,14 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) {
response.AddHttpHeaderField("foo", "bar"); response.AddHttpHeaderField("foo", "bar");
response.AddHttpHeaderField("range", "piyo"); response.AddHttpHeaderField("range", "piyo");
response.AddHttpHeaderField("content-length", "999"); response.AddHttpHeaderField("content-length", "999");
response.AddHttpHeaderField("set-cookie", "a=1");
const char kData[] = "content-type: image/png\ncontent-length: 10\n\n";
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; wtf_size_t end = 0;
bool result = bool result =
ParseMultipartHeadersFromBody(kData, strlen(kData), &response, &end); ParseMultipartHeadersFromBody(kData, strlen(kData), &response, &end);
...@@ -332,6 +338,7 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) { ...@@ -332,6 +338,7 @@ TEST(HTTPParsersTest, ParseMultipartHeaders) {
EXPECT_EQ("10", response.HttpHeaderField("content-length")); EXPECT_EQ("10", response.HttpHeaderField("content-length"));
EXPECT_EQ("bar", response.HttpHeaderField("foo")); EXPECT_EQ("bar", response.HttpHeaderField("foo"));
EXPECT_EQ(AtomicString(), response.HttpHeaderField("range")); EXPECT_EQ(AtomicString(), response.HttpHeaderField("range"));
EXPECT_EQ("x=2, y=3", response.HttpHeaderField("set-cookie"));
} }
TEST(HTTPParsersTest, ParseMultipartHeadersContentCharset) { 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