// 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 "chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h"

#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/ssl/certificate_error_report.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_utils.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_filter.h"
#include "services/network/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/curve25519.h"

namespace {

static const char kHkdfLabel[] = "certificate report";
const uint32_t kServerPublicKeyTestVersion = 16;

std::string GetReportContents(const network::ResourceRequest& request,
                              const uint8_t* server_private_key) {
  std::string serialized_report(network::GetUploadData(request));
  encrypted_messages::EncryptedMessage encrypted_message;
  EXPECT_TRUE(encrypted_message.ParseFromString(serialized_report));
  EXPECT_EQ(kServerPublicKeyTestVersion,
            encrypted_message.server_public_key_version());
  EXPECT_EQ(
      encrypted_messages::EncryptedMessage::AEAD_ECDH_AES_128_CTR_HMAC_SHA256,
      encrypted_message.algorithm());
  std::string decrypted_report;
  // TODO(estark): kHkdfLabel needs to include the null character in the label
  // due to a matching error in the server for the case of certificate
  // reporting, the strlen + 1 can be removed once that error is fixed.
  // https://crbug.com/517746
  EXPECT_TRUE(encrypted_messages::DecryptMessageForTesting(
      server_private_key, base::StringPiece(kHkdfLabel, strlen(kHkdfLabel) + 1),
      encrypted_message, &decrypted_report));
  return decrypted_report;
}

void WaitReports(
    certificate_reporting_test_utils::RequestObserver* observer,
    const certificate_reporting_test_utils::ReportExpectation& expectation,
    std::vector<std::string>* full_reports) {
  observer->Wait(expectation.num_reports());
  EXPECT_EQ(expectation.successful_reports, observer->successful_reports());
  EXPECT_EQ(expectation.failed_reports, observer->failed_reports());
  EXPECT_EQ(expectation.delayed_reports, observer->delayed_reports());
  if (full_reports)
    *full_reports = observer->full_reports();
  observer->ClearObservedReports();
}

}  // namespace

namespace certificate_reporting_test_utils {

RequestObserver::RequestObserver()
    : num_events_to_wait_for_(0u), num_received_events_(0u) {}

RequestObserver::~RequestObserver() {}

void RequestObserver::Wait(unsigned int num_events_to_wait_for) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(!run_loop_);
  ASSERT_LE(num_received_events_, num_events_to_wait_for)
      << "Observed unexpected report";

  if (num_received_events_ < num_events_to_wait_for) {
    num_events_to_wait_for_ = num_events_to_wait_for;
    run_loop_.reset(new base::RunLoop());
    run_loop_->Run();
    run_loop_.reset(nullptr);
    EXPECT_EQ(0u, num_received_events_);
    EXPECT_EQ(0u, num_events_to_wait_for_);
  } else if (num_received_events_ == num_events_to_wait_for) {
    num_received_events_ = 0u;
    num_events_to_wait_for_ = 0u;
  }
}

void RequestObserver::OnRequest(const std::string& serialized_report,
                                ReportSendingResult report_type) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  CertificateErrorReport report;
  EXPECT_TRUE(report.InitializeFromString(serialized_report));

  full_reports_.push_back(serialized_report);

  switch (report_type) {
    case REPORTS_SUCCESSFUL:
      successful_reports_[report.hostname()] =
          report.is_retry_upload() ? RETRIED : NOT_RETRIED;
      break;
    case REPORTS_FAIL:
      failed_reports_[report.hostname()] =
          report.is_retry_upload() ? RETRIED : NOT_RETRIED;
      break;
    case REPORTS_DELAY:
      delayed_reports_[report.hostname()] =
          report.is_retry_upload() ? RETRIED : NOT_RETRIED;
      break;
  }

  num_received_events_++;
  if (!run_loop_) {
    return;
  }
  ASSERT_LE(num_received_events_, num_events_to_wait_for_)
      << "Observed unexpected report";

  if (num_received_events_ == num_events_to_wait_for_) {
    num_events_to_wait_for_ = 0u;
    num_received_events_ = 0u;
    run_loop_->Quit();
  }
}

const ObservedReportMap& RequestObserver::successful_reports() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return successful_reports_;
}

const ObservedReportMap& RequestObserver::failed_reports() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return failed_reports_;
}

const ObservedReportMap& RequestObserver::delayed_reports() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return delayed_reports_;
}
const std::vector<std::string>& RequestObserver::full_reports() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  return full_reports_;
}

void RequestObserver::ClearObservedReports() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  successful_reports_.clear();
  failed_reports_.clear();
  delayed_reports_.clear();
  full_reports_.clear();
}

DelayableCertReportURLRequestJob::DelayableCertReportURLRequestJob(
    bool delayed,
    bool should_fail,
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate,
    const base::Callback<void()>& destruction_callback)
    : net::URLRequestJob(request, network_delegate),
      delayed_(delayed),
      should_fail_(should_fail),
      started_(false),
      destruction_callback_(destruction_callback),
      weak_factory_(this) {}

DelayableCertReportURLRequestJob::~DelayableCertReportURLRequestJob() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
                                   destruction_callback_);
}

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

void DelayableCertReportURLRequestJob::Start() {
  started_ = true;
  if (delayed_) {
    // Do nothing until Resume() is called.
    return;
  }
  Resume();
}

int DelayableCertReportURLRequestJob::ReadRawData(net::IOBuffer* buf,
                                                  int buf_size) {
  // Report sender ignores responses. Return empty response.
  return 0;
}

void DelayableCertReportURLRequestJob::GetResponseInfo(
    net::HttpResponseInfo* info) {
  // Report sender ignores responses. Return empty response.
  if (!should_fail_) {
    info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
  }
}

void DelayableCertReportURLRequestJob::Resume() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  if (!started_) {
    // If Start() hasn't been called yet, then unset |delayed_| so that when
    // Start() is called, the request will begin immediately.
    delayed_ = false;
    return;
  }
  if (should_fail_) {
    NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
                                           net::ERR_SSL_PROTOCOL_ERROR));
    return;
  }
  // Start reading asynchronously as would a normal network request.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&DelayableCertReportURLRequestJob::NotifyHeadersComplete,
                     weak_factory_.GetWeakPtr()));
}

ReportExpectation::ReportExpectation() {}

ReportExpectation::ReportExpectation(const ReportExpectation& other) = default;

ReportExpectation::~ReportExpectation() {}

// static
ReportExpectation ReportExpectation::Successful(
    const ObservedReportMap& reports) {
  ReportExpectation expectation;
  expectation.successful_reports = reports;
  return expectation;
}

// static
ReportExpectation ReportExpectation::Failed(const ObservedReportMap& reports) {
  ReportExpectation expectation;
  expectation.failed_reports = reports;
  return expectation;
}

// static
ReportExpectation ReportExpectation::Delayed(const ObservedReportMap& reports) {
  ReportExpectation expectation;
  expectation.delayed_reports = reports;
  return expectation;
}

int ReportExpectation::num_reports() const {
  return successful_reports.size() + failed_reports.size() +
         delayed_reports.size();
}

CertificateReportingServiceObserver::CertificateReportingServiceObserver() {}

CertificateReportingServiceObserver::~CertificateReportingServiceObserver() {}

void CertificateReportingServiceObserver::Clear() {
  did_reset_ = false;
}

void CertificateReportingServiceObserver::WaitForReset() {
  DCHECK(!run_loop_);
  if (did_reset_)
    return;
  run_loop_.reset(new base::RunLoop());
  run_loop_->Run();
  run_loop_.reset();
}

void CertificateReportingServiceObserver::OnServiceReset() {
  did_reset_ = true;
  if (run_loop_)
    run_loop_->Quit();
}

CertificateReportingServiceTestHelper::CertificateReportingServiceTestHelper()
    : expected_report_result_(REPORTS_FAIL) {
  memset(server_private_key_, 1, sizeof(server_private_key_));
  X25519_public_from_private(server_public_key_, server_private_key_);
}

CertificateReportingServiceTestHelper::
    ~CertificateReportingServiceTestHelper() {}

void CertificateReportingServiceTestHelper::SetFailureMode(
    ReportSendingResult expected_report_result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  expected_report_result_ = expected_report_result;
}

void CertificateReportingServiceTestHelper::ResumeDelayedRequest() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  EXPECT_EQ(REPORTS_DELAY, expected_report_result_);
  if (delayed_client_) {
    SendResponse(std::move(delayed_client_), delayed_result_ == REPORTS_FAIL);
    request_destroyed_observer_.OnRequest(delayed_report_, delayed_result_);
  }
}

uint8_t* CertificateReportingServiceTestHelper::server_public_key() {
  return server_public_key_;
}

uint32_t CertificateReportingServiceTestHelper::server_public_key_version()
    const {
  return kServerPublicKeyTestVersion;
}

void CertificateReportingServiceTestHelper::WaitForRequestsCreated(
    const ReportExpectation& expectation) {
  WaitReports(&request_created_observer_, expectation, nullptr);
}

void CertificateReportingServiceTestHelper::WaitForRequestsCreated(
    const ReportExpectation& expectation,
    std::vector<std::string>* full_reports) {
  WaitReports(&request_created_observer_, expectation, full_reports);
}

void CertificateReportingServiceTestHelper::WaitForRequestsDestroyed(
    const ReportExpectation& expectation) {
  WaitReports(&request_destroyed_observer_, expectation, nullptr);
}

void CertificateReportingServiceTestHelper::WaitForRequestsDestroyed(
    const ReportExpectation& expectation,
    std::vector<std::string>* full_reports) {
  WaitReports(&request_destroyed_observer_, expectation, full_reports);
}

void CertificateReportingServiceTestHelper::ExpectNoRequests(
    CertificateReportingService* service) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // Check that all requests have been destroyed.
  EXPECT_TRUE(request_destroyed_observer_.successful_reports().empty());
  EXPECT_TRUE(request_destroyed_observer_.failed_reports().empty());
  EXPECT_TRUE(request_destroyed_observer_.delayed_reports().empty());

  if (service->GetReporterForTesting()) {
    // Reporter can be null if reporting is disabled.
    EXPECT_EQ(
        0u,
        service->GetReporterForTesting()->inflight_report_count_for_testing());
  }
}

void CertificateReportingServiceTestHelper::SendResponse(
    network::mojom::URLLoaderClientPtr client,
    bool fail) {
  if (fail) {
    client->OnComplete(
        network::URLLoaderCompletionStatus(net::ERR_SSL_PROTOCOL_ERROR));
    return;
  }

  network::ResourceResponseHead head;
  head.headers = new net::HttpResponseHeaders(
      "HTTP/1.1 200 OK\nContent-type: text/html\n\n");
  head.mime_type = "text/html";
  client->OnReceiveResponse(head);
  client->OnComplete(network::URLLoaderCompletionStatus());
}

void CertificateReportingServiceTestHelper::CreateLoaderAndStart(
    network::mojom::URLLoaderRequest request,
    int32_t routing_id,
    int32_t request_id,
    uint32_t options,
    const network::ResourceRequest& url_request,
    network::mojom::URLLoaderClientPtr client,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
  const std::string serialized_report =
      GetReportContents(url_request, server_private_key_);
  request_created_observer_.OnRequest(serialized_report,
                                      expected_report_result_);

  if (expected_report_result_ == REPORTS_FAIL) {
    SendResponse(std::move(client), true);
    request_destroyed_observer_.OnRequest(serialized_report,
                                          expected_report_result_);
    return;
  }

  if (expected_report_result_ == REPORTS_DELAY) {
    DCHECK(!delayed_client_) << "Supports only one delayed request at a time";
    delayed_client_ = std::move(client);
    delayed_report_ = serialized_report;
    delayed_result_ = expected_report_result_;
    return;
  }

  SendResponse(std::move(client), false);
  request_destroyed_observer_.OnRequest(serialized_report,
                                        expected_report_result_);
}

void CertificateReportingServiceTestHelper::Clone(
    network::mojom::URLLoaderFactoryRequest request) {
  NOTREACHED();
}

std::unique_ptr<network::SharedURLLoaderFactoryInfo>
CertificateReportingServiceTestHelper::Clone() {
  NOTREACHED();
  return nullptr;
}

EventHistogramTester::EventHistogramTester() {}

EventHistogramTester::~EventHistogramTester() {
  if (submitted_) {
    histogram_tester_.ExpectBucketCount(
        CertificateReportingService::kReportEventHistogram,
        static_cast<int>(CertificateReportingService::ReportOutcome::SUBMITTED),
        submitted_);
  }
  if (failed_) {
    histogram_tester_.ExpectBucketCount(
        CertificateReportingService::kReportEventHistogram,
        static_cast<int>(CertificateReportingService::ReportOutcome::FAILED),
        failed_);
  }
  if (successful_) {
    histogram_tester_.ExpectBucketCount(
        CertificateReportingService::kReportEventHistogram,
        static_cast<int>(
            CertificateReportingService::ReportOutcome::SUCCESSFUL),
        successful_);
  }
  if (dropped_) {
    histogram_tester_.ExpectBucketCount(
        CertificateReportingService::kReportEventHistogram,
        static_cast<int>(
            CertificateReportingService::ReportOutcome::DROPPED_OR_IGNORED),
        dropped_);
  }
  histogram_tester_.ExpectTotalCount(
      CertificateReportingService::kReportEventHistogram,
      submitted_ + failed_ + successful_ + dropped_);
}

void EventHistogramTester::SetExpectedValues(int submitted,
                                             int failed,
                                             int successful,
                                             int dropped) {
  submitted_ = submitted;
  failed_ = failed;
  successful_ = successful;
  dropped_ = dropped;
}

}  // namespace certificate_reporting_test_utils
