// 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/domain_reliability/monitor.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
#include "components/domain_reliability/baked_in_configs.h"
#include "components/domain_reliability/google_configs.h"
#include "components/domain_reliability/header.h"
#include "components/domain_reliability/quic_error_mapping.h"
#include "content/public/browser/network_service_instance.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

namespace domain_reliability {

namespace {

int URLRequestStatusToNetError(const net::URLRequestStatus& status) {
  switch (status.status()) {
    case net::URLRequestStatus::SUCCESS:
      return net::OK;
    case net::URLRequestStatus::IO_PENDING:
      return net::ERR_IO_PENDING;
    case net::URLRequestStatus::CANCELED:
      return net::ERR_ABORTED;
    case net::URLRequestStatus::FAILED:
      return status.error();
    default:
      NOTREACHED();
      return net::ERR_UNEXPECTED;
  }
}

// Creates a new beacon based on |beacon_template| but fills in the status,
// chrome_error, and server_ip fields based on the endpoint and result of
// |attempt|.
//
// If there is no matching status for the result, returns false (which
// means the attempt should not result in a beacon being reported).
std::unique_ptr<DomainReliabilityBeacon> CreateBeaconFromAttempt(
    const DomainReliabilityBeacon& beacon_template,
    const net::ConnectionAttempt& attempt) {
  std::string status;
  if (!GetDomainReliabilityBeaconStatus(
          attempt.result, beacon_template.http_response_code, &status)) {
    return std::unique_ptr<DomainReliabilityBeacon>();
  }

  std::unique_ptr<DomainReliabilityBeacon> beacon(
      new DomainReliabilityBeacon(beacon_template));
  beacon->status = status;
  beacon->chrome_error = attempt.result;
  if (!attempt.endpoint.address().empty())
    beacon->server_ip = attempt.endpoint.ToString();
  else
    beacon->server_ip = "";
  return beacon;
}

const char* kDomainReliabilityHeaderName = "NEL";

}  // namespace

DomainReliabilityMonitor::DomainReliabilityMonitor(
    const std::string& upload_reporter_string,
    const DomainReliabilityContext::UploadAllowedCallback&
        upload_allowed_callback,
    const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
    const scoped_refptr<base::SingleThreadTaskRunner>& network_thread)
    : time_(new ActualTime()),
      upload_reporter_string_(upload_reporter_string),
      upload_allowed_callback_(upload_allowed_callback),
      scheduler_params_(
          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
      dispatcher_(time_.get()),
      context_manager_(this),
      pref_task_runner_(pref_thread),
      network_task_runner_(network_thread),
      network_connection_tracker_(nullptr),
      moved_to_network_thread_(false),
      discard_uploads_set_(false),
      weak_factory_(this) {
  DCHECK(OnPrefThread());
}

DomainReliabilityMonitor::DomainReliabilityMonitor(
    const std::string& upload_reporter_string,
    const DomainReliabilityContext::UploadAllowedCallback&
        upload_allowed_callback,
    const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
    const scoped_refptr<base::SingleThreadTaskRunner>& network_thread,
    std::unique_ptr<MockableTime> time)
    : time_(std::move(time)),
      upload_reporter_string_(upload_reporter_string),
      upload_allowed_callback_(upload_allowed_callback),
      scheduler_params_(
          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
      dispatcher_(time_.get()),
      context_manager_(this),
      pref_task_runner_(pref_thread),
      network_task_runner_(network_thread),
      network_connection_tracker_(nullptr),
      moved_to_network_thread_(false),
      discard_uploads_set_(false),
      weak_factory_(this) {
  DCHECK(OnPrefThread());
}

DomainReliabilityMonitor::~DomainReliabilityMonitor() {
  if (moved_to_network_thread_) {
    DCHECK(network_connection_tracker_);
    network_connection_tracker_->RemoveNetworkConnectionObserver(this);
    DCHECK(OnNetworkThread());
  } else {
    DCHECK(OnPrefThread());
  }
}

void DomainReliabilityMonitor::MoveToNetworkThread() {
  DCHECK(OnPrefThread());
  DCHECK(!moved_to_network_thread_);

  network_connection_tracker_ = content::GetNetworkConnectionTracker();
  network_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &network::NetworkConnectionTracker::AddNetworkConnectionObserver,
          base::Unretained(network_connection_tracker_),
          base::Unretained(this)));
  moved_to_network_thread_ = true;
}

void DomainReliabilityMonitor::InitURLRequestContext(
    net::URLRequestContext* url_request_context) {
  DCHECK(url_request_context);
  DCHECK(OnNetworkThread());
  DCHECK(moved_to_network_thread_);

  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
      new net::TrivialURLRequestContextGetter(url_request_context,
                                              network_task_runner_);
  InitURLRequestContext(url_request_context_getter);
}

void DomainReliabilityMonitor::InitURLRequestContext(
    const scoped_refptr<net::URLRequestContextGetter>&
        url_request_context_getter) {
  DCHECK(OnNetworkThread());
  DCHECK(moved_to_network_thread_);

  // Make sure the URLRequestContext actually lives on what was declared to be
  // the network thread.
  DCHECK(url_request_context_getter->GetNetworkTaskRunner()->
         RunsTasksInCurrentSequence());

  uploader_ = DomainReliabilityUploader::Create(time_.get(),
                                                url_request_context_getter);
}

void DomainReliabilityMonitor::Shutdown() {
  uploader_->Shutdown();
}

void DomainReliabilityMonitor::AddBakedInConfigs() {
  DCHECK(OnNetworkThread());
  DCHECK(moved_to_network_thread_);

  for (size_t i = 0; kBakedInJsonConfigs[i]; ++i) {
    base::StringPiece json(kBakedInJsonConfigs[i]);
    std::unique_ptr<const DomainReliabilityConfig> config =
        DomainReliabilityConfig::FromJSON(json);
    if (!config) {
      DLOG(WARNING) << "Baked-in Domain Reliability config failed to parse: "
                    << json;
      continue;
    }
    context_manager_.AddContextForConfig(std::move(config));
  }

  std::vector<std::unique_ptr<DomainReliabilityConfig>> google_configs;
  GetAllGoogleConfigs(&google_configs);
  for (auto& google_config : google_configs)
    context_manager_.AddContextForConfig(std::move(google_config));
}

void DomainReliabilityMonitor::SetDiscardUploads(bool discard_uploads) {
  DCHECK(OnNetworkThread());
  DCHECK(moved_to_network_thread_);
  DCHECK(uploader_);

  uploader_->SetDiscardUploads(discard_uploads);
  discard_uploads_set_ = true;
}

void DomainReliabilityMonitor::OnBeforeRedirect(net::URLRequest* request) {
  DCHECK(OnNetworkThread());
  DCHECK(discard_uploads_set_);

  // Record the redirect itself in addition to the final request.
  OnRequestLegComplete(RequestInfo(*request));
}

void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request,
                                           bool started) {
  DCHECK(OnNetworkThread());
  DCHECK(discard_uploads_set_);

  if (!started)
    return;
  RequestInfo request_info(*request);
  OnRequestLegComplete(request_info);

  if (request_info.response_info.network_accessed) {
    // A request was just using the network, so now is a good time to run any
    // pending and eligible uploads.
    dispatcher_.RunEligibleTasks();
  }
}

void DomainReliabilityMonitor::OnConnectionChanged(
    network::mojom::ConnectionType type) {
  last_network_change_time_ = time_->NowTicks();
}

void DomainReliabilityMonitor::ClearBrowsingData(
   DomainReliabilityClearMode mode,
   const base::Callback<bool(const GURL&)>& origin_filter) {
  DCHECK(OnNetworkThread());

  switch (mode) {
    case CLEAR_BEACONS:
      context_manager_.ClearBeacons(origin_filter);
      break;
    case CLEAR_CONTEXTS:
      context_manager_.RemoveContexts(origin_filter);
      break;
    case MAX_CLEAR_MODE:
      NOTREACHED();
  }
}

std::unique_ptr<base::Value> DomainReliabilityMonitor::GetWebUIData() const {
  DCHECK(OnNetworkThread());

  std::unique_ptr<base::DictionaryValue> data_value(
      new base::DictionaryValue());
  data_value->Set("contexts", context_manager_.GetWebUIData());
  return std::move(data_value);
}

DomainReliabilityContext* DomainReliabilityMonitor::AddContextForTesting(
    std::unique_ptr<const DomainReliabilityConfig> config) {
  DCHECK(OnNetworkThread());

  return context_manager_.AddContextForConfig(std::move(config));
}

void DomainReliabilityMonitor::ForceUploadsForTesting() {
  dispatcher_.RunAllTasksForTesting();
}

std::unique_ptr<DomainReliabilityContext>
DomainReliabilityMonitor::CreateContextForConfig(
    std::unique_ptr<const DomainReliabilityConfig> config) {
  DCHECK(OnNetworkThread());
  DCHECK(config);
  DCHECK(config->IsValid());

  return std::make_unique<DomainReliabilityContext>(
      time_.get(), scheduler_params_, upload_reporter_string_,
      &last_network_change_time_, upload_allowed_callback_, &dispatcher_,
      uploader_.get(), std::move(config));
}

DomainReliabilityMonitor::RequestInfo::RequestInfo() {}

DomainReliabilityMonitor::RequestInfo::RequestInfo(
    const net::URLRequest& request)
    : url(request.url()),
      status(request.status()),
      response_info(request.response_info()),
      load_flags(request.load_flags()),
      upload_depth(
          DomainReliabilityUploader::GetURLRequestUploadDepth(request)) {
  request.GetLoadTimingInfo(&load_timing_info);
  request.GetConnectionAttempts(&connection_attempts);
  request.PopulateNetErrorDetails(&details);
  if (!request.GetRemoteEndpoint(&remote_endpoint))
    remote_endpoint = net::IPEndPoint();
}

DomainReliabilityMonitor::RequestInfo::RequestInfo(const RequestInfo& other) =
    default;

DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}

// static
bool DomainReliabilityMonitor::RequestInfo::ShouldReportRequest(
    const DomainReliabilityMonitor::RequestInfo& request) {
  // Always report upload requests, even though they have DO_NOT_SEND_COOKIES.
  if (request.upload_depth > 0)
    return true;

  // Don't report requests that weren't supposed to send cookies.
  if (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES)
    return false;

  // Report requests that accessed the network or failed with an error code
  // that Domain Reliability is interested in.
  if (request.response_info.network_accessed)
    return true;
  if (URLRequestStatusToNetError(request.status) != net::OK)
    return true;
  if (request.details.quic_port_migration_detected)
    return true;

  return false;
}

void DomainReliabilityMonitor::OnRequestLegComplete(
    const RequestInfo& request) {
  // Check these again because unit tests call this directly.
  DCHECK(OnNetworkThread());
  DCHECK(discard_uploads_set_);

  MaybeHandleHeader(request);

  if (!RequestInfo::ShouldReportRequest(request))
    return;

  int response_code;
  if (request.response_info.headers)
    response_code = request.response_info.headers->response_code();
  else
    response_code = -1;

  net::ConnectionAttempt url_request_attempt(
      request.remote_endpoint, URLRequestStatusToNetError(request.status));

  DomainReliabilityBeacon beacon_template;
  if (request.response_info.connection_info !=
      net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN) {
    beacon_template.protocol =
        GetDomainReliabilityProtocol(request.response_info.connection_info,
                                     request.response_info.ssl_info.is_valid());
  } else {
    // Use the connection info from the network error details if the response
    // is unavailable.
    beacon_template.protocol =
        GetDomainReliabilityProtocol(request.details.connection_info,
                                     request.response_info.ssl_info.is_valid());
  }
  GetDomainReliabilityBeaconQuicError(request.details.quic_connection_error,
                                      &beacon_template.quic_error);
  beacon_template.http_response_code = response_code;
  beacon_template.start_time = request.load_timing_info.request_start;
  beacon_template.elapsed = time_->NowTicks() - beacon_template.start_time;
  beacon_template.was_proxied = request.response_info.was_fetched_via_proxy;
  beacon_template.url = request.url;
  beacon_template.upload_depth = request.upload_depth;
  beacon_template.details = request.details;

  // This is not foolproof -- it's possible that we'll see the same error twice
  // (e.g. an SSL error during connection on one attempt, and then an error
  // that maps to the same code during a read).
  // TODO(juliatuttle): Find a way for this code to reliably tell whether we
  // eventually established a connection or not.
  bool url_request_attempt_is_duplicate = false;
  for (const auto& attempt : request.connection_attempts) {
    if (attempt.result == url_request_attempt.result)
      url_request_attempt_is_duplicate = true;

    std::unique_ptr<DomainReliabilityBeacon> beacon =
        CreateBeaconFromAttempt(beacon_template, attempt);
    if (beacon)
      context_manager_.RouteBeacon(std::move(beacon));
  }

  if (url_request_attempt_is_duplicate)
    return;

  std::unique_ptr<DomainReliabilityBeacon> beacon =
      CreateBeaconFromAttempt(beacon_template, url_request_attempt);
  if (beacon)
    context_manager_.RouteBeacon(std::move(beacon));
}

void DomainReliabilityMonitor::MaybeHandleHeader(
    const RequestInfo& request) {
  if (!request.response_info.headers)
    return;

  size_t iter = 0;
  std::string kHeaderNameString(kDomainReliabilityHeaderName);

  std::string header_value;
  if (!request.response_info.headers->EnumerateHeader(
          &iter, kHeaderNameString, &header_value)) {
    // No header found.
    return;
  }

  std::string ignored_header_value;
  if (request.response_info.headers->EnumerateHeader(
          &iter, kHeaderNameString, &ignored_header_value)) {
    LOG(WARNING) << "Request to " << request.url << " had (at least) two "
                 << kHeaderNameString << " headers: \"" << header_value
                 << "\" and \"" << ignored_header_value << "\".";
    return;
  }

  std::unique_ptr<DomainReliabilityHeader> parsed =
      DomainReliabilityHeader::Parse(header_value);
  GURL origin = request.url.GetOrigin();
  switch (parsed->status()) {
    case DomainReliabilityHeader::PARSE_SET_CONFIG:
      {
        base::TimeDelta max_age = parsed->max_age();
        context_manager_.SetConfig(origin, parsed->ReleaseConfig(), max_age);
      }
      break;
    case DomainReliabilityHeader::PARSE_CLEAR_CONFIG:
      context_manager_.ClearConfig(origin);
      break;
    case DomainReliabilityHeader::PARSE_ERROR:
      LOG(WARNING) << "Request to " << request.url << " had invalid "
                   << kHeaderNameString << " header \"" << header_value
                   << "\".";
      break;
  }
}

base::WeakPtr<DomainReliabilityMonitor>
DomainReliabilityMonitor::MakeWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

}  // namespace domain_reliability
