diff --git crashpad/client/prune_crash_reports.cc crashpad/client/prune_crash_reports.cc index 3aaaeee..d99fcb4 100644 --- crashpad/client/prune_crash_reports.cc +++ crashpad/client/prune_crash_reports.cc @@ -67,13 +67,19 @@ void PruneCrashReportDatabase(CrashReportDatabase* database, } // static -std::unique_ptr PruneCondition::GetDefault() { +std::unique_ptr PruneCondition::GetDefault( + int max_size_in_mb, + int max_age_in_days) { // DatabaseSizePruneCondition must be the LHS so that it is always evaluated, // due to the short-circuting behavior of BinaryPruneCondition. + if (max_size_in_mb <= 0) + max_size_in_mb = 128; + if (max_age_in_days <= 0) + max_age_in_days = 365; return base::WrapUnique( new BinaryPruneCondition(BinaryPruneCondition::OR, - new DatabaseSizePruneCondition(1024 * 128), - new AgePruneCondition(365))); + new DatabaseSizePruneCondition(max_size_in_mb), + new AgePruneCondition(max_age_in_days))); } static const time_t kSecondsInDay = 60 * 60 * 24; diff --git crashpad/client/prune_crash_reports.h crashpad/client/prune_crash_reports.h index 6dac5f3..34f5ee1 100644 --- crashpad/client/prune_crash_reports.h +++ crashpad/client/prune_crash_reports.h @@ -57,7 +57,8 @@ class PruneCondition { //! of 128 MB. //! //! \return A PruneCondition for use with PruneCrashReportDatabase(). - static std::unique_ptr GetDefault(); + static std::unique_ptr GetDefault(int max_size_in_mb, + int max_age_in_days); virtual ~PruneCondition() {} diff --git crashpad/client/settings.cc crashpad/client/settings.cc index 7757ecb..d458337 100644 --- crashpad/client/settings.cc +++ crashpad/client/settings.cc @@ -38,7 +38,7 @@ void ScopedLockedFileHandleTraits::Free(FileHandle handle) { struct Settings::Data { static const uint32_t kSettingsMagic = 'CPds'; - static const uint32_t kSettingsVersion = 1; + static const uint32_t kSettingsVersion = 2; enum Options : uint32_t { kUploadsEnabled = 1 << 0, @@ -49,6 +49,9 @@ struct Settings::Data { options(0), padding_0(0), last_upload_attempt_time(0), + next_upload_attempt_time(0), + backoff_step(0), + padding_1(0), client_id() {} uint32_t magic; @@ -56,6 +59,9 @@ struct Settings::Data { uint32_t options; uint32_t padding_0; int64_t last_upload_attempt_time; // time_t + int64_t next_upload_attempt_time; // time_t + uint32_t backoff_step; + uint32_t padding_1; UUID client_id; }; @@ -141,6 +147,56 @@ bool Settings::SetLastUploadAttemptTime(time_t time) { return WriteSettings(handle.get(), settings); } +bool Settings::GetNextUploadAttemptTime(time_t* time) { + DCHECK(initialized_.is_valid()); + + Data settings; + if (!OpenAndReadSettings(&settings)) + return false; + + *time = InRangeCast(settings.next_upload_attempt_time, + std::numeric_limits::max()); + return true; +} + +bool Settings::SetNextUploadAttemptTime(time_t time) { + DCHECK(initialized_.is_valid()); + + Data settings; + ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings); + if (!handle.is_valid()) + return false; + + settings.next_upload_attempt_time = InRangeCast(time, 0); + + return WriteSettings(handle.get(), settings); +} + +bool Settings::GetBackoffStep(int* step) { + DCHECK(initialized_.is_valid()); + + Data settings; + if (!OpenAndReadSettings(&settings)) + return false; + + *step = InRangeCast(settings.backoff_step, + std::numeric_limits::max()); + return true; +} + +bool Settings::SetBackoffStep(int step) { + DCHECK(initialized_.is_valid()); + + Data settings; + ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings); + if (!handle.is_valid()) + return false; + + settings.backoff_step = InRangeCast(step, 0); + + return WriteSettings(handle.get(), settings); +} + // static Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle( FileHandle file, diff --git crashpad/client/settings.h crashpad/client/settings.h index b64f74f..0c3c22e 100644 --- crashpad/client/settings.h +++ crashpad/client/settings.h @@ -102,6 +102,11 @@ class Settings { //! error logged. bool SetLastUploadAttemptTime(time_t time); + bool GetNextUploadAttemptTime(time_t* time); + bool SetNextUploadAttemptTime(time_t time); + bool GetBackoffStep(int* step); + bool SetBackoffStep(int step); + private: struct Data; diff --git crashpad/handler/crash_report_upload_thread.h crashpad/handler/crash_report_upload_thread.h index 14debac..c25c653 100644 --- crashpad/handler/crash_report_upload_thread.h +++ crashpad/handler/crash_report_upload_thread.h @@ -78,7 +78,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate { //! This method may be called from any thread. void ReportPending(); - private: + protected: //! \brief The result code from UploadReport(). enum class UploadResult { //! \brief The crash report was uploaded successfully. @@ -101,7 +101,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate { //! \brief Obtains all pending reports from the database, and calls //! ProcessPendingReport() to process each one. - void ProcessPendingReports(); + virtual void ProcessPendingReports(); //! \brief Processes a single pending report from the database. //! @@ -115,7 +115,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate { //! remain in the “pending” state. If the upload fails and no more retries are //! desired, or report upload is disabled, it will be marked as “completed” in //! the database without ever having been uploaded. - void ProcessPendingReport(const CrashReportDatabase::Report& report); + virtual void ProcessPendingReport(const CrashReportDatabase::Report& report); //! \brief Attempts to upload a crash report. //! diff --git crashpad/handler/handler_main.cc crashpad/handler/handler_main.cc index 5006cf6..26b3b6a 100644 --- crashpad/handler/handler_main.cc +++ crashpad/handler/handler_main.cc @@ -33,8 +33,10 @@ #include "base/logging.h" #include "base/metrics/persistent_histogram_allocator.h" #include "base/scoped_generic.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "cef/libcef/features/features.h" #include "client/crash_report_database.h" #include "client/crashpad_client.h" #include "client/prune_crash_reports.h" @@ -69,6 +71,10 @@ #include "util/win/session_end_watcher.h" #endif // OS_MACOSX +#if BUILDFLAG(ENABLE_CEF) +#include "cef/libcef/common/cef_crash_report_upload_thread.h" +#endif + namespace crashpad { namespace { @@ -403,6 +409,9 @@ int HandlerMain(int argc, char* argv[]) { kOptionPipeName, #endif // OS_MACOSX kOptionURL, + kOptionMaxUploads, + kOptionMaxDatabaseSize, + kOptionMaxDatabaseAge, // Standard options. kOptionHelp = -2, @@ -424,12 +433,18 @@ int HandlerMain(int argc, char* argv[]) { #endif // OS_MACOSX bool rate_limit; bool upload_gzip; + int max_uploads; + int max_database_size; + int max_database_age; } options = {}; #if defined(OS_MACOSX) options.handshake_fd = -1; #endif options.rate_limit = true; options.upload_gzip = true; + options.max_uploads = 0; + options.max_database_size = 0; + options.max_database_age = 0; const option long_options[] = { {"annotation", required_argument, nullptr, kOptionAnnotation}, @@ -460,6 +475,9 @@ int HandlerMain(int argc, char* argv[]) { {"url", required_argument, nullptr, kOptionURL}, {"help", no_argument, nullptr, kOptionHelp}, {"version", no_argument, nullptr, kOptionVersion}, + {"max-uploads", required_argument, nullptr, kOptionMaxUploads}, + {"max-db-size", required_argument, nullptr, kOptionMaxDatabaseSize}, + {"max-db-age", required_argument, nullptr, kOptionMaxDatabaseAge}, {nullptr, 0, nullptr, 0}, }; @@ -535,6 +553,27 @@ int HandlerMain(int argc, char* argv[]) { options.url = optarg; break; } + case kOptionMaxUploads: { + if (base::StringToInt(optarg, &options.max_uploads)) { + if (options.max_uploads < 0) + options.max_uploads = 0; + } + break; + } + case kOptionMaxDatabaseSize: { + if (base::StringToInt(optarg, &options.max_database_size)) { + if (options.max_database_size < 0) + options.max_database_size = 0; + } + break; + } + case kOptionMaxDatabaseAge: { + if (base::StringToInt(optarg, &options.max_database_age)) { + if (options.max_database_age < 0) + options.max_database_age = 0; + } + break; + } case kOptionHelp: { Usage(me); MetricsRecordExit(Metrics::LifetimeMilestone::kExitedEarly); @@ -672,12 +711,19 @@ int HandlerMain(int argc, char* argv[]) { // TODO(scottmg): options.rate_limit should be removed when we have a // configurable database setting to control upload limiting. // See https://crashpad.chromium.org/bug/23. +#if BUILDFLAG(ENABLE_CEF) + CefCrashReportUploadThread upload_thread( + database.get(), options.url, options.rate_limit, options.upload_gzip, + options.max_uploads); +#else CrashReportUploadThread upload_thread( database.get(), options.url, options.rate_limit, options.upload_gzip); +#endif upload_thread.Start(); PruneCrashReportThread prune_thread(database.get(), - PruneCondition::GetDefault()); + PruneCondition::GetDefault(options.max_database_size, + options.max_database_age)); prune_thread.Start(); CrashReportExceptionHandler exception_handler( diff --git crashpad/util/net/http_transport_win.cc crashpad/util/net/http_transport_win.cc index 294048a..e87e47e 100644 --- crashpad/util/net/http_transport_win.cc +++ crashpad/util/net/http_transport_win.cc @@ -146,7 +146,7 @@ bool HTTPTransportWin::ExecuteSynchronously(std::string* response_body) { ScopedHINTERNET request(WinHttpOpenRequest( connect.get(), base::UTF8ToUTF16(method()).c_str(), - url_path.c_str(), + (url_path + extra_info).c_str(), nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES,