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

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/supports_user_data.h"
#include "components/domain_reliability/util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_context_getter.h"

namespace domain_reliability {

namespace {

const char kJsonMimeType[] = "application/json; charset=utf-8";

class UploadUserData : public base::SupportsUserData::Data {
 public:
  static net::URLFetcher::CreateDataCallback CreateCreateDataCallback(
      int depth) {
    return base::Bind(&UploadUserData::CreateUploadUserData, depth);
  }

  static const void* const kUserDataKey;

  int depth() const { return depth_; }

 private:
  UploadUserData(int depth) : depth_(depth) {}

  static std::unique_ptr<base::SupportsUserData::Data> CreateUploadUserData(
      int depth) {
    return base::WrapUnique(new UploadUserData(depth));
  }

  int depth_;
};

const void* const UploadUserData::kUserDataKey =
    &UploadUserData::kUserDataKey;

class DomainReliabilityUploaderImpl
    : public DomainReliabilityUploader, net::URLFetcherDelegate {
 public:
  DomainReliabilityUploaderImpl(
      MockableTime* time,
      const scoped_refptr<net::URLRequestContextGetter>&
          url_request_context_getter)
      : time_(time),
        url_request_context_getter_(url_request_context_getter),
        discard_uploads_(true),
        shutdown_(false),
        discarded_upload_count_(0u) {}

  ~DomainReliabilityUploaderImpl() override {
    DCHECK(shutdown_);
  }

  // DomainReliabilityUploader implementation:
  void UploadReport(
      const std::string& report_json,
      int max_upload_depth,
      const GURL& upload_url,
      const DomainReliabilityUploader::UploadCallback& callback) override {
    VLOG(1) << "Uploading report to " << upload_url;
    VLOG(2) << "Report JSON: " << report_json;

    if (discard_uploads_)
      discarded_upload_count_++;

    if (discard_uploads_ || shutdown_) {
      VLOG(1) << "Discarding report instead of uploading.";
      UploadResult result;
      result.status = UploadResult::SUCCESS;
      callback.Run(result);
      return;
    }

    net::NetworkTrafficAnnotationTag traffic_annotation =
        net::DefineNetworkTrafficAnnotation("domain_reliability_report_upload",
                                            R"(
          semantics {
            sender: "Domain Reliability"
            description:
              "If Chromium has trouble reaching certain Google sites or "
              "services, Domain Reliability may report the problems back to "
              "Google."
            trigger: "Failure to load certain Google sites or services."
            data:
              "Details of the failed request, including the URL, any IP "
              "addresses the browser tried to connect to, error(s) "
              "encountered loading the resource, and other connection details."
            destination: GOOGLE_OWNED_SERVICE
          }
          policy {
            cookies_allowed: NO
            setting:
              "Users can enable or disable Domain Reliability on desktop, via "
              "toggling 'Automatically send usage statistics and crash reports "
              "to Google' in Chromium's settings under Privacy. On ChromeOS, "
              "the setting is named 'Automatically send diagnostic and usage "
              "data to Google'."
            policy_exception_justification: "Not implemented."
          })");
    std::unique_ptr<net::URLFetcher> owned_fetcher = net::URLFetcher::Create(
        0, upload_url, net::URLFetcher::POST, this, traffic_annotation);
    net::URLFetcher* fetcher = owned_fetcher.get();
    fetcher->SetRequestContext(url_request_context_getter_.get());
    fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                          net::LOAD_DO_NOT_SAVE_COOKIES);
    fetcher->SetUploadData(kJsonMimeType, report_json);
    fetcher->SetAutomaticallyRetryOn5xx(false);
    fetcher->SetURLRequestUserData(
        UploadUserData::kUserDataKey,
        UploadUserData::CreateCreateDataCallback(max_upload_depth + 1));
    fetcher->Start();

    uploads_[fetcher] = {std::move(owned_fetcher), callback};
  }

  void SetDiscardUploads(bool discard_uploads) override {
    discard_uploads_ = discard_uploads;
    VLOG(1) << "Setting discard_uploads to " << discard_uploads;
  }

  void Shutdown() override {
    DCHECK(!shutdown_);
    shutdown_ = true;
    uploads_.clear();
  }

  int GetDiscardedUploadCount() const override {
    return discarded_upload_count_;
  }

  // net::URLFetcherDelegate implementation:
  void OnURLFetchComplete(const net::URLFetcher* fetcher) override {
    DCHECK(fetcher);

    auto callback_it = uploads_.find(fetcher);
    DCHECK(callback_it != uploads_.end());

    int net_error = GetNetErrorFromURLRequestStatus(fetcher->GetStatus());
    int http_response_code = fetcher->GetResponseCode();
    base::TimeDelta retry_after;
    {
      std::string retry_after_string;
      if (fetcher->GetResponseHeaders() &&
          fetcher->GetResponseHeaders()->EnumerateHeader(nullptr,
                                                         "Retry-After",
                                                         &retry_after_string)) {
        net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
                                             time_->Now(),
                                             &retry_after);
      }
    }

    VLOG(1) << "Upload finished with net error " << net_error
            << ", response code " << http_response_code
            << ", retry after " << retry_after;

    base::UmaHistogramSparse("DomainReliability.UploadResponseCode",
                             http_response_code);
    base::UmaHistogramSparse("DomainReliability.UploadNetError", -net_error);

    UploadResult result;
    GetUploadResultFromResponseDetails(net_error,
                                       http_response_code,
                                       retry_after,
                                       &result);
    callback_it->second.second.Run(result);

    uploads_.erase(callback_it);
  }

 private:
  using DomainReliabilityUploader::UploadCallback;

  MockableTime* time_;
  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
  std::map<const net::URLFetcher*,
           std::pair<std::unique_ptr<net::URLFetcher>, UploadCallback>>
      uploads_;
  bool discard_uploads_;
  bool shutdown_;
  int discarded_upload_count_;
};

}  // namespace

DomainReliabilityUploader::DomainReliabilityUploader() {}
DomainReliabilityUploader::~DomainReliabilityUploader() {}

// static
std::unique_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
    MockableTime* time,
    const scoped_refptr<net::URLRequestContextGetter>&
        url_request_context_getter) {
  return std::unique_ptr<DomainReliabilityUploader>(
      new DomainReliabilityUploaderImpl(time, url_request_context_getter));
}

// static
int DomainReliabilityUploader::GetURLRequestUploadDepth(
    const net::URLRequest& request) {
  UploadUserData* data = static_cast<UploadUserData*>(
      request.GetUserData(UploadUserData::kUserDataKey));
  if (!data)
    return 0;
  return data->depth();
}

void DomainReliabilityUploader::Shutdown() {}

}  // namespace domain_reliability
