Index: third_party/crashpad/crashpad/client/crash_report_database_mac.mm |
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm |
index 4222078130e74f6dab0b15a9732ad025d3489cb7..9799bb0fa25d5677d0953e83fc28b37a017a9a97 100644 |
--- a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm |
+++ b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm |
@@ -47,9 +47,9 @@ const char kCompletedDirectory[] = "completed"; |
const char kSettings[] = "settings.dat"; |
const char* const kReportDirectories[] = { |
- kWriteDirectory, |
- kUploadPendingDirectory, |
- kCompletedDirectory, |
+ kWriteDirectory, |
+ kUploadPendingDirectory, |
+ kCompletedDirectory, |
}; |
const char kCrashReportFileExtension[] = "dmp"; |
@@ -60,6 +60,7 @@ const char kXattrCreationTime[] = "creation_time"; |
const char kXattrIsUploaded[] = "uploaded"; |
const char kXattrLastUploadTime[] = "last_upload_time"; |
const char kXattrUploadAttemptCount[] = "upload_count"; |
+const char kXattrIsUploadExplicitlyRequested[] = "upload_explicitly_requested"; |
const char kXattrDatabaseInitialized[] = "initialized"; |
@@ -140,6 +141,7 @@ class CrashReportDatabaseMac : 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: |
//! \brief A private extension of the Report class that maintains bookkeeping |
@@ -201,6 +203,18 @@ class CrashReportDatabaseMac : public CrashReportDatabase { |
//! \return The long name of the extended attribute. |
std::string XattrName(const base::StringPiece& name); |
+ //! \brief Marks a report with a given path as completed. |
+ //! |
+ //! Assumes that the report is locked. |
+ //! |
+ //! \param[in] report_path The path of the file to mark completed. |
+ //! \param[out] out_path The path of the new file. This parameter is optional. |
+ //! |
+ //! \return The operation status code. |
+ CrashReportDatabase::OperationStatus MarkReportCompletedLocked( |
+ const base::FilePath& report_path, |
+ base::FilePath* out_path); |
+ |
base::FilePath base_dir_; |
Settings settings_; |
bool xattr_new_names_; |
@@ -449,14 +463,10 @@ CrashReportDatabaseMac::RecordUploadAttempt(const Report* report, |
return kBusyError; |
if (successful) { |
- base::FilePath new_path = |
- base_dir_.Append(kCompletedDirectory).Append(report_path.BaseName()); |
- if (rename(report_path.value().c_str(), new_path.value().c_str()) != 0) { |
- PLOG(ERROR) << "rename " << report_path.value() << " to " |
- << new_path.value(); |
- return kFileSystemError; |
- } |
- report_path = new_path; |
+ CrashReportDatabase::OperationStatus os = |
+ MarkReportCompletedLocked(report_path, &report_path); |
+ if (os != kNoError) |
+ return os; |
} |
if (!WriteXattrBool(report_path, XattrName(kXattrIsUploaded), successful)) { |
@@ -500,15 +510,7 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::SkipReportUpload( |
if (!lock.is_valid()) |
return kBusyError; |
- base::FilePath new_path = |
- base_dir_.Append(kCompletedDirectory).Append(report_path.BaseName()); |
- if (rename(report_path.value().c_str(), new_path.value().c_str()) != 0) { |
- PLOG(ERROR) << "rename " << report_path.value() << " to " |
- << new_path.value(); |
- return kFileSystemError; |
- } |
- |
- return kNoError; |
+ return MarkReportCompletedLocked(report_path, nullptr); |
} |
CrashReportDatabase::OperationStatus CrashReportDatabaseMac::DeleteReport( |
@@ -556,6 +558,45 @@ base::FilePath CrashReportDatabaseMac::LocateCrashReport(const UUID& uuid) { |
return base::FilePath(); |
} |
+CrashReportDatabase::OperationStatus CrashReportDatabaseMac::RequestUpload( |
+ const UUID& uuid) { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ |
+ base::FilePath report_path = LocateCrashReport(uuid); |
+ if (report_path.empty()) |
+ return kReportNotFound; |
+ |
+ base::ScopedFD lock(ObtainReportLock(report_path)); |
+ if (!lock.is_valid()) |
+ return kBusyError; |
+ |
+ // If the crash report has already been uploaded, don't request new upload. |
+ bool uploaded = false; |
+ XattrStatus status = |
+ ReadXattrBool(report_path, XattrName(kXattrIsUploaded), &uploaded); |
+ if (status == XattrStatus::kOtherError) |
+ return kDatabaseError; |
+ if (uploaded) |
+ return kCannotRequestUpload; |
+ |
+ // Mark the crash report as having upload explicitly requested by the user, |
+ // and move it to the pending state. |
+ if (!WriteXattrBool( |
+ report_path, XattrName(kXattrIsUploadExplicitlyRequested), true)) { |
+ return kDatabaseError; |
+ } |
+ |
+ base::FilePath new_path = |
+ base_dir_.Append(kUploadPendingDirectory).Append(report_path.BaseName()); |
+ if (rename(report_path.value().c_str(), new_path.value().c_str()) != 0) { |
+ PLOG(ERROR) << "rename " << report_path.value() << " to " |
+ << new_path.value(); |
+ return kFileSystemError; |
+ } |
+ |
+ return kNoError; |
+} |
+ |
// static |
base::ScopedFD CrashReportDatabaseMac::ObtainReportLock( |
const base::FilePath& path) { |
@@ -604,6 +645,14 @@ bool CrashReportDatabaseMac::ReadReportMetadataLocked( |
return false; |
} |
+ report->upload_explicitly_requested = false; |
+ if (ReadXattrBool(path, |
+ XattrName(kXattrIsUploadExplicitlyRequested), |
+ &report->upload_explicitly_requested) == |
+ XattrStatus::kOtherError) { |
+ return false; |
+ } |
+ |
return true; |
} |
@@ -647,6 +696,28 @@ std::string CrashReportDatabaseMac::XattrName(const base::StringPiece& name) { |
return XattrNameInternal(name, xattr_new_names_); |
} |
+CrashReportDatabase::OperationStatus |
+CrashReportDatabaseMac::MarkReportCompletedLocked( |
+ const base::FilePath& report_path, |
+ base::FilePath* out_path) { |
+ if (RemoveXattr(report_path, XattrName(kXattrIsUploadExplicitlyRequested)) == |
+ XattrStatus::kOtherError) { |
+ return kDatabaseError; |
+ } |
+ |
+ base::FilePath new_path = |
+ base_dir_.Append(kCompletedDirectory).Append(report_path.BaseName()); |
+ if (rename(report_path.value().c_str(), new_path.value().c_str()) != 0) { |
+ PLOG(ERROR) << "rename " << report_path.value() << " to " |
+ << new_path.value(); |
+ return kFileSystemError; |
+ } |
+ |
+ if (out_path) |
+ *out_path = new_path; |
+ return kNoError; |
+} |
+ |
std::unique_ptr<CrashReportDatabase> InitializeInternal( |
const base::FilePath& path, |
bool may_create) { |