| OLD | NEW |
| 1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 | 96 |
| 97 enum class ReportState { | 97 enum class ReportState { |
| 98 //! \brief Created and filled out by caller, owned by database. | 98 //! \brief Created and filled out by caller, owned by database. |
| 99 kPending, | 99 kPending, |
| 100 //! \brief In the process of uploading, owned by caller. | 100 //! \brief In the process of uploading, owned by caller. |
| 101 kUploading, | 101 kUploading, |
| 102 //! \brief Upload completed or skipped, owned by database. | 102 //! \brief Upload completed or skipped, owned by database. |
| 103 kCompleted, | 103 kCompleted, |
| 104 }; | 104 }; |
| 105 | 105 |
| 106 enum { |
| 107 //! \brief Corresponds to uploaded bit of the report state. |
| 108 kAttributeUploaded = 1 << 0, |
| 109 |
| 110 //! \brief Corresponds to upload_explicity_requested bit of the report state. |
| 111 kAttributeUploadExplicitlyRequested = 1 << 1, |
| 112 }; |
| 113 |
| 106 struct MetadataFileReportRecord { | 114 struct MetadataFileReportRecord { |
| 107 // Note that this default constructor does no initialization. It is used only | 115 // Note that this default constructor does no initialization. It is used only |
| 108 // to create an array of records that are immediately initialized by reading | 116 // to create an array of records that are immediately initialized by reading |
| 109 // from disk in Metadata::Read(). | 117 // from disk in Metadata::Read(). |
| 110 MetadataFileReportRecord() {} | 118 MetadataFileReportRecord() {} |
| 111 | 119 |
| 112 // Constructs from a ReportDisk, adding to |string_table| and storing indices | 120 // Constructs from a ReportDisk, adding to |string_table| and storing indices |
| 113 // as strings into that table. | 121 // as strings into that table. |
| 114 MetadataFileReportRecord(const ReportDisk& report, std::string* string_table); | 122 MetadataFileReportRecord(const ReportDisk& report, std::string* string_table); |
| 115 | 123 |
| 116 UUID uuid; // UUID is a 16 byte, standard layout structure. | 124 UUID uuid; // UUID is a 16 byte, standard layout structure. |
| 117 uint32_t file_path_index; // Index into string table. File name is relative | 125 uint32_t file_path_index; // Index into string table. File name is relative |
| 118 // to the reports directory when on disk. | 126 // to the reports directory when on disk. |
| 119 uint32_t id_index; // Index into string table. | 127 uint32_t id_index; // Index into string table. |
| 120 int64_t creation_time; // Holds a time_t. | 128 int64_t creation_time; // Holds a time_t. |
| 121 int64_t last_upload_attempt_time; // Holds a time_t. | 129 int64_t last_upload_attempt_time; // Holds a time_t. |
| 122 int32_t upload_attempts; | 130 int32_t upload_attempts; |
| 123 int32_t state; // A ReportState. | 131 int32_t state; // A ReportState. |
| 124 uint8_t uploaded; // Boolean, 0 or 1. | 132 uint8_t attributes; // Bitfield of kAttribute*. |
| 125 uint8_t padding[7]; | 133 uint8_t padding[7]; |
| 126 }; | 134 }; |
| 127 | 135 |
| 128 //! \brief A private extension of the Report class that includes additional data | 136 //! \brief A private extension of the Report class that includes additional data |
| 129 //! that's stored on disk in the metadata file. | 137 //! that's stored on disk in the metadata file. |
| 130 struct ReportDisk : public CrashReportDatabase::Report { | 138 struct ReportDisk : public CrashReportDatabase::Report { |
| 131 ReportDisk(const MetadataFileReportRecord& record, | 139 ReportDisk(const MetadataFileReportRecord& record, |
| 132 const base::FilePath& report_dir, | 140 const base::FilePath& report_dir, |
| 133 const std::string& string_table); | 141 const std::string& string_table); |
| 134 | 142 |
| 135 ReportDisk(const UUID& uuid, | 143 ReportDisk(const UUID& uuid, |
| 136 const base::FilePath& path, | 144 const base::FilePath& path, |
| 137 time_t creation_tim, | 145 time_t creation_tim, |
| 138 ReportState state); | 146 ReportState state); |
| 139 | 147 |
| 140 //! \brief The current state of the report. | 148 //! \brief The current state of the report. |
| 141 ReportState state; | 149 ReportState state; |
| 142 }; | 150 }; |
| 143 | 151 |
| 144 MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report, | 152 MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report, |
| 145 std::string* string_table) | 153 std::string* string_table) |
| 146 : uuid(report.uuid), | 154 : uuid(report.uuid), |
| 147 file_path_index( | 155 file_path_index( |
| 148 AddStringToTable(string_table, report.file_path.BaseName().value())), | 156 AddStringToTable(string_table, report.file_path.BaseName().value())), |
| 149 id_index(AddStringToTable(string_table, report.id)), | 157 id_index(AddStringToTable(string_table, report.id)), |
| 150 creation_time(report.creation_time), | 158 creation_time(report.creation_time), |
| 151 last_upload_attempt_time(report.last_upload_attempt_time), | 159 last_upload_attempt_time(report.last_upload_attempt_time), |
| 152 upload_attempts(report.upload_attempts), | 160 upload_attempts(report.upload_attempts), |
| 153 state(static_cast<uint32_t>(report.state)), | 161 state(static_cast<uint32_t>(report.state)), |
| 154 uploaded(report.uploaded) { | 162 attributes((report.uploaded ? kAttributeUploaded : 0) | |
| 163 (report.upload_explicitly_requested |
| 164 ? kAttributeUploadExplicitlyRequested |
| 165 : 0)) { |
| 155 memset(&padding, 0, sizeof(padding)); | 166 memset(&padding, 0, sizeof(padding)); |
| 156 } | 167 } |
| 157 | 168 |
| 158 ReportDisk::ReportDisk(const MetadataFileReportRecord& record, | 169 ReportDisk::ReportDisk(const MetadataFileReportRecord& record, |
| 159 const base::FilePath& report_dir, | 170 const base::FilePath& report_dir, |
| 160 const std::string& string_table) | 171 const std::string& string_table) |
| 161 : Report() { | 172 : Report() { |
| 162 uuid = record.uuid; | 173 uuid = record.uuid; |
| 163 file_path = report_dir.Append( | 174 file_path = report_dir.Append( |
| 164 base::UTF8ToUTF16(&string_table[record.file_path_index])); | 175 base::UTF8ToUTF16(&string_table[record.file_path_index])); |
| 165 id = &string_table[record.id_index]; | 176 id = &string_table[record.id_index]; |
| 166 creation_time = record.creation_time; | 177 creation_time = record.creation_time; |
| 167 uploaded = record.uploaded != 0; | |
| 168 last_upload_attempt_time = record.last_upload_attempt_time; | 178 last_upload_attempt_time = record.last_upload_attempt_time; |
| 169 upload_attempts = record.upload_attempts; | 179 upload_attempts = record.upload_attempts; |
| 170 state = static_cast<ReportState>(record.state); | 180 state = static_cast<ReportState>(record.state); |
| 181 uploaded = (record.attributes & kAttributeUploaded) != 0; |
| 182 upload_explicitly_requested = |
| 183 (record.attributes & kAttributeUploadExplicitlyRequested) != 0; |
| 171 } | 184 } |
| 172 | 185 |
| 173 ReportDisk::ReportDisk(const UUID& uuid, | 186 ReportDisk::ReportDisk(const UUID& uuid, |
| 174 const base::FilePath& path, | 187 const base::FilePath& path, |
| 175 time_t creation_time, | 188 time_t creation_time, |
| 176 ReportState state) | 189 ReportState state) |
| 177 : Report() { | 190 : Report() { |
| 178 this->uuid = uuid; | 191 this->uuid = uuid; |
| 179 this->file_path = path; | 192 this->file_path = path; |
| 180 this->creation_time = creation_time; | 193 this->creation_time = creation_time; |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; | 583 OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; |
| 571 OperationStatus GetPendingReports(std::vector<Report>* reports) override; | 584 OperationStatus GetPendingReports(std::vector<Report>* reports) override; |
| 572 OperationStatus GetCompletedReports(std::vector<Report>* reports) override; | 585 OperationStatus GetCompletedReports(std::vector<Report>* reports) override; |
| 573 OperationStatus GetReportForUploading(const UUID& uuid, | 586 OperationStatus GetReportForUploading(const UUID& uuid, |
| 574 const Report** report) override; | 587 const Report** report) override; |
| 575 OperationStatus RecordUploadAttempt(const Report* report, | 588 OperationStatus RecordUploadAttempt(const Report* report, |
| 576 bool successful, | 589 bool successful, |
| 577 const std::string& id) override; | 590 const std::string& id) override; |
| 578 OperationStatus SkipReportUpload(const UUID& uuid) override; | 591 OperationStatus SkipReportUpload(const UUID& uuid) override; |
| 579 OperationStatus DeleteReport(const UUID& uuid) override; | 592 OperationStatus DeleteReport(const UUID& uuid) override; |
| 593 OperationStatus RequestUpload(const UUID& uuid) override; |
| 580 | 594 |
| 581 private: | 595 private: |
| 582 std::unique_ptr<Metadata> AcquireMetadata(); | 596 std::unique_ptr<Metadata> AcquireMetadata(); |
| 583 | 597 |
| 584 base::FilePath base_dir_; | 598 base::FilePath base_dir_; |
| 585 Settings settings_; | 599 Settings settings_; |
| 586 InitializationStateDcheck initialized_; | 600 InitializationStateDcheck initialized_; |
| 587 | 601 |
| 588 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseWin); | 602 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseWin); |
| 589 }; | 603 }; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 report->uuid, ReportState::kUploading, &report_disk); | 780 report->uuid, ReportState::kUploading, &report_disk); |
| 767 if (os != kNoError) | 781 if (os != kNoError) |
| 768 return os; | 782 return os; |
| 769 | 783 |
| 770 time_t now = time(nullptr); | 784 time_t now = time(nullptr); |
| 771 | 785 |
| 772 report_disk->uploaded = successful; | 786 report_disk->uploaded = successful; |
| 773 report_disk->id = id; | 787 report_disk->id = id; |
| 774 report_disk->last_upload_attempt_time = now; | 788 report_disk->last_upload_attempt_time = now; |
| 775 report_disk->upload_attempts++; | 789 report_disk->upload_attempts++; |
| 776 report_disk->state = | 790 if (successful) { |
| 777 successful ? ReportState::kCompleted : ReportState::kPending; | 791 report_disk->state = ReportState::kCompleted; |
| 792 report_disk->upload_explicitly_requested = false; |
| 793 } else { |
| 794 report_disk->state = ReportState::kPending; |
| 795 report_disk->upload_explicitly_requested = |
| 796 report->upload_explicitly_requested; |
| 797 } |
| 778 | 798 |
| 779 if (!settings_.SetLastUploadAttemptTime(now)) | 799 if (!settings_.SetLastUploadAttemptTime(now)) |
| 780 return kDatabaseError; | 800 return kDatabaseError; |
| 781 | 801 |
| 782 return kNoError; | 802 return kNoError; |
| 783 } | 803 } |
| 784 | 804 |
| 785 OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) { | 805 OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) { |
| 786 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 806 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 787 | 807 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 804 | 824 |
| 805 OperationStatus CrashReportDatabaseWin::SkipReportUpload(const UUID& uuid) { | 825 OperationStatus CrashReportDatabaseWin::SkipReportUpload(const UUID& uuid) { |
| 806 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 826 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 807 | 827 |
| 808 std::unique_ptr<Metadata> metadata(AcquireMetadata()); | 828 std::unique_ptr<Metadata> metadata(AcquireMetadata()); |
| 809 if (!metadata) | 829 if (!metadata) |
| 810 return kDatabaseError; | 830 return kDatabaseError; |
| 811 ReportDisk* report_disk; | 831 ReportDisk* report_disk; |
| 812 OperationStatus os = metadata->FindSingleReportAndMarkDirty( | 832 OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
| 813 uuid, ReportState::kPending, &report_disk); | 833 uuid, ReportState::kPending, &report_disk); |
| 814 if (os == kNoError) | 834 if (os == kNoError) { |
| 815 report_disk->state = ReportState::kCompleted; | 835 report_disk->state = ReportState::kCompleted; |
| 836 report_disk->upload_explicitly_requested = false; |
| 837 } |
| 816 return os; | 838 return os; |
| 817 } | 839 } |
| 818 | 840 |
| 819 std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() { | 841 std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() { |
| 820 base::FilePath metadata_file = base_dir_.Append(kMetadataFileName); | 842 base::FilePath metadata_file = base_dir_.Append(kMetadataFileName); |
| 821 return Metadata::Create(metadata_file, base_dir_.Append(kReportsDirectory)); | 843 return Metadata::Create(metadata_file, base_dir_.Append(kReportsDirectory)); |
| 822 } | 844 } |
| 823 | 845 |
| 824 std::unique_ptr<CrashReportDatabase> InitializeInternal( | 846 std::unique_ptr<CrashReportDatabase> InitializeInternal( |
| 825 const base::FilePath& path, | 847 const base::FilePath& path, |
| 826 bool may_create) { | 848 bool may_create) { |
| 827 std::unique_ptr<CrashReportDatabaseWin> database_win( | 849 std::unique_ptr<CrashReportDatabaseWin> database_win( |
| 828 new CrashReportDatabaseWin(path)); | 850 new CrashReportDatabaseWin(path)); |
| 829 return database_win->Initialize(may_create) | 851 return database_win->Initialize(may_create) |
| 830 ? std::move(database_win) | 852 ? std::move(database_win) |
| 831 : std::unique_ptr<CrashReportDatabaseWin>(); | 853 : std::unique_ptr<CrashReportDatabaseWin>(); |
| 832 } | 854 } |
| 833 | 855 |
| 856 OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) { |
| 857 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| 858 |
| 859 std::unique_ptr<Metadata> metadata(AcquireMetadata()); |
| 860 if (!metadata) |
| 861 return kDatabaseError; |
| 862 |
| 863 ReportDisk* report_disk; |
| 864 // TODO(gayane): Search for the report only once regardless of its state. |
| 865 OperationStatus os = metadata->FindSingleReportAndMarkDirty( |
| 866 uuid, ReportState::kCompleted, &report_disk); |
| 867 if (os == kBusyError) { |
| 868 os = metadata->FindSingleReportAndMarkDirty( |
| 869 uuid, ReportState::kPending, &report_disk); |
| 870 } |
| 871 |
| 872 if (os != kNoError) |
| 873 return os; |
| 874 |
| 875 // If the crash report has already been uploaded, don't request new upload. |
| 876 if (report_disk->uploaded) |
| 877 return kCannotRequestUpload; |
| 878 |
| 879 // Mark the crash report as having upload explicitly requested by the user, |
| 880 // and move it to the pending state. |
| 881 report_disk->upload_explicitly_requested = true; |
| 882 report_disk->state = ReportState::kPending; |
| 883 |
| 884 return kNoError; |
| 885 } |
| 886 |
| 834 } // namespace | 887 } // namespace |
| 835 | 888 |
| 836 // static | 889 // static |
| 837 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( | 890 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( |
| 838 const base::FilePath& path) { | 891 const base::FilePath& path) { |
| 839 return InitializeInternal(path, true); | 892 return InitializeInternal(path, true); |
| 840 } | 893 } |
| 841 | 894 |
| 842 // static | 895 // static |
| 843 std::unique_ptr<CrashReportDatabase> | 896 std::unique_ptr<CrashReportDatabase> |
| 844 CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { | 897 CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { |
| 845 return InitializeInternal(path, false); | 898 return InitializeInternal(path, false); |
| 846 } | 899 } |
| 847 | 900 |
| 848 } // namespace crashpad | 901 } // namespace crashpad |
| OLD | NEW |