// 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 <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/profiler/scoped_tracker.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 "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 scoped_refptr<base::SingleThreadTaskRunner>& pref_thread,
    const scoped_refptr<base::SingleThreadTaskRunner>& network_thread)
    : time_(new ActualTime()),
      upload_reporter_string_(upload_reporter_string),
      scheduler_params_(
          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
      dispatcher_(time_.get()),
      context_manager_(this),
      pref_task_runner_(pref_thread),
      network_task_runner_(network_thread),
      moved_to_network_thread_(false),
      discard_uploads_set_(false),
      weak_factory_(this) {
  DCHECK(OnPrefThread());
}

DomainReliabilityMonitor::DomainReliabilityMonitor(
    const std::string& upload_reporter_string,
    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),
      scheduler_params_(
          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
      dispatcher_(time_.get()),
      context_manager_(this),
      pref_task_runner_(pref_thread),
      network_task_runner_(network_thread),
      moved_to_network_thread_(false),
      discard_uploads_set_(false),
      weak_factory_(this) {
  DCHECK(OnPrefThread());
}

DomainReliabilityMonitor::~DomainReliabilityMonitor() {
  if (moved_to_network_thread_) {
    net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
    DCHECK(OnNetworkThread());
  } else {
    DCHECK(OnPrefThread());
  }
}

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

  network_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&net::NetworkChangeNotifier::AddNetworkChangeObserver,
                 base::Unretained(this)));
  moved_to_network_thread_ = true;
}

void DomainReliabilityMonitor::InitURLRequestContext(
    net::URLRequestContext* 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()->
         RunsTasksOnCurrentThread());

  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_->set_discard_uploads(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::OnNetworkChanged(
    net::NetworkChangeNotifier::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 base::MakeUnique<DomainReliabilityContext>(
      time_.get(), scheduler_params_, upload_reporter_string_,
      &last_network_change_time_, &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.get())
    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.get())
    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
