// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CRASH_REPORTER_CRASH_SENDER_UTIL_H_
#define CRASH_REPORTER_CRASH_SENDER_UTIL_H_

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

#include <base/files/file.h>
#include <base/files/file_path.h>
#include <base/optional.h>
#include <base/time/clock.h>
#include <base/time/time.h>
#include <base/values.h>
#include <brillo/http/http_form_data.h>
#include <brillo/http/http_transport.h>
#include <gtest/gtest_prod.h>  // for FRIEND_TEST
#include <metrics/metrics_library.h>
#include <session_manager/dbus-proxies.h>
#include <shill/dbus-proxies.h>

#include "crash-reporter/crash_sender_base.h"

namespace util {

// URL to send official build crash reports to.
constexpr char kReportUploadProdUrl[] = "https://clients2.google.com/cr/report";

// URL to send test/dev build crash reports to.
constexpr char kReportUploadStagingUrl[] =
    "https://clients2.google.com/cr/staging_report";

// Maximum crashes to send per 24 hours.
constexpr int kMaxCrashRate = 32;

// Maximum bytes of crash reports to send per 24 hours. Note that "whichever
// comes last" maximum with kMaxCrashRate; that is, we'll always send 32 crashes
// per 24 hours, even if that exceeds 24MB, and we'll always send 24MB per 24
// hours, even if that exceeds 32 crashes.
constexpr int kMaxCrashBytes = 24 * 1024 * 1024;

// Maximum time to sleep before attempting to send a crash report. This value is
// inclusive as an upper bound, thus 0 means a crash report can be sent
// immediately.
constexpr int kMaxSpreadTimeInSeconds = 600;

// Parsed command line flags.
struct CommandLineFlags {
  base::TimeDelta max_spread_time;
  std::string crash_directory;
  bool ignore_rate_limits = false;
  bool ignore_hold_off_time = false;
  bool allow_dev_sending = false;
  bool ignore_pause_file = false;
  bool test_mode = false;
  bool upload_old_reports = false;
  bool force_upload_on_test_images = false;
};

// Represents a metadata file name, and its parsed metadata.
typedef std::pair<base::FilePath, CrashInfo> MetaFile;

// Parses the command line, and handles the command line flags.
//
// On error, the process exits as a failure with an error message for the
// first-encountered error.
void ParseCommandLine(int argc,
                      const char* const* argv,
                      CommandLineFlags* flags);

// Returns true if the marker file exists indicating we should pause sending.
// This can be overridden with a command line flag to the program.
bool DoesPauseFileExist();

// Gets the base part of a crash report file, such as:
// name.01234.5678.9012.meta -> name.01234.5678.9012
// name.01234.5678.1234.9012.meta -> name.01234.5678.1234.9012
// name.01234.5678.9012.log.tar.xz -> name.01234.5678.9012
// name.01234.5678.1234.9012.log.tar.xz -> name.01234.5678.1234.9012
// This supports both 4-segment and 5-segment basenames, as long as the last
// segment always is numeric and the extension does not start with an
// all-numeric component.
//
// We make sure "name" is sanitized in CrashCollector::Sanitize to not include
// any periods. The directory part will be preserved.
base::FilePath GetBasePartOfCrashFile(const base::FilePath& file_name);

// Removes orphaned files in |crash_dir|, that are files 24 hours old or older,
// without corresponding meta file.
void RemoveOrphanedCrashFiles(const base::FilePath& crash_dir);

// Sort the vector of crash reports so that the report we want to send first
// is at the front of the vector.
void SortReports(std::vector<MetaFile>* reports);

// Returns the list of meta data files (files with ".meta" suffix), sorted by
// the timestamp in the old-to-new order.
std::vector<base::FilePath> GetMetaFiles(const base::FilePath& crash_dir);

// Returns true if the metadata indicates that the crash was already uploaded.
bool IsAlreadyUploaded(const base::FilePath& meta_file);

// Returns true if the given timestamp file is new enough, indicating that there
// was a recent attempt to send a crash report.
bool IsTimestampNewEnough(const base::FilePath& timestamp_file);

// Returns true if sending a crash report now does not exceed |max_crash_rate|
// crashes and |max_crash_bytes| bytes per 24 hours.
//
// |timestamps_dir| contains the state files indicating how many sends have
// happened and how big they were.
bool IsBelowRate(const base::FilePath& timestamps_dir,
                 int max_crash_rate,
                 int max_crash_bytes);

// Records a crash send attempt so that IsBelowRate knows about it.
// |timestamps_dir| should be the same directory passed to IsBelowRate().
// |bytes| is the number of bytes sent over the network.
void RecordSendAttempt(const base::FilePath& timestamps_dir, int bytes);

// A helper class for sending crashes. The behaviors can be customized with
// Options class for unit testing.
//
// Crash reports will be sent even when the device is on a mobile data
// connection (see crbug.com/185110 for discussion).
class Sender : public SenderBase {
 public:
  struct Options : SenderBase::Options {
    // Shill FlimFlam Manager proxy interface for determining network state.
    org::chromium::flimflam::ManagerProxyInterface* shill_proxy = nullptr;

