// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"

#include <algorithm>
#include <limits>
#include <utility>

#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
#include "net/base/network_change_notifier.h"
#include "net/base/proxy_server.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"

namespace data_reduction_proxy {

namespace {

// Values of the UMA DataReductionProxy.Protocol.AcceptTransform histogram
// defined in metrics/histograms/histograms.xml. This enum must remain
// synchronized with DataReductionProxyProtocolAcceptTransformEvent in
// tools/metrics/histograms/enums.xml.
enum AcceptTransformEvent {
  LITE_PAGE_REQUESTED = 0,
  LITE_PAGE_TRANSFORM_RECEIVED = 1,
  EMPTY_IMAGE_POLICY_DIRECTIVE_RECEIVED = 2,
  EMPTY_IMAGE_REQUESTED = 3,
  EMPTY_IMAGE_TRANSFORM_RECEIVED = 4,
  COMPRESSED_VIDEO_REQUESTED = 5,
  IDENTITY_TRANSFORM_REQUESTED = 6,
  IDENTITY_TRANSFORM_RECEIVED = 7,
  COMPRESSED_VIDEO_RECEIVED = 8,
  UNKNOWN_TRANSFORM_RECEIVED = 9,
  ACCEPT_TRANSFORM_EVENT_BOUNDARY
};

// Records the occurrence of |sample| in |name| histogram. UMA macros are not
// used because the |name| is not static.
void RecordNewContentLengthHistogram(const std::string& name, int64_t sample) {
  base::UmaHistogramCustomCounts(
      name, sample,
      1,          // Minimum sample size in bytes.
      128 << 20,  // Maximum sample size in bytes. 128MB is chosen because some
                  // video requests can be very large.
      50          // Bucket count.
      );
}

void RecordNewContentLengthHistograms(
    const char* prefix,
    bool is_https,
    bool is_video,
    DataReductionProxyRequestType request_type,
    int64_t content_length) {
  const char* connection_type = is_https ? ".Https" : ".Http";
  const char* suffix = ".Other";
  // TODO(crbug.com/726411): Differentiate between a bypass and a disabled
  // proxy config.
  switch (request_type) {
    case VIA_DATA_REDUCTION_PROXY:
      suffix = ".ViaDRP";
      break;
    case HTTPS:
    case DIRECT_HTTP:
      suffix = ".Direct";
      break;
    case SHORT_BYPASS:
    case LONG_BYPASS:
      suffix = ".BypassedDRP";
      break;
    case UPDATE:
    case UNKNOWN_TYPE:
    default:
      // Value already properly initialized to ".Other"
      break;
  }
  // Record a histogram for all traffic, including video.
  RecordNewContentLengthHistogram(
      base::StringPrintf("%s%s%s", prefix, connection_type, suffix),
      content_length);
  if (is_video) {
    RecordNewContentLengthHistogram(
        base::StringPrintf("%s%s%s.Video", prefix, connection_type, suffix),
        content_length);
  }
}

// |received_content_length| is the number of prefilter bytes received.
// |original_content_length| is the length of resource if accessed directly
// without data saver proxy. |freshness_lifetime| specifies how long the
// resource will be fresh for.
void RecordContentLengthHistograms(bool is_https,
                                   bool is_video,
                                   int64_t received_content_length,
                                   int64_t original_content_length,
                                   const base::TimeDelta& freshness_lifetime,
                                   DataReductionProxyRequestType request_type) {
  // Add the current resource to these histograms only when the content length
  // is valid.
  if (original_content_length >= 0) {
    // This is only used locally in integration testing.
    LOCAL_HISTOGRAM_COUNTS_1000000("Net.HttpOriginalContentLengthWithValidOCL",
                                   original_content_length);
    UMA_HISTOGRAM_COUNTS_1M("Net.HttpContentLengthDifferenceWithValidOCL",
                            original_content_length - received_content_length);
  } else {
    // Presume the original content length is the same as the received content
    // length.
    original_content_length = received_content_length;
  }
  UMA_HISTOGRAM_COUNTS_1M("Net.HttpContentLength", received_content_length);

  // Record the new histograms broken down by HTTP/HTTPS and video/non-video
  RecordNewContentLengthHistograms("Net.HttpContentLengthV2", is_https,
                                   is_video, request_type,
                                   received_content_length);
  RecordNewContentLengthHistograms("Net.HttpOriginalContentLengthV2", is_https,
                                   is_video, request_type,
                                   original_content_length);

  UMA_HISTOGRAM_COUNTS_1M("Net.HttpOriginalContentLength",
                          original_content_length);
  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
                              freshness_lifetime.InSeconds(),
                              base::TimeDelta::FromHours(1).InSeconds(),
                              base::TimeDelta::FromDays(30).InSeconds(), 100);
}

void RecordAcceptTransformEvent(AcceptTransformEvent event) {
  UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.Protocol.AcceptTransform",
                            event, ACCEPT_TRANSFORM_EVENT_BOUNDARY);
}

void RecordAcceptTransformSentUMA(
    const net::HttpRequestHeaders& request_headers) {
  switch (ParseRequestTransform(request_headers)) {
    case TRANSFORM_LITE_PAGE:
      RecordAcceptTransformEvent(LITE_PAGE_REQUESTED);
      break;
    case TRANSFORM_EMPTY_IMAGE:
      RecordAcceptTransformEvent(EMPTY_IMAGE_REQUESTED);
      break;
    case TRANSFORM_COMPRESSED_VIDEO:
      RecordAcceptTransformEvent(COMPRESSED_VIDEO_REQUESTED);
      break;
    case TRANSFORM_IDENTITY:
      RecordAcceptTransformEvent(IDENTITY_TRANSFORM_REQUESTED);
      break;
    case TRANSFORM_NONE:
      break;
    case TRANSFORM_PAGE_POLICIES_EMPTY_IMAGE:
    case TRANSFORM_UNKNOWN:
      NOTREACHED();
      break;
  }
}

void RecordAcceptTransformReceivedUMA(const net::URLRequest& request) {
  net::HttpResponseHeaders* response_headers = request.response_headers();
  if (!response_headers) {
    return;
  }

  switch (ParseResponseTransform(*response_headers)) {
    case TRANSFORM_UNKNOWN:
      RecordAcceptTransformEvent(UNKNOWN_TRANSFORM_RECEIVED);
      break;
    case TRANSFORM_LITE_PAGE:
      RecordAcceptTransformEvent(LITE_PAGE_TRANSFORM_RECEIVED);
      break;
    case TRANSFORM_PAGE_POLICIES_EMPTY_IMAGE:
      RecordAcceptTransformEvent(EMPTY_IMAGE_POLICY_DIRECTIVE_RECEIVED);
      break;
    case TRANSFORM_EMPTY_IMAGE:
      RecordAcceptTransformEvent(EMPTY_IMAGE_TRANSFORM_RECEIVED);
      break;
    case TRANSFORM_IDENTITY:
      RecordAcceptTransformEvent(IDENTITY_TRANSFORM_RECEIVED);
      break;
    case TRANSFORM_COMPRESSED_VIDEO:
      RecordAcceptTransformEvent(COMPRESSED_VIDEO_RECEIVED);
      break;
    case TRANSFORM_NONE:
      break;
  }
}

// Verifies that the chrome proxy related request headers are set correctly.
// |via_chrome_proxy| is true if the request is being fetched via Chrome Data
// Saver proxy.
void VerifyHttpRequestHeaders(bool via_chrome_proxy,
                              const net::HttpRequestHeaders& headers) {
  // If holdback is enabled, then |via_chrome_proxy| should be false.
  DCHECK(!params::IsIncludedInHoldbackFieldTrial() || !via_chrome_proxy);

  if (via_chrome_proxy) {
    DCHECK(headers.HasHeader(chrome_proxy_ect_header()));
    std::string chrome_proxy_header_value;
    DCHECK(
        headers.GetHeader(chrome_proxy_header(), &chrome_proxy_header_value));
    // Check that only 1 "exp" directive is sent.
    DCHECK_GT(3u, base::SplitStringUsingSubstr(chrome_proxy_header_value,
                                               "exp=", base::TRIM_WHITESPACE,
                                               base::SPLIT_WANT_ALL)
                      .size());
    // Silence unused variable warning in release builds.
    (void)chrome_proxy_header_value;
  } else {
    DCHECK(!headers.HasHeader(chrome_proxy_header()));
    DCHECK(!headers.HasHeader(chrome_proxy_accept_transform_header()));
    DCHECK(!headers.HasHeader(chrome_proxy_ect_header()));
  }
}

// If the response is the entire resource, then the renderer won't show a
// placeholder. This should match the behavior in blink::ImageResource.
bool IsEntireResource(const net::HttpResponseHeaders* response_headers) {
  if (!response_headers || response_headers->response_code() != 206)
    return true;

  int64_t first, last, length;
  return response_headers->GetContentRangeFor206(&first, &last, &length) &&
         first == 0 && last + 1 == length;
}

}  // namespace

DataReductionProxyNetworkDelegate::DataReductionProxyNetworkDelegate(
    std::unique_ptr<net::NetworkDelegate> network_delegate,
    DataReductionProxyConfig* config,
    DataReductionProxyRequestOptions* request_options,
    const DataReductionProxyConfigurator* configurator)
    : LayeredNetworkDelegate(std::move(network_delegate)),
      data_reduction_proxy_config_(config),
      data_reduction_proxy_bypass_stats_(nullptr),
      data_reduction_proxy_request_options_(request_options),
      data_reduction_proxy_io_data_(nullptr),
      configurator_(configurator) {
  DCHECK(data_reduction_proxy_config_);
  DCHECK(data_reduction_proxy_request_options_);
  DCHECK(configurator_);
}

DataReductionProxyNetworkDelegate::~DataReductionProxyNetworkDelegate() {
}

void DataReductionProxyNetworkDelegate::InitIODataAndUMA(
    DataReductionProxyIOData* io_data,
    DataReductionProxyBypassStats* bypass_stats) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(bypass_stats);
  data_reduction_proxy_io_data_ = io_data;
  data_reduction_proxy_bypass_stats_ = bypass_stats;
}

void DataReductionProxyNetworkDelegate::OnBeforeStartTransactionInternal(
    net::URLRequest* request,
    net::HttpRequestHeaders* headers) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (!data_reduction_proxy_io_data_)
    return;
  if (!data_reduction_proxy_io_data_->IsEnabled())
    return;

  if (request->url().SchemeIsCryptographic() ||
      !request->url().SchemeIsHTTPOrHTTPS()) {
    return;
  }

  if (data_reduction_proxy_io_data_->resource_type_provider()) {
    // Sets content type of |request| in the resource type provider, so it can
    // be later used for determining the proxy that should be used for fetching
    // |request|.
    data_reduction_proxy_io_data_->resource_type_provider()->SetContentType(
        *request);
  }

  if (data_reduction_proxy_io_data_->lofi_decider()) {
    data_reduction_proxy_io_data_->lofi_decider()
        ->MaybeSetAcceptTransformHeader(*request, headers);
  }

  MaybeAddChromeProxyECTHeader(headers, *request);
}

void DataReductionProxyNetworkDelegate::OnBeforeSendHeadersInternal(
    net::URLRequest* request,
    const net::ProxyInfo& proxy_info,
    const net::ProxyRetryInfoMap& proxy_retry_info,
    net::HttpRequestHeaders* headers) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(data_reduction_proxy_config_);
  DCHECK(request);

  // If there was a redirect or request bypass, use the same page ID for both
  // requests. As long as the session ID has not changed. Re-issued requests
  // and client redirects will be assigned a new page ID as they are different
  // URLRequests.
  DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
  base::Optional<uint64_t> page_id;
  if (data && data->session_key() ==
                  data_reduction_proxy_request_options_->GetSecureSession()) {
    page_id = data->page_id();
  }
  // Always persist data's |request_info| since it tracks connection pingback
  // data for redirects on main frame requests. It should include re-issued
  // requests and client redirects.
  std::vector<DataReductionProxyData::RequestInfo> request_info;
  if (data)
    request_info = data->TakeRequestInfo();

  // Reset |request|'s DataReductionProxyData.
  DataReductionProxyData::ClearData(request);
  data = nullptr;

  bool using_data_reduction_proxy = true;
  // The following checks rule out direct, invalid, and other connection types.
  if (!proxy_info.is_http() && !proxy_info.is_https() &&
      !proxy_info.is_quic()) {
    using_data_reduction_proxy = false;
  } else if (proxy_info.proxy_server().host_port_pair().IsEmpty()) {
    using_data_reduction_proxy = false;
  } else if (!data_reduction_proxy_config_->FindConfiguredDataReductionProxy(
                 proxy_info.proxy_server())) {
    using_data_reduction_proxy = false;
  }

  bool is_holdback_eligible = false;

  if (params::IsIncludedInHoldbackFieldTrial() &&
      WasEligibleWithoutHoldback(*request, proxy_info, proxy_retry_info)) {
    is_holdback_eligible = true;
  }
  // If holdback is enabled, |using_data_reduction_proxy| must be false.
  DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
         !using_data_reduction_proxy);

  // For the holdback field trial, still log UMA and send the pingback as if
  // the proxy were used.
  if (is_holdback_eligible || using_data_reduction_proxy) {
    // Retrieves DataReductionProxyData from a request, creating a new instance
    // if needed.
    data = DataReductionProxyData::GetDataAndCreateIfNecessary(request);
    data->set_used_data_reduction_proxy(true);
    // Only set GURL, NQE and session key string for main frame requests since
    // they are not needed for sub-resources.
    if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) {
      data->set_session_key(
          data_reduction_proxy_request_options_->GetSecureSession());
      data->set_request_url(request->url());
      if (request->context()->network_quality_estimator()) {
        data->set_effective_connection_type(request->context()
                                                ->network_quality_estimator()
                                                ->GetEffectiveConnectionType());
      }
      data->set_connection_type(
          net::NetworkChangeNotifier::GetConnectionType());
      // Generate a page ID for main frame requests that don't already have one.
      // TODO(ryansturm): remove LOAD_MAIN_FRAME_DEPRECATED from d_r_p.
      // crbug.com/709621
      if (!page_id) {
        page_id = data_reduction_proxy_request_options_->GeneratePageId();
      }
      data->set_page_id(page_id.value());
      data->set_request_info(std::move(request_info));
    }
  }

  LoFiDecider* lofi_decider = nullptr;
  if (data_reduction_proxy_io_data_)
    lofi_decider = data_reduction_proxy_io_data_->lofi_decider();

  if (!using_data_reduction_proxy) {
    if (lofi_decider) {
      // If not using the data reduction proxy, strip the
      // Chrome-Proxy-Accept-Transform header.
      lofi_decider->RemoveAcceptTransformHeader(headers);
    }
    RemoveChromeProxyECTHeader(headers);
    headers->RemoveHeader(chrome_proxy_header());
    VerifyHttpRequestHeaders(false, *headers);
    return;
  }

  DCHECK(data);
  data->set_lofi_requested(
      lofi_decider ? lofi_decider->ShouldRecordLoFiUMA(*request) : false);
  MaybeAddBrotliToAcceptEncodingHeader(proxy_info, headers, *request);

  data_reduction_proxy_request_options_->AddRequestHeader(headers, page_id);

  VerifyHttpRequestHeaders(true, *headers);
  RecordAcceptTransformSentUMA(*headers);
}

void DataReductionProxyNetworkDelegate::OnBeforeRedirectInternal(
    net::URLRequest* request,
    const GURL& new_location) {
  // Since this is after a redirect response, reset |request|'s
  // DataReductionProxyData, but keep page ID and session.
  // TODO(ryansturm): Change ClearData logic to have persistent and
  // non-persistent (WRT redirects) data.
  // crbug.com/709564
  DataReductionProxyData* data = DataReductionProxyData::GetData(*request);
  base::Optional<uint64_t> page_id;
  if (data && data->session_key() ==
                  data_reduction_proxy_request_options_->GetSecureSession()) {
    page_id = data->page_id();
  }

  // Persist data's |request_info| since it tracks connection pingback data for
  // redirects on main frame requests.
  std::vector<DataReductionProxyData::RequestInfo> request_info;
  if (data)
    request_info = data->TakeRequestInfo();

  DataReductionProxyData::ClearData(request);

  if (page_id) {
    data = DataReductionProxyData::GetDataAndCreateIfNecessary(request);
    data->set_page_id(page_id.value());
    data->set_session_key(
        data_reduction_proxy_request_options_->GetSecureSession());
    data->set_request_info(std::move(request_info));
  }
}

void DataReductionProxyNetworkDelegate::OnCompletedInternal(
    net::URLRequest* request,
    bool started,
    int net_error) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(request);
  DCHECK_NE(net::ERR_IO_PENDING, net_error);
  if (data_reduction_proxy_bypass_stats_)
    data_reduction_proxy_bypass_stats_->OnUrlRequestCompleted(request, started,
                                                              net_error);

  net::HttpRequestHeaders request_headers;
  bool server_lofi = request->response_headers() &&
                     IsEmptyImagePreview(*(request->response_headers()));
  bool will_show_client_lofi_placeholder =
      data_reduction_proxy_io_data_ &&
      data_reduction_proxy_io_data_->lofi_decider() &&
      data_reduction_proxy_io_data_->lofi_decider()->IsClientLoFiImageRequest(
          *request) &&
      // If the response contains the entire resource, then the renderer won't
      // show a placeholder for this image, so don't bother triggering an
      // infobar.
      !IsEntireResource(request->response_headers());

  if ((server_lofi || will_show_client_lofi_placeholder) &&
      data_reduction_proxy_io_data_ &&
      data_reduction_proxy_io_data_->lofi_ui_service()) {
    data_reduction_proxy_io_data_->lofi_ui_service()->OnLoFiReponseReceived(
        *request);
  } else if (data_reduction_proxy_io_data_ && request->response_headers() &&
             IsLitePagePreview(*(request->response_headers()))) {
    RecordLitePageTransformationType(LITE_PAGE);
  } else if (request->GetFullRequestHeaders(&request_headers)) {
    // TODO(bengr): transform processing logic should happen elsewhere.
    std::string header_value;
    request_headers.GetHeader(chrome_proxy_accept_transform_header(),
                              &header_value);
    if (header_value == lite_page_directive())
      RecordLitePageTransformationType(NO_TRANSFORMATION_LITE_PAGE_REQUESTED);
  }

  if (!request->response_info().network_accessed ||
      !request->url().SchemeIsHTTPOrHTTPS() ||
      request->GetTotalReceivedBytes() == 0) {
    return;
  }

  DataReductionProxyRequestType request_type = GetDataReductionProxyRequestType(
      *request, configurator_->GetProxyConfig(), *data_reduction_proxy_config_);

  CalculateAndRecordDataUsage(*request, request_type);
  RecordContentLength(*request, request_type,
                      util::CalculateOCLFromOFCL(*request));
  RecordAcceptTransformReceivedUMA(*request);
}

void DataReductionProxyNetworkDelegate::OnHeadersReceivedInternal(
    net::URLRequest* request,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
    GURL* allowed_unsafe_redirect_url) {
  if (!original_response_headers ||
      original_response_headers->IsRedirect(nullptr))
    return;

  switch (ParseResponseTransform(*original_response_headers)) {
    case TRANSFORM_LITE_PAGE:
      DataReductionProxyData::GetDataAndCreateIfNecessary(request)
          ->set_lite_page_received(true);
      break;
    case TRANSFORM_PAGE_POLICIES_EMPTY_IMAGE:
      DataReductionProxyData::GetDataAndCreateIfNecessary(request)
          ->set_lofi_policy_received(true);
      break;
    case TRANSFORM_EMPTY_IMAGE:
      DataReductionProxyData::GetDataAndCreateIfNecessary(request)
          ->set_lofi_received(true);
      break;
    case TRANSFORM_IDENTITY:
    case TRANSFORM_COMPRESSED_VIDEO:
    case TRANSFORM_NONE:
    case TRANSFORM_UNKNOWN:
      break;
  }
  if (data_reduction_proxy_io_data_ &&
      data_reduction_proxy_io_data_->lofi_decider() &&
      data_reduction_proxy_io_data_->lofi_decider()->IsClientLoFiImageRequest(
          *request)) {
    DataReductionProxyData* data =
        DataReductionProxyData::GetDataAndCreateIfNecessary(request);
    data->set_client_lofi_requested(true);
  }
}

void DataReductionProxyNetworkDelegate::CalculateAndRecordDataUsage(
    const net::URLRequest& request,
    DataReductionProxyRequestType request_type) {
  DCHECK(thread_checker_.CalledOnValidThread());
  int64_t data_used = request.GetTotalReceivedBytes();

  // Estimate how many bytes would have been used if the DataReductionProxy was
  // not used, and record the data usage.
  int64_t original_size = util::EstimateOriginalReceivedBytes(
      request, data_reduction_proxy_io_data_
                   ? data_reduction_proxy_io_data_->lofi_decider()
                   : nullptr);

  std::string mime_type;
  if (request.response_headers())
    request.response_headers()->GetMimeType(&mime_type);

  AccumulateDataUsage(
      data_used, original_size, request_type, mime_type,
      data_use_measurement::DataUseMeasurement::IsUserRequest(request),
      data_use_measurement::DataUseMeasurement::GetContentTypeForRequest(
          request),
      request.traffic_annotation().unique_id_hash_code);

  if (params::IsDataSaverSiteBreakdownUsingPLMEnabled() &&
      data_reduction_proxy_io_data_ &&
      data_reduction_proxy_io_data_->resource_type_provider() &&
      data_reduction_proxy_io_data_->resource_type_provider()
          ->IsNonContentInitiatedRequest(request)) {
    // Record non-content initiated traffic to the Other bucket for data saver
    // site-breakdown.
    data_reduction_proxy_io_data_->UpdateDataUseForHost(
        data_used, original_size, util::GetSiteBreakdownOtherHostName());
  }
}

void DataReductionProxyNetworkDelegate::AccumulateDataUsage(
    int64_t data_used,
    int64_t original_size,
    DataReductionProxyRequestType request_type,
    const std::string& mime_type,
    bool is_user_traffic,
    data_use_measurement::DataUseUserData::DataUseContentType content_type,
    int32_t service_hash_code) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_GE(data_used, 0);
  DCHECK_GE(original_size, 0);
  if (data_reduction_proxy_io_data_) {
    data_reduction_proxy_io_data_->UpdateContentLengths(
        data_used, original_size, data_reduction_proxy_io_data_->IsEnabled(),
        request_type, mime_type, is_user_traffic, content_type,
        service_hash_code);
  }
}

void DataReductionProxyNetworkDelegate::RecordContentLength(
    const net::URLRequest& request,
    DataReductionProxyRequestType request_type,
    int64_t original_content_length) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!request.response_headers() || request.was_cached() ||
      request.received_response_content_length() == 0) {
    return;
  }

  // Record content length histograms for the request.
  base::TimeDelta freshness_lifetime =
      request.response_headers()
          ->GetFreshnessLifetimes(request.response_info().response_time)
          .freshness;

  bool is_https = request.url().SchemeIs("https");
  bool is_video = false;
  std::string mime_type;
  if (request.response_headers()->GetMimeType(&mime_type)) {
    is_video = net::MatchesMimeType("video/*", mime_type);
  }

  RecordContentLengthHistograms(
      is_https, is_video, request.received_response_content_length(),
      original_content_length, freshness_lifetime, request_type);

  if (data_reduction_proxy_io_data_ && data_reduction_proxy_bypass_stats_) {
    // Record BypassedBytes histograms for the request.
    data_reduction_proxy_bypass_stats_->RecordBypassedBytesHistograms(
        request, data_reduction_proxy_io_data_->IsEnabled(),
        configurator_->GetProxyConfig());
  }
}

void DataReductionProxyNetworkDelegate::RecordLitePageTransformationType(
    LitePageTransformationType type) {
  DCHECK(thread_checker_.CalledOnValidThread());
  UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.LoFi.TransformationType", type,
                            LITE_PAGE_TRANSFORMATION_TYPES_INDEX_BOUNDARY);
}

bool DataReductionProxyNetworkDelegate::WasEligibleWithoutHoldback(
    const net::URLRequest& request,
    const net::ProxyInfo& proxy_info,
    const net::ProxyRetryInfoMap& proxy_retry_info) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(proxy_info.is_empty() || proxy_info.is_direct() ||
         !data_reduction_proxy_config_->FindConfiguredDataReductionProxy(
             proxy_info.proxy_server()));
  if (!util::EligibleForDataReductionProxy(proxy_info, request.url(),
                                           request.method())) {
    return false;
  }
  net::ProxyConfig proxy_config =
      data_reduction_proxy_config_->ProxyConfigIgnoringHoldback();
  net::ProxyInfo data_reduction_proxy_info;
  return util::ApplyProxyConfigToProxyInfo(proxy_config, proxy_retry_info,
                                           request.url(),
                                           &data_reduction_proxy_info);
}

void DataReductionProxyNetworkDelegate::MaybeAddBrotliToAcceptEncodingHeader(
    const net::ProxyInfo& proxy_info,
    net::HttpRequestHeaders* request_headers,
    const net::URLRequest& request) const {
  DCHECK(thread_checker_.CalledOnValidThread());

  // This method should be called only when the resolved proxy was a data
  // saver proxy.
  DCHECK(data_reduction_proxy_config_->FindConfiguredDataReductionProxy(
      proxy_info.proxy_server()));
  DCHECK(request.url().is_valid());
  DCHECK(!request.url().SchemeIsCryptographic());
  DCHECK(request.url().SchemeIsHTTPOrHTTPS());

  static const char kBrotli[] = "br";

  if (!request.context()->enable_brotli()) {
    // Verify that Brotli is enabled globally.
    return;
  }

  if (!params::IsBrotliAcceptEncodingEnabled()) {
    // Verify that Brotli is enabled for data reduction proxy.
    return;
  }

  if (!proxy_info.proxy_server().is_https() &&
      !proxy_info.proxy_server().is_quic()) {
    // Brotli encoding can be used only when the proxy server is a secure proxy
    // server.
    return;
  }

  if (!request_headers->HasHeader(net::HttpRequestHeaders::kAcceptEncoding))
    return;

  std::string header_value;
  request_headers->GetHeader(net::HttpRequestHeaders::kAcceptEncoding,
                             &header_value);

  // Brotli should not be already present in the header since the URL is non-
  // cryptographic. This is an approximate check, and would trigger even if the
  // accept-encoding header contains an encoding that has prefix |kBrotli|.
  DCHECK_EQ(std::string::npos, header_value.find(kBrotli));

  request_headers->RemoveHeader(net::HttpRequestHeaders::kAcceptEncoding);
  if (!header_value.empty())
    header_value += ", ";
  header_value += kBrotli;
  request_headers->SetHeader(net::HttpRequestHeaders::kAcceptEncoding,
                             header_value);
}

void DataReductionProxyNetworkDelegate::MaybeAddChromeProxyECTHeader(
    net::HttpRequestHeaders* request_headers,
    const net::URLRequest& request) const {
  DCHECK(thread_checker_.CalledOnValidThread());

  // This method should be called only when the resolved proxy was a data
  // saver proxy.
  DCHECK(request.url().is_valid());
  DCHECK(!request.url().SchemeIsCryptographic());
  DCHECK(request.url().SchemeIsHTTPOrHTTPS());

  if (request_headers->HasHeader(chrome_proxy_ect_header()))
    request_headers->RemoveHeader(chrome_proxy_ect_header());

  if (request.context()->network_quality_estimator()) {
    net::EffectiveConnectionType type = request.context()
                                            ->network_quality_estimator()
                                            ->GetEffectiveConnectionType();
    if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
      DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_LAST, type);
      request_headers->SetHeader(chrome_proxy_ect_header(),
                                 net::GetNameForEffectiveConnectionType(type));
      return;
    }
  }
  request_headers->SetHeader(chrome_proxy_ect_header(),
                             net::GetNameForEffectiveConnectionType(
                                 net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN));

  static_assert(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE + 1 ==
                    net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
                "ECT enum value is not handled.");
  static_assert(net::EFFECTIVE_CONNECTION_TYPE_4G + 1 ==
                    net::EFFECTIVE_CONNECTION_TYPE_LAST,
                "ECT enum value is not handled.");
}

void DataReductionProxyNetworkDelegate::RemoveChromeProxyECTHeader(
    net::HttpRequestHeaders* request_headers) const {
  DCHECK(thread_checker_.CalledOnValidThread());

  request_headers->RemoveHeader(chrome_proxy_ect_header());
}

}  // namespace data_reduction_proxy
