Index: third_party/crashpad/crashpad/client/crash_report_database_win.cc |
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_win.cc b/third_party/crashpad/crashpad/client/crash_report_database_win.cc |
index c3869c58f5b6cf699552ea8757050f4bd6c194f1..c0bc42b888159fa74b504eb77b56c4ce578d08c0 100644 |
--- a/third_party/crashpad/crashpad/client/crash_report_database_win.cc |
+++ b/third_party/crashpad/crashpad/client/crash_report_database_win.cc |
@@ -103,6 +103,14 @@ enum class ReportState { |
kCompleted, |
}; |
+enum { |
+ //! \brief Corresponds to uploaded bit of the report state. |
+ kAttributeUploaded = 1 << 0, |
+ |
+ //! \brief Corresponds to upload_explicity_requested bit of the report state. |
+ kAttributeUploadExplicitlyRequested = 1 << 1, |
+}; |
+ |
struct MetadataFileReportRecord { |
// Note that this default constructor does no initialization. It is used only |
// to create an array of records that are immediately initialized by reading |
@@ -121,7 +129,7 @@ struct MetadataFileReportRecord { |
int64_t last_upload_attempt_time; // Holds a time_t. |
int32_t upload_attempts; |
int32_t state; // A ReportState. |
- uint8_t uploaded; // Boolean, 0 or 1. |
+ uint8_t attributes; // Bitfield of kAttribute*. |
uint8_t padding[7]; |
}; |
@@ -151,7 +159,10 @@ MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report, |
last_upload_attempt_time(report.last_upload_attempt_time), |
upload_attempts(report.upload_attempts), |
state(static_cast<uint32_t>(report.state)), |
- uploaded(report.uploaded) { |
+ attributes((report.uploaded ? kAttributeUploaded : 0) | |
+ (report.upload_explicitly_requested |
+ ? kAttributeUploadExplicitlyRequested |
+ : 0)) { |
memset(&padding, 0, sizeof(padding)); |
} |
@@ -164,10 +175,12 @@ ReportDisk::ReportDisk(const MetadataFileReportRecord& record, |
base::UTF8ToUTF16(&string_table[record.file_path_index])); |
id = &string_table[record.id_index]; |
creation_time = record.creation_time; |
- uploaded = record.uploaded != 0; |
last_upload_attempt_time = record.last_upload_attempt_time; |
upload_attempts = record.upload_attempts; |
state = static_cast<ReportState>(record.state); |
+ uploaded = (record.attributes & kAttributeUploaded) != 0; |
+ upload_explicitly_requested = |
+ (record.attributes & kAttributeUploadExplicitlyRequested) != 0; |
} |
ReportDisk::ReportDisk(const UUID& uuid, |
@@ -577,6 +590,7 @@ class CrashReportDatabaseWin : public CrashReportDatabase { |
const std::string& id) override; |
OperationStatus SkipReportUpload(const UUID& uuid) override; |
OperationStatus DeleteReport(const UUID& uuid) override; |
+ OperationStatus RequestUpload(const UUID& uuid) override; |
private: |
std::unique_ptr<Metadata> AcquireMetadata(); |
@@ -773,8 +787,14 @@ OperationStatus CrashReportDatabaseWin::RecordUploadAttempt( |
report_disk->id = id; |
report_disk->last_upload_attempt_time = now; |
report_disk->upload_attempts++; |
- report_disk->state = |
- successful ? ReportState::kCompleted : ReportState::kPending; |
+ if (successful) { |
+ report_disk->state = ReportState::kCompleted; |
+ report_disk->upload_explicitly_requested = false; |
+ } else { |
+ report_disk->state = ReportState::kPending; |
+ report_disk->upload_explicitly_requested = |
+ report->upload_explicitly_requested; |
+ } |
if (!settings_.SetLastUploadAttemptTime(now)) |
return kDatabaseError; |
@@ -811,8 +831,10 @@ OperationStatus CrashReportDatabaseWin::SkipReportUpload(const UUID& uuid) { |
ReportDisk* report_disk; |
OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
uuid, ReportState::kPending, &report_disk); |
- if (os == kNoError) |
+ if (os == kNoError) { |
report_disk->state = ReportState::kCompleted; |
+ report_disk->upload_explicitly_requested = false; |
+ } |
return os; |
} |
@@ -831,6 +853,37 @@ std::unique_ptr<CrashReportDatabase> InitializeInternal( |
: std::unique_ptr<CrashReportDatabaseWin>(); |
} |
+OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ |
+ std::unique_ptr<Metadata> metadata(AcquireMetadata()); |
+ if (!metadata) |
+ return kDatabaseError; |
+ |
+ ReportDisk* report_disk; |
+ // TODO(gayane): Search for the report only once regardless of its state. |
+ OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
+ uuid, ReportState::kCompleted, &report_disk); |
+ if (os == kBusyError) { |
+ os = metadata->FindSingleReportAndMarkDirty( |
+ uuid, ReportState::kPending, &report_disk); |
+ } |
+ |
+ if (os != kNoError) |
+ return os; |
+ |
+ // If the crash report has already been uploaded, don't request new upload. |
+ if (report_disk->uploaded) |
+ return kCannotRequestUpload; |
+ |
+ // Mark the crash report as having upload explicitly requested by the user, |
+ // and move it to the pending state. |
+ report_disk->upload_explicitly_requested = true; |
+ report_disk->state = ReportState::kPending; |
+ |
+ return kNoError; |
+} |
+ |
} // namespace |
// static |