Commit b2c3c3e8 authored by Yutaka Hirano's avatar Yutaka Hirano Committed by Commit Bot

[fetch keepalive] Introduce limit on the size of URL and headers

This is (3) in
https://docs.google.com/document/d/1sMG4xAT-myWtFaNa0kuLjRqsyxSy12ahgRIbffy1Bxk/.

Bug: 1018050
Change-Id: Ib265bd86153842b4f90c836fb0b06d200e94a787
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1880361
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709882}
parent ad33ba0d
...@@ -96,7 +96,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor { ...@@ -96,7 +96,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
std::move(request), 0 /* options */, resource_request, std::move(request), 0 /* options */, resource_request,
std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS, &params, std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
0, /* request_id */ 0, /* request_id */
resource_scheduler_client_, nullptr /* keepalive_statistics_recorder */, 0 /* keepalive_request_size */, resource_scheduler_client_,
nullptr /* keepalive_statistics_recorder */,
nullptr /* network_usage_accumulator */, nullptr /* header_client */, nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */); nullptr /* origin_policy_manager */);
} }
......
...@@ -51,10 +51,12 @@ void KeepaliveStatisticsRecorder::Unregister(int process_id) { ...@@ -51,10 +51,12 @@ void KeepaliveStatisticsRecorder::Unregister(int process_id) {
--it->second.num_registrations; --it->second.num_registrations;
} }
void KeepaliveStatisticsRecorder::OnLoadStarted(int process_id) { void KeepaliveStatisticsRecorder::OnLoadStarted(int process_id,
int request_size) {
auto it = per_process_records_.find(process_id); auto it = per_process_records_.find(process_id);
if (it != per_process_records_.end()) { if (it != per_process_records_.end()) {
++it->second.num_inflight_requests; ++it->second.num_inflight_requests;
it->second.total_request_size += request_size;
if (it->second.peak_inflight_requests < it->second.num_inflight_requests) { if (it->second.peak_inflight_requests < it->second.num_inflight_requests) {
it->second.peak_inflight_requests = it->second.num_inflight_requests; it->second.peak_inflight_requests = it->second.num_inflight_requests;
if (!base::FeatureList::IsEnabled(features::kDisableKeepaliveFetch)) { if (!base::FeatureList::IsEnabled(features::kDisableKeepaliveFetch)) {
...@@ -75,10 +77,14 @@ void KeepaliveStatisticsRecorder::OnLoadStarted(int process_id) { ...@@ -75,10 +77,14 @@ void KeepaliveStatisticsRecorder::OnLoadStarted(int process_id) {
} }
} }
void KeepaliveStatisticsRecorder::OnLoadFinished(int process_id) { void KeepaliveStatisticsRecorder::OnLoadFinished(int process_id,
int request_size) {
auto it = per_process_records_.find(process_id); auto it = per_process_records_.find(process_id);
if (it != per_process_records_.end()) if (it != per_process_records_.end()) {
--it->second.num_inflight_requests; --it->second.num_inflight_requests;
DCHECK_GE(it->second.total_request_size, request_size);
it->second.total_request_size -= request_size;
}
--num_inflight_requests_; --num_inflight_requests_;
} }
...@@ -90,6 +96,14 @@ int KeepaliveStatisticsRecorder::NumInflightRequestsPerProcess( ...@@ -90,6 +96,14 @@ int KeepaliveStatisticsRecorder::NumInflightRequestsPerProcess(
return it->second.num_inflight_requests; return it->second.num_inflight_requests;
} }
int KeepaliveStatisticsRecorder::GetTotalRequestSizePerProcess(
int process_id) const {
auto it = per_process_records_.find(process_id);
if (it == per_process_records_.end())
return 0;
return it->second.total_request_size;
}
bool KeepaliveStatisticsRecorder::HasRecordForProcess(int process_id) const { bool KeepaliveStatisticsRecorder::HasRecordForProcess(int process_id) const {
auto it = per_process_records_.find(process_id); auto it = per_process_records_.find(process_id);
if (it != per_process_records_.end()) { if (it != per_process_records_.end()) {
......
...@@ -23,6 +23,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder ...@@ -23,6 +23,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder
int num_registrations = 1; int num_registrations = 1;
int num_inflight_requests = 0; int num_inflight_requests = 0;
int peak_inflight_requests = 0; int peak_inflight_requests = 0;
int total_request_size = 0;
}; };
KeepaliveStatisticsRecorder(); KeepaliveStatisticsRecorder();
...@@ -36,9 +37,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder ...@@ -36,9 +37,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder
void Unregister(int process_id); void Unregister(int process_id);
// Called when a request with keepalive set starts. // Called when a request with keepalive set starts.
void OnLoadStarted(int process_id); void OnLoadStarted(int process_id, int request_size);
// Called when a request with keepalive set finishes. // Called when a request with keepalive set finishes.
void OnLoadFinished(int process_id); void OnLoadFinished(int process_id, int request_size);
const std::unordered_map<int, PerProcessStats>& per_process_records() const { const std::unordered_map<int, PerProcessStats>& per_process_records() const {
return per_process_records_; return per_process_records_;
...@@ -46,6 +47,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder ...@@ -46,6 +47,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) KeepaliveStatisticsRecorder
// Returns true iff. number of Register calls > Unregister calls. // Returns true iff. number of Register calls > Unregister calls.
bool HasRecordForProcess(int process_id) const; bool HasRecordForProcess(int process_id) const;
int NumInflightRequestsPerProcess(int process_id) const; int NumInflightRequestsPerProcess(int process_id) const;
int GetTotalRequestSizePerProcess(int process_id) const;
int num_inflight_requests() const { return num_inflight_requests_; } int num_inflight_requests() const { return num_inflight_requests_; }
int peak_inflight_requests() const { return peak_inflight_requests_; } int peak_inflight_requests() const { return peak_inflight_requests_; }
......
...@@ -80,7 +80,7 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) { ...@@ -80,7 +80,7 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) {
constexpr int process = 4; constexpr int process = 4;
r.Register(process); r.Register(process);
r.OnLoadStarted(process); r.OnLoadStarted(process, 12);
{ {
const auto& map = r.per_process_records(); const auto& map = r.per_process_records();
EXPECT_EQ(1u, map.size()); EXPECT_EQ(1u, map.size());
...@@ -89,12 +89,13 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) { ...@@ -89,12 +89,13 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) {
EXPECT_EQ(1, it->second.num_registrations); EXPECT_EQ(1, it->second.num_registrations);
EXPECT_EQ(1, it->second.num_inflight_requests); EXPECT_EQ(1, it->second.num_inflight_requests);
EXPECT_EQ(1, it->second.peak_inflight_requests); EXPECT_EQ(1, it->second.peak_inflight_requests);
EXPECT_EQ(12, it->second.total_request_size);
EXPECT_EQ(1, r.num_inflight_requests()); EXPECT_EQ(1, r.num_inflight_requests());
EXPECT_EQ(1, r.peak_inflight_requests()); EXPECT_EQ(1, r.peak_inflight_requests());
} }
r.OnLoadFinished(process); r.OnLoadFinished(process, 12);
{ {
const auto& map = r.per_process_records(); const auto& map = r.per_process_records();
EXPECT_EQ(1u, map.size()); EXPECT_EQ(1u, map.size());
...@@ -103,6 +104,7 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) { ...@@ -103,6 +104,7 @@ TEST(KeepaliveStatisticsRecorderTest, IssueOneRequest) {
EXPECT_EQ(1, it->second.num_registrations); EXPECT_EQ(1, it->second.num_registrations);
EXPECT_EQ(0, it->second.num_inflight_requests); EXPECT_EQ(0, it->second.num_inflight_requests);
EXPECT_EQ(1, it->second.peak_inflight_requests); EXPECT_EQ(1, it->second.peak_inflight_requests);
EXPECT_EQ(0, it->second.total_request_size);
EXPECT_EQ(0, r.num_inflight_requests()); EXPECT_EQ(0, r.num_inflight_requests());
EXPECT_EQ(1, r.peak_inflight_requests()); EXPECT_EQ(1, r.peak_inflight_requests());
...@@ -121,23 +123,23 @@ TEST(KeepaliveStatisticsRecorderTest, IssueRequests) { ...@@ -121,23 +123,23 @@ TEST(KeepaliveStatisticsRecorderTest, IssueRequests) {
r.Register(process2); r.Register(process2);
r.Register(process2); r.Register(process2);
r.OnLoadStarted(process1); r.OnLoadStarted(process1, 13);
r.OnLoadStarted(process1); r.OnLoadStarted(process1, 5);
r.OnLoadStarted(process2); r.OnLoadStarted(process2, 8);
r.OnLoadStarted(process2); r.OnLoadStarted(process2, 4);
r.OnLoadStarted(process2); r.OnLoadStarted(process2, 82);
r.OnLoadStarted(process2); r.OnLoadStarted(process2, 3);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 1);
r.OnLoadFinished(process2); r.OnLoadFinished(process2, 4);
r.OnLoadFinished(process2); r.OnLoadFinished(process2, 8);
r.OnLoadFinished(process2); r.OnLoadFinished(process2, 82);
r.OnLoadStarted(process2); r.OnLoadStarted(process2, 13);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 4);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 5);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 6);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 7);
r.OnLoadStarted(no_process); r.OnLoadStarted(no_process, 8);
r.OnLoadFinished(no_process); r.OnLoadFinished(no_process, 6);
const auto& map = r.per_process_records(); const auto& map = r.per_process_records();
EXPECT_EQ(2u, map.size()); EXPECT_EQ(2u, map.size());
...@@ -147,11 +149,13 @@ TEST(KeepaliveStatisticsRecorderTest, IssueRequests) { ...@@ -147,11 +149,13 @@ TEST(KeepaliveStatisticsRecorderTest, IssueRequests) {
EXPECT_EQ(3, it1->second.num_registrations); EXPECT_EQ(3, it1->second.num_registrations);
EXPECT_EQ(2, it1->second.num_inflight_requests); EXPECT_EQ(2, it1->second.num_inflight_requests);
EXPECT_EQ(2, it1->second.peak_inflight_requests); EXPECT_EQ(2, it1->second.peak_inflight_requests);
EXPECT_EQ(18, it1->second.total_request_size);
ASSERT_NE(it2, map.end()); ASSERT_NE(it2, map.end());
EXPECT_EQ(2, it2->second.num_registrations); EXPECT_EQ(2, it2->second.num_registrations);
EXPECT_EQ(2, it2->second.num_inflight_requests); EXPECT_EQ(2, it2->second.num_inflight_requests);
EXPECT_EQ(4, it2->second.peak_inflight_requests); EXPECT_EQ(4, it2->second.peak_inflight_requests);
EXPECT_EQ(16, it2->second.total_request_size);
EXPECT_EQ(9, r.num_inflight_requests()); EXPECT_EQ(9, r.num_inflight_requests());
EXPECT_EQ(10, r.peak_inflight_requests()); EXPECT_EQ(10, r.peak_inflight_requests());
...@@ -162,12 +166,12 @@ TEST(KeepaliveStatisticsRecorderTest, ProcessReuse) { ...@@ -162,12 +166,12 @@ TEST(KeepaliveStatisticsRecorderTest, ProcessReuse) {
constexpr int process = 2; constexpr int process = 2;
r.Register(process); r.Register(process);
r.OnLoadStarted(process); r.OnLoadStarted(process, 1);
r.OnLoadStarted(process); r.OnLoadStarted(process, 2);
r.OnLoadStarted(process); r.OnLoadStarted(process, 3);
r.OnLoadFinished(process); r.OnLoadFinished(process, 2);
r.OnLoadFinished(process); r.OnLoadFinished(process, 3);
r.OnLoadFinished(process); r.OnLoadFinished(process, 1);
r.Unregister(process); r.Unregister(process);
r.Register(process); r.Register(process);
...@@ -178,6 +182,7 @@ TEST(KeepaliveStatisticsRecorderTest, ProcessReuse) { ...@@ -178,6 +182,7 @@ TEST(KeepaliveStatisticsRecorderTest, ProcessReuse) {
EXPECT_EQ(1, it->second.num_registrations); EXPECT_EQ(1, it->second.num_registrations);
EXPECT_EQ(0, it->second.num_inflight_requests); EXPECT_EQ(0, it->second.num_inflight_requests);
EXPECT_EQ(0, it->second.peak_inflight_requests); EXPECT_EQ(0, it->second.peak_inflight_requests);
EXPECT_EQ(0, it->second.total_request_size);
} }
} // namespace } // namespace
......
...@@ -330,6 +330,7 @@ URLLoader::URLLoader( ...@@ -330,6 +330,7 @@ URLLoader::URLLoader(
const net::NetworkTrafficAnnotationTag& traffic_annotation, const net::NetworkTrafficAnnotationTag& traffic_annotation,
const mojom::URLLoaderFactoryParams* factory_params, const mojom::URLLoaderFactoryParams* factory_params,
uint32_t request_id, uint32_t request_id,
int keepalive_request_size,
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client, scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder, base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator, base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
...@@ -346,6 +347,7 @@ URLLoader::URLLoader( ...@@ -346,6 +347,7 @@ URLLoader::URLLoader(
factory_params_(factory_params), factory_params_(factory_params),
render_frame_id_(request.render_frame_id), render_frame_id_(request.render_frame_id),
request_id_(request_id), request_id_(request_id),
keepalive_request_size_(keepalive_request_size),
keepalive_(request.keepalive), keepalive_(request.keepalive),
do_not_prompt_for_login_(request.do_not_prompt_for_login), do_not_prompt_for_login_(request.do_not_prompt_for_login),
binding_(this, std::move(url_loader_request)), binding_(this, std::move(url_loader_request)),
...@@ -473,21 +475,9 @@ URLLoader::URLLoader( ...@@ -473,21 +475,9 @@ URLLoader::URLLoader(
base::Bind(&URLLoader::SetRawResponseHeaders, base::Unretained(this))); base::Bind(&URLLoader::SetRawResponseHeaders, base::Unretained(this)));
} }
if (keepalive_ && keepalive_statistics_recorder_) if (keepalive_ && keepalive_statistics_recorder_) {
keepalive_statistics_recorder_->OnLoadStarted(factory_params_->process_id); keepalive_statistics_recorder_->OnLoadStarted(factory_params_->process_id,
keepalive_request_size_);
if (keepalive_) {
const size_t url_size = request.url.spec().size();
size_t headers_size = 0;
for (const auto& pair : merged_headers.GetHeaderVector()) {
headers_size += (pair.key.size() + pair.value.size());
}
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.UrlSize", url_size);
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.HeadersSize",
headers_size);
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.UrlPlusHeadersSize",
url_size + headers_size);
} }
// Resolve elements from request_body and prepare upload data. // Resolve elements from request_body and prepare upload data.
...@@ -676,8 +666,10 @@ void URLLoader::ScheduleStart() { ...@@ -676,8 +666,10 @@ void URLLoader::ScheduleStart() {
URLLoader::~URLLoader() { URLLoader::~URLLoader() {
RecordBodyReadFromNetBeforePausedIfNeeded(); RecordBodyReadFromNetBeforePausedIfNeeded();
if (keepalive_ && keepalive_statistics_recorder_) if (keepalive_ && keepalive_statistics_recorder_) {
keepalive_statistics_recorder_->OnLoadFinished(factory_params_->process_id); keepalive_statistics_recorder_->OnLoadFinished(factory_params_->process_id,
keepalive_request_size_);
}
} }
// static // static
......
...@@ -80,6 +80,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -80,6 +80,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
const net::NetworkTrafficAnnotationTag& traffic_annotation, const net::NetworkTrafficAnnotationTag& traffic_annotation,
const mojom::URLLoaderFactoryParams* factory_params, const mojom::URLLoaderFactoryParams* factory_params,
uint32_t request_id, uint32_t request_id,
int keepalive_request_size,
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client, scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder, base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator, base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
...@@ -263,6 +264,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -263,6 +264,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
int render_frame_id_; int render_frame_id_;
uint32_t request_id_; uint32_t request_id_;
const int keepalive_request_size_;
const bool keepalive_; const bool keepalive_;
const bool do_not_prompt_for_login_; const bool do_not_prompt_for_login_;
std::unique_ptr<net::URLRequest> url_request_; std::unique_ptr<net::URLRequest> url_request_;
......
...@@ -26,6 +26,7 @@ namespace network { ...@@ -26,6 +26,7 @@ namespace network {
constexpr int URLLoaderFactory::kMaxKeepaliveConnections; constexpr int URLLoaderFactory::kMaxKeepaliveConnections;
constexpr int URLLoaderFactory::kMaxKeepaliveConnectionsPerProcess; constexpr int URLLoaderFactory::kMaxKeepaliveConnectionsPerProcess;
constexpr int URLLoaderFactory::kMaxTotalKeepaliveRequestSize;
URLLoaderFactory::URLLoaderFactory( URLLoaderFactory::URLLoaderFactory(
NetworkContext* context, NetworkContext* context,
...@@ -99,13 +100,36 @@ void URLLoaderFactory::CreateLoaderAndStart( ...@@ -99,13 +100,36 @@ void URLLoaderFactory::CreateLoaderAndStart(
context_->network_service()->network_usage_accumulator()->AsWeakPtr(); context_->network_service()->network_usage_accumulator()->AsWeakPtr();
} }
int keepalive_request_size = 0;
bool exhausted = false; bool exhausted = false;
if (url_request.keepalive && keepalive_statistics_recorder) { if (url_request.keepalive && keepalive_statistics_recorder) {
const size_t url_size = url_request.url.spec().size();
size_t headers_size = 0;
net::HttpRequestHeaders merged_headers = url_request.headers;
merged_headers.MergeFrom(url_request.cors_exempt_headers);
for (const auto& pair : merged_headers.GetHeaderVector()) {
headers_size += (pair.key.size() + pair.value.size());
}
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.UrlSize", url_size);
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.HeadersSize",
headers_size);
UMA_HISTOGRAM_COUNTS_10000("Net.KeepaliveRequest.UrlPlusHeadersSize",
url_size + headers_size);
keepalive_request_size = url_size + headers_size;
const auto& recorder = *keepalive_statistics_recorder; const auto& recorder = *keepalive_statistics_recorder;
if (recorder.num_inflight_requests() >= kMaxKeepaliveConnections) if (recorder.num_inflight_requests() >= kMaxKeepaliveConnections) {
exhausted = true;
} else if (recorder.NumInflightRequestsPerProcess(params_->process_id) >=
kMaxKeepaliveConnectionsPerProcess) {
exhausted = true; exhausted = true;
if (recorder.NumInflightRequestsPerProcess(params_->process_id) >= } else if (recorder.GetTotalRequestSizePerProcess(params_->process_id) +
kMaxKeepaliveConnectionsPerProcess) { keepalive_request_size >
kMaxTotalKeepaliveRequestSize) {
exhausted = true; exhausted = true;
} }
} }
...@@ -129,8 +153,8 @@ void URLLoaderFactory::CreateLoaderAndStart( ...@@ -129,8 +153,8 @@ void URLLoaderFactory::CreateLoaderAndStart(
base::Unretained(cors_url_loader_factory_)), base::Unretained(cors_url_loader_factory_)),
std::move(request), options, url_request, std::move(client), std::move(request), options, url_request, std::move(client),
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation), static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
params_.get(), request_id, resource_scheduler_client_, params_.get(), request_id, keepalive_request_size,
std::move(keepalive_statistics_recorder), resource_scheduler_client_, std::move(keepalive_statistics_recorder),
std::move(network_usage_accumulator), std::move(network_usage_accumulator),
header_client_.is_bound() ? header_client_.get() : nullptr, header_client_.is_bound() ? header_client_.get() : nullptr,
context_->origin_policy_manager()); context_->origin_policy_manager());
......
...@@ -63,6 +63,7 @@ class URLLoaderFactory : public mojom::URLLoaderFactory { ...@@ -63,6 +63,7 @@ class URLLoaderFactory : public mojom::URLLoaderFactory {
static constexpr int kMaxKeepaliveConnections = 2048; static constexpr int kMaxKeepaliveConnections = 2048;
static constexpr int kMaxKeepaliveConnectionsPerProcess = 256; static constexpr int kMaxKeepaliveConnectionsPerProcess = 256;
static constexpr int kMaxTotalKeepaliveRequestSize = 256 * 1024;
private: private:
// The NetworkContext that indirectly owns |this|. // The NetworkContext that indirectly owns |this|.
......
This diff is collapsed.
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