Throttle transfer size updates and relax when it was reported

Currently transfer size updates are reported only when report_raw_headers is set.
This CL relaxes that requirement and checks if either report_raw_headers is set
(to work with devtools) or the renderer has permission to read the resource.

This CL also throttles the transfer size updates to be reported only once per
500 ms per resource.

Bug: 836029
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I7e34a0b0c5fad7e424772c075041c0609dc1b365
Reviewed-on: https://chromium-review.googlesource.com/1050814
Commit-Queue: rajendrant <[email protected]>
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Charlie Harrison <[email protected]>
Reviewed-by: Ɓukasz Anforowicz <[email protected]>
Reviewed-by: Andrey Kosyakov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#572064}
diff --git a/content/browser/loader/mojo_async_resource_handler.cc b/content/browser/loader/mojo_async_resource_handler.cc
index 55c8d8e0..4910201 100644
--- a/content/browser/loader/mojo_async_resource_handler.cc
+++ b/content/browser/loader/mojo_async_resource_handler.cc
@@ -38,6 +38,21 @@
 
 constexpr size_t kMaxChunkSize = 32 * 1024;
 
+// Time between sending the transfer size updates to renderer. This threshold is
+// chosen as a compromise between sending too frequent updates and the limit its
+// consumers (DevTools and page load metrics) expect.
+constexpr base::TimeDelta kTransferSizeReportInterval =
+    base::TimeDelta::FromMilliseconds(500);
+
+bool ShouldReportTransferSize(
+    const ResourceRequestInfoImpl* resource_request_info) {
+  // Transfer size is reported only when report_raw_headers is set or the
+  // renderer is allowed to receive the resource response metadata (e.g. by
+  // Cross-Origin Read Blocking).
+  return resource_request_info->ShouldReportRawHeaders() ||
+         !resource_request_info->blocked_response_from_reaching_renderer();
+}
+
 }  // namespace
 
 // This class is for sharing the ownership of a ScopedDataPipeProducerHandle
@@ -303,11 +318,15 @@
     return;
   }
 
-  const ResourceRequestInfoImpl* info = GetRequestInfo();
-  if (info->ShouldReportRawHeaders()) {
+  if (ShouldReportTransferSize(GetRequestInfo()) &&
+      (time_transfer_size_next_report_.is_null() ||
+       time_transfer_size_next_report_ <= base::TimeTicks::Now())) {
     auto transfer_size_diff = CalculateRecentlyReceivedBytes();
-    if (transfer_size_diff > 0)
+    if (transfer_size_diff > 0) {
       url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+      time_transfer_size_next_report_ =
+          base::TimeTicks::Now() + kTransferSizeReportInterval;
+    }
   }
 
   if (response_body_consumer_handle_.is_valid()) {
@@ -487,6 +506,12 @@
     loader_status.ssl_info = request()->ssl_info();
   }
 
+  if (ShouldReportTransferSize(GetRequestInfo())) {
+    auto transfer_size_diff = CalculateRecentlyReceivedBytes();
+    if (transfer_size_diff > 0)
+      url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+  }
+
   url_loader_client_->OnComplete(loader_status);
   controller->Resume();
 }