// Copyright 2016 The Chromium Embedded Framework 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 "libcef/common/cef_crash_report_upload_thread.h"

#include "libcef/common/cef_crash_report_utils.h"
#include "third_party/crashpad/crashpad/client/settings.h"

using namespace crashpad;

CefCrashReportUploadThread::CefCrashReportUploadThread(
    CrashReportDatabase* database,
    const std::string& url,
    const Options& options,
    int max_uploads)
    : CrashReportUploadThread(database, url, options),
      max_uploads_(max_uploads) {}

CefCrashReportUploadThread::~CefCrashReportUploadThread() {}

void CefCrashReportUploadThread::ProcessPendingReports() {
  if (BackoffPending()) {
    // Try again later.
    return;
  }

  if (MaxUploadsEnabled()) {
    // Retrieve all completed reports.
    std::vector<CrashReportDatabase::Report> reports;
    if (database_->GetCompletedReports(&reports) !=
        CrashReportDatabase::kNoError) {
      // The database is sick. It might be prudent to stop trying to poke it
      // from this thread by abandoning the thread altogether. On the other
      // hand, if the problem is transient, it might be possible to talk to it
      // again on the next pass. For now, take the latter approach.
      return;
    }

    const time_t now = time(nullptr);
    const int kSeconds = 60 * 60 * 24;  // 24 hours

    // Count how many reports have completed in the last 24 hours.
    recent_upload_ct_ = 0;
    for (const CrashReportDatabase::Report& report : reports) {
      if (report.last_upload_attempt_time > now - kSeconds)
        recent_upload_ct_++;
    }
  }

  // Continue with processing pending reports.
  CrashReportUploadThread::ProcessPendingReports();
}

void CefCrashReportUploadThread::ProcessPendingReport(
    const CrashReportDatabase::Report& report) {
  // Always allow upload if it's been explicitly requested by the user.
  if (!report.upload_explicitly_requested) {
    if (!UploadsEnabled()) {
      // Don’t attempt an upload if there’s no URL or if uploads have been
      // disabled in the database’s settings.
      database_->SkipReportUpload(
          report.uuid, Metrics::CrashSkippedReason::kUploadsDisabled);
      return;
    }

    if (MaxUploadsExceeded()) {
      // Don't send uploads if the rate limit has been exceeded.
      database_->SkipReportUpload(
          report.uuid, Metrics::CrashSkippedReason::kUploadThrottled);
      return;
    }
  }

  if (BackoffPending()) {
    // Try again later.
    return;
  }

  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
  CrashReportDatabase::OperationStatus status =
      database_->GetReportForUploading(report.uuid, &upload_report);
  switch (status) {
    case CrashReportDatabase::kNoError:
      break;

    case CrashReportDatabase::kBusyError:
      return;

    case CrashReportDatabase::kReportNotFound:
    case CrashReportDatabase::kFileSystemError:
    case CrashReportDatabase::kDatabaseError:
      // In these cases, SkipReportUpload() might not work either, but it’s best
      // to at least try to get the report out of the way.
      database_->SkipReportUpload(report.uuid,
                                  Metrics::CrashSkippedReason::kDatabaseError);
      return;

    case CrashReportDatabase::kCannotRequestUpload:
      NOTREACHED();
      return;
  }

  std::string response_body;
  UploadResult upload_result =
      UploadReport(upload_report.get(), &response_body);
  switch (upload_result) {
    case UploadResult::kSuccess:
      // The upload completed successfully.
      database_->RecordUploadComplete(std::move(upload_report), response_body);
      if (MaxUploadsEnabled())
        recent_upload_ct_++;
      ResetBackoff();
      break;
    case UploadResult::kPermanentFailure:
      // The upload should never be retried.
      database_->SkipReportUpload(report.uuid,
                                  Metrics::CrashSkippedReason::kUploadFailed);
      break;
    case UploadResult::kRetry:
      // The upload will be retried after a reasonable backoff delay. Since we
      // didn't successfully upload it we won't count it against the rate limit.
      IncreaseBackoff();
      break;
  }
}

CrashReportUploadThread::ParameterMap
CefCrashReportUploadThread::FilterParameters(const ParameterMap& parameters) {
  return crash_report_utils::FilterParameters(parameters);
}

bool CefCrashReportUploadThread::UploadsEnabled() const {
  Settings* const settings = database_->GetSettings();
  bool uploads_enabled;
  return !url_.empty() && settings->GetUploadsEnabled(&uploads_enabled) &&
         uploads_enabled;
}

bool CefCrashReportUploadThread::MaxUploadsEnabled() const {
  return options_.rate_limit && max_uploads_ > 0;
}

bool CefCrashReportUploadThread::MaxUploadsExceeded() const {
  return MaxUploadsEnabled() && recent_upload_ct_ >= max_uploads_;
}

bool CefCrashReportUploadThread::BackoffPending() const {
  if (!options_.rate_limit)
    return false;

  Settings* const settings = database_->GetSettings();

  time_t next_upload_time;
  if (settings->GetNextUploadAttemptTime(&next_upload_time) &&
      next_upload_time > 0) {
    const time_t now = time(nullptr);
    if (now < next_upload_time)
      return true;
  }

  return false;
}

void CefCrashReportUploadThread::IncreaseBackoff() {
  if (!options_.rate_limit)
    return;

  const int kHour = 60 * 60;  // 1 hour
  const int kBackoffSchedule[] = {
      kHour / 4,   // 15 minutes
      kHour,       // 1 hour
      kHour * 2,   // 2 hours
      kHour * 4,   // 4 hours
      kHour * 8,   // 8 hours
      kHour * 24,  // 24 hours
  };
  const int kBackoffScheduleSize =
      sizeof(kBackoffSchedule) / sizeof(kBackoffSchedule[0]);

  Settings* settings = database_->GetSettings();

  int backoff_step = 0;
  if (settings->GetBackoffStep(&backoff_step) && backoff_step < 0)
    backoff_step = 0;
  if (++backoff_step > kBackoffScheduleSize)
    backoff_step = kBackoffScheduleSize;

  time_t next_upload_time = time(nullptr);  // now
  next_upload_time += kBackoffSchedule[backoff_step - 1];

  settings->SetBackoffStep(backoff_step);
  settings->SetNextUploadAttemptTime(next_upload_time);

  if (max_uploads_ > 1) {
    // If the server is having trouble then we don't want to send many crash
    // reports after the backoff expires. Reduce max uploads to 1 per 24 hours
    // until the client is restarted.
    max_uploads_ = 1;
  }
}

void CefCrashReportUploadThread::ResetBackoff() {
  if (!options_.rate_limit)
    return;

  Settings* settings = database_->GetSettings();
  settings->SetBackoffStep(0);
  settings->SetNextUploadAttemptTime(0);
}
