// Copyright 2016 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 "net/reporting/reporting_uploader.h"

#include <string>
#include <utility>
#include <vector>

#include "base/callback_helpers.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_context.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace net {

namespace {

constexpr char kUploadContentType[] = "application/reports+json";

constexpr net::NetworkTrafficAnnotationTag kReportUploadTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("reporting", R"(
        semantics {
          sender: "Reporting API"
          description:
            "The Reporting API reports various issues back to website owners "
            "to help them detect and fix problems."
          trigger:
            "Encountering issues. Examples of these issues are Content "
            "Security Policy violations and Interventions/Deprecations "
            "encountered. See draft of reporting spec here: "
            "https://wicg.github.io/reporting."
          data: "Details of the issue, depending on issue type."
          destination: OTHER
        }
        policy {
          cookies_allowed: NO
          setting: "This feature cannot be disabled by settings."
          policy_exception_justification: "Not implemented."
        })");

class UploadUserData : public base::SupportsUserData::Data {
 public:
  static const void* const kUserDataKey;

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

  int depth;
};

// Returns true if |request| contains any of the |allowed_values| in a response
// header field named |header|. |allowed_values| are expected to be lower-case
// and the check is case-insensitive.
bool HasHeaderValues(URLRequest* request,
                     const std::string& header,
                     const std::set<std::string>& allowed_values) {
  std::string response_headers;
  request->GetResponseHeaderByName(header, &response_headers);
  const std::vector<std::string> response_values =
      base::SplitString(base::ToLowerASCII(response_headers), ",",
                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  for (const auto& value : response_values) {
    if (allowed_values.find(value) != allowed_values.end())
      return true;
  }
  return false;
}

// SetUserData needs a unique const void* to serve as the key, so create a const
// void* and use its own address as the unique pointer.
const void* const UploadUserData::kUserDataKey = &UploadUserData::kUserDataKey;

ReportingUploader::Outcome ResponseCodeToOutcome(int response_code) {
  if (response_code >= 200 && response_code <= 299)
    return ReportingUploader::Outcome::SUCCESS;
  if (response_code == 410)
    return ReportingUploader::Outcome::REMOVE_ENDPOINT;
  return ReportingUploader::Outcome::FAILURE;
}

enum class UploadOutcome {
  CANCELED_REDIRECT_TO_INSECURE_URL = 0,
  CANCELED_AUTH_REQUIRED = 1,
  CANCELED_CERTIFICATE_REQUESTED = 2,
  CANCELED_SSL_CERTIFICATE_ERROR = 3,
  CANCELED_REPORTING_SHUTDOWN = 4,
  FAILED = 5,  // See Net.Reporting.UploadError for breakdown.
  SUCCEEDED_SUCCESS = 6,
  SUCCEEDED_REMOVE_ENDPOINT = 7,
  CORS_PREFLIGHT_ERROR = 8,

  MAX
};

void RecordUploadOutcome(UploadOutcome outcome) {
  UMA_HISTOGRAM_ENUMERATION("Net.Reporting.UploadOutcome", outcome,
                            UploadOutcome::MAX);
}

// TODO: Record net and HTTP error.

struct PendingUpload {
  enum State { CREATED, SENDING_PREFLIGHT, SENDING_PAYLOAD };

  PendingUpload(const url::Origin& report_origin,
                const GURL& url,
                const std::string& json,
                int max_depth,
                ReportingUploader::UploadCallback callback)
      : state(CREATED),
        report_origin(report_origin),
        url(url),
        payload_reader(UploadOwnedBytesElementReader::CreateWithString(json)),
        max_depth(max_depth),
        callback(std::move(callback)) {}

  void RunCallback(ReportingUploader::Outcome outcome) {
    std::move(callback).Run(outcome);
  }

  State state;
  const url::Origin report_origin;
  const GURL url;
  std::unique_ptr<UploadElementReader> payload_reader;
  int max_depth;
  ReportingUploader::UploadCallback callback;
  std::unique_ptr<URLRequest> request;
};

class ReportingUploaderImpl : public ReportingUploader, URLRequest::Delegate {
 public:
  ReportingUploaderImpl(const URLRequestContext* context) : context_(context) {
    DCHECK(context_);
  }

  ~ReportingUploaderImpl() override {
    for (auto& request_and_upload : uploads_) {
      auto& upload = request_and_upload.second;
      upload->RunCallback(Outcome::FAILURE);
    }
  }

  void StartUpload(const url::Origin& report_origin,
                   const GURL& url,
                   const std::string& json,
                   int max_depth,
                   UploadCallback callback) override {
    auto upload = std::make_unique<PendingUpload>(
        report_origin, url, json, max_depth, std::move(callback));
    auto collector_origin = url::Origin::Create(url);
    if (collector_origin == report_origin) {
      // Skip the preflight check if the reports are being sent to the same
      // origin as the requests they describe.
      StartPayloadRequest(std::move(upload));
    } else {
      StartPreflightRequest(std::move(upload));
    }
  }

  void StartPreflightRequest(std::unique_ptr<PendingUpload> upload) {
    DCHECK(upload->state == PendingUpload::CREATED);

    upload->state = PendingUpload::SENDING_PREFLIGHT;
    upload->request = context_->CreateRequest(upload->url, IDLE, this,
                                              kReportUploadTrafficAnnotation);

    upload->request->set_method("OPTIONS");

    upload->request->SetLoadFlags(LOAD_DISABLE_CACHE |
                                  LOAD_DO_NOT_SAVE_COOKIES |
                                  LOAD_DO_NOT_SEND_COOKIES);

    upload->request->SetExtraRequestHeaderByName(
        HttpRequestHeaders::kOrigin, upload->report_origin.Serialize(), true);
    upload->request->SetExtraRequestHeaderByName(
        "Access-Control-Request-Method", "POST", true);
    upload->request->SetExtraRequestHeaderByName(
        "Access-Control-Request-Headers", "content-type", true);

    // Set the max_depth for this request, to cap how deep a stack of "reports
    // about reports" can get.  (Without this, a Reporting policy that uploads
    // reports to the same origin can cause an infinite stack of reports about
    // reports.)
    upload->request->SetUserData(
        UploadUserData::kUserDataKey,
        std::make_unique<UploadUserData>(upload->max_depth));

    URLRequest* raw_request = upload->request.get();
    uploads_[raw_request] = std::move(upload);
    raw_request->Start();
  }

  void StartPayloadRequest(std::unique_ptr<PendingUpload> upload) {
    DCHECK(upload->state == PendingUpload::CREATED ||
           upload->state == PendingUpload::SENDING_PREFLIGHT);

    upload->state = PendingUpload::SENDING_PAYLOAD;
    upload->request = context_->CreateRequest(upload->url, IDLE, this,
                                              kReportUploadTrafficAnnotation);

    upload->request->set_method("POST");

    upload->request->SetLoadFlags(LOAD_DISABLE_CACHE |
                                  LOAD_DO_NOT_SAVE_COOKIES |
                                  LOAD_DO_NOT_SEND_COOKIES);

    upload->request->SetExtraRequestHeaderByName(
        HttpRequestHeaders::kContentType, kUploadContentType, true);

    upload->request->set_upload(ElementsUploadDataStream::CreateWithReader(
        std::move(upload->payload_reader), 0));

    // Set the max_depth for this request, to cap how deep a stack of "reports
    // about reports" can get.  (Without this, a Reporting policy that uploads
    // reports to the same origin can cause an infinite stack of reports about
    // reports.)
    upload->request->SetUserData(
        UploadUserData::kUserDataKey,
        std::make_unique<UploadUserData>(upload->max_depth));

    URLRequest* raw_request = upload->request.get();
    uploads_[raw_request] = std::move(upload);
    raw_request->Start();
  }

  int GetUploadDepth(const net::URLRequest& request) override {
    UploadUserData* data = static_cast<UploadUserData*>(
        request.GetUserData(UploadUserData::kUserDataKey));
    return data ? data->depth + 1 : 0;
  }

  // URLRequest::Delegate implementation:

  void OnReceivedRedirect(URLRequest* request,
                          const RedirectInfo& redirect_info,
                          bool* defer_redirect) override {
    if (!redirect_info.new_url.SchemeIsCryptographic()) {
      request->Cancel();
      return;
    }
  }

  void OnAuthRequired(URLRequest* request,
                      AuthChallengeInfo* auth_info) override {
    request->Cancel();
  }

  void OnCertificateRequested(URLRequest* request,
                              SSLCertRequestInfo* cert_request_info) override {
    request->Cancel();
  }

  void OnSSLCertificateError(URLRequest* request,
                             const SSLInfo& ssl_info,
                             bool fatal) override {
    request->Cancel();
  }

  void OnResponseStarted(URLRequest* request, int net_error) override {
    // Grab Upload from map, and hold on to it in a local unique_ptr so it's
    // removed at the end of the method.
    auto it = uploads_.find(request);
    DCHECK(it != uploads_.end());
    std::unique_ptr<PendingUpload> upload = std::move(it->second);
    uploads_.erase(it);

    if (net_error != OK) {
      RecordUploadOutcome(UploadOutcome::FAILED);
      base::UmaHistogramSparse("Net.Reporting.UploadError", net_error);
      upload->RunCallback(ReportingUploader::Outcome::FAILURE);
      return;
    }

    // request->GetResponseCode() should work, but doesn't in the cases above
    // where the request was canceled, so get the response code by hand.
    // TODO(juliatuttle): Check if mmenke fixed this yet.
    HttpResponseHeaders* headers = request->response_headers();
    int response_code = headers ? headers->response_code() : 0;

    switch (upload->state) {
      case PendingUpload::SENDING_PREFLIGHT:
        HandlePreflightResponse(std::move(upload), response_code);
        break;
      case PendingUpload::SENDING_PAYLOAD:
        HandlePayloadResponse(std::move(upload), response_code);
        break;
      default:
        NOTREACHED();
    }
  }

  void HandlePreflightResponse(std::unique_ptr<PendingUpload> upload,
                               int response_code) {
    // Check that the preflight succeeded: it must have an HTTP OK status code,
    // with the following headers:
    // - Access-Control-Allow-Origin: * or the report origin
    // - Access-Control-Allow-Methods: POST
    // - Access-Control-Allow-Headers: Content-Type
    URLRequest* request = upload->request.get();
    bool preflight_succeeded =
        (response_code >= 200 && response_code <= 299) &&
        HasHeaderValues(
            request, "Access-Control-Allow-Origin",
            {"*", base::ToLowerASCII(upload->report_origin.Serialize())}) &&
        HasHeaderValues(request, "Access-Control-Allow-Methods", {"post"}) &&
        HasHeaderValues(request, "Access-Control-Allow-Headers",
                        {"content-type"});
    if (!preflight_succeeded) {
      RecordUploadOutcome(UploadOutcome::CORS_PREFLIGHT_ERROR);
      upload->RunCallback(ReportingUploader::Outcome::FAILURE);
      return;
    }

    StartPayloadRequest(std::move(upload));
  }

  void HandlePayloadResponse(std::unique_ptr<PendingUpload> upload,
                             int response_code) {
    if (response_code >= 200 && response_code <= 299) {
      RecordUploadOutcome(UploadOutcome::SUCCEEDED_SUCCESS);
    } else if (response_code == 410) {
      RecordUploadOutcome(UploadOutcome::SUCCEEDED_REMOVE_ENDPOINT);
    } else {
      RecordUploadOutcome(UploadOutcome::FAILED);
      base::UmaHistogramSparse("Net.Reporting.UploadError", response_code);
    }
    upload->RunCallback(ResponseCodeToOutcome(response_code));
  }

  void OnReadCompleted(URLRequest* request, int bytes_read) override {
    // Reporting doesn't need anything in the body of the response, so it
    // doesn't read it, so it should never get OnReadCompleted calls.
    NOTREACHED();
  }

 private:
  const URLRequestContext* context_;
  std::map<const URLRequest*, std::unique_ptr<PendingUpload>> uploads_;
};

}  // namespace

ReportingUploader::~ReportingUploader() = default;

// static
std::unique_ptr<ReportingUploader> ReportingUploader::Create(
    const URLRequestContext* context) {
  return std::make_unique<ReportingUploaderImpl>(context);
}

}  // namespace net