    // Maximum crashes to send per 24 hours. (We'll send more if still below
    // max_crash_bytes.)
    int max_crash_rate = kMaxCrashRate;

    // Maximum bytes we will upload per 24 hours. (We'll send more if still
    // below max_crash_rate.)
    int max_crash_bytes = kMaxCrashBytes;

    // Maximum time to sleep before attempting to send.
    base::TimeDelta max_spread_time;

    // Boundary to use in the form data.
    std::string form_data_boundary;

    // If true, we will ignore other checks when deciding if we should write to
    // the Chrome uploads.log file.
    bool always_write_uploads_log = false;

    // If true, we allow sending crash reports for unofficial test images and
    // the reports are uploaded to a staging crash server instead.
    bool allow_dev_sending = false;

    // If true, just touch the kTestModeSuccessfulFile if the crash report
    // looks legible instead of actually uploading it.
    bool test_mode = false;

    // If true, ignore timestamp check and upload old reports.
    bool upload_old_reports = false;

    // If true, always upload on test images and add a flag to the metadata
    // indicating that it's from a test image.
    bool force_upload_on_test_images = false;
  };

  Sender(std::unique_ptr<MetricsLibraryInterface> metrics_lib,
         std::unique_ptr<base::Clock> clock,
         const Options& options);
  Sender(const Sender&) = delete;
  Sender& operator=(const Sender&) = delete;

  // Chooses an action to take for the crash report associated with the given
  // meta file, and reports the reason. The crash information will be stored in
  // |info| for reuse.
  SenderBase::Action ChooseAction(const base::FilePath& meta_file,
                                  std::string* reason,
                                  CrashInfo* info);

  // Removes invalid files in |crash_dir|, that are unknown, corrupted, or
  // invalid in other ways, and picks crash reports that should be sent to the
  // server. The meta files of the latter will be stored in |to_send|.
  void RemoveAndPickCrashFiles(const base::FilePath& directory,
                               std::vector<MetaFile>* reports_to_send);

  // Creates an Http transport object for invoking the Crash Server.
  virtual std::shared_ptr<brillo::http::Transport> GetTransport();

  // Sends each crash in |crash_meta_files|, in multiple steps:
  //
  // For each meta file:
  // - Sleeps to avoid overloading the network
  // - Checks if the device enters guest mode, and stops if entered.
  // - Enforces the rate limit per 24 hours.
  // - Removes crash files that are successfully uploaded.
  void SendCrashes(const std::vector<MetaFile>& crash_meta_files);

  // Given the |details| for a crash, creates a brillo::http::FormData object
  // which will have all of the fields for submission to the crash server
  // populated. Returns a nullptr if there were critical errors in populating
  // the data. This also logs out all of the details during the process. On
  // success, |product_name_out| is also set to the product name (it's not
  // possible to extract data from the returned FormData object in a
  // non-destructive manner).
  std::unique_ptr<brillo::http::FormData> CreateCrashFormData(
      const CrashDetails& details, std::string* product_name_out);

 private:
  friend class IsNetworkOnlineTest;
  FRIEND_TEST(CrashSenderUtilTest, RemoveReportFiles);
  FRIEND_TEST(CrashSenderUtilTest, FailRemoveReportFilesSendsMetric);

  // Removes report files associated with the given meta file.
  // More specifically, if "foo.meta" is given, "foo.*" will be removed.
  void RemoveReportFiles(const base::FilePath& meta_file);

  // Send the specified reason for removing a crash to UMA.
  void RecordCrashRemoveReason(SenderBase::CrashRemoveReason reason) override;

  // Creates a JSON entity with the required fields for uploads.log file.
  std::unique_ptr<base::Value> CreateJsonEntity(const std::string& report_id,
                                                const std::string& product_name,
                                                const CrashDetails& details);

  // Requests to send a crash report represented with the given crash details.
  // If the return code is kRetryUploading, the failure can be retried and the
  // caller should not remove the crash report. Otherwise, the caller should
  // remove the crash report using the returned removal reason code.
  SenderBase::CrashRemoveReason RequestToSendCrash(const CrashDetails& details);

  // Returns true if we have consent to send crashes to Google.
  bool HasCrashUploadingConsent();

  // Is this a "safe" device coredump, from an allowlist of driver names
  // for devices whose device coredump does not contain PII?
  bool IsSafeDeviceCoredump(const CrashInfo& info);

  // Checks if we have an online connection state so we can try sending crash
  // reports.
  bool IsNetworkOnline();

  std::unique_ptr<MetricsLibraryInterface> metrics_lib_;
  std::unique_ptr<org::chromium::flimflam::ManagerProxyInterface> shill_proxy_;
  std::vector<std::string> proxy_servers_;
  std::string form_data_boundary_;
  bool always_write_uploads_log_;
  const int max_crash_rate_;
  const int max_crash_bytes_;
  const base::TimeDelta max_spread_time_;
  bool allow_dev_sending_;
  const bool test_mode_;
  const bool upload_old_reports_;
  const bool force_upload_on_test_images_;
};

}  // namespace util

#endif  // CRASH_REPORTER_CRASH_SENDER_UTIL_H_
