| Index: components/browser_watcher/postmortem_report_collector.cc
|
| diff --git a/components/browser_watcher/postmortem_report_collector.cc b/components/browser_watcher/postmortem_report_collector.cc
|
| index 4812179e7bf498685bcae398971f42f6e5a43d05..2b3d9d5a18509828040620859bca530d0d05397d 100644
|
| --- a/components/browser_watcher/postmortem_report_collector.cc
|
| +++ b/components/browser_watcher/postmortem_report_collector.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/logging.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/path_service.h"
|
| +#include "base/strings/string_piece.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "components/browser_watcher/postmortem_minidump_writer.h"
|
| #include "third_party/crashpad/crashpad/client/settings.h"
|
| @@ -22,10 +23,74 @@ using base::FilePath;
|
| namespace browser_watcher {
|
|
|
| using ActivitySnapshot = base::debug::ThreadActivityAnalyzer::Snapshot;
|
| +using base::debug::ActivityUserData;
|
| using base::debug::GlobalActivityAnalyzer;
|
| using base::debug::ThreadActivityAnalyzer;
|
| using crashpad::CrashReportDatabase;
|
|
|
| +namespace {
|
| +
|
| +// Collects stability user data from the recorded format to the collected
|
| +// format.
|
| +void CollectUserData(
|
| + const ActivityUserData::Snapshot& recorded_map,
|
| + google::protobuf::Map<std::string, TypedValue>* collected_map) {
|
| + DCHECK(collected_map);
|
| +
|
| + for (const auto& name_and_value : recorded_map) {
|
| + const ActivityUserData::TypedValue& recorded_value = name_and_value.second;
|
| + TypedValue collected_value;
|
| +
|
| + switch (recorded_value.type()) {
|
| + case ActivityUserData::END_OF_VALUES:
|
| + NOTREACHED();
|
| + break;
|
| + case ActivityUserData::RAW_VALUE:
|
| + collected_value.set_bytes_value(recorded_value.Get().as_string());
|
| + break;
|
| + case ActivityUserData::RAW_VALUE_REFERENCE: {
|
| + base::StringPiece recorded_ref = recorded_value.GetReference();
|
| + TypedValue::Reference* collected_ref =
|
| + collected_value.mutable_bytes_reference();
|
| + collected_ref->set_address(
|
| + reinterpret_cast<uintptr_t>(recorded_ref.data()));
|
| + collected_ref->set_size(recorded_ref.size());
|
| + break;
|
| + }
|
| + case ActivityUserData::STRING_VALUE:
|
| + collected_value.set_string_value(
|
| + recorded_value.GetString().as_string());
|
| + break;
|
| + case ActivityUserData::STRING_VALUE_REFERENCE: {
|
| + base::StringPiece recorded_ref = recorded_value.GetStringReference();
|
| + TypedValue::Reference* collected_ref =
|
| + collected_value.mutable_string_reference();
|
| + collected_ref->set_address(
|
| + reinterpret_cast<uintptr_t>(recorded_ref.data()));
|
| + collected_ref->set_size(recorded_ref.size());
|
| + break;
|
| + }
|
| + case ActivityUserData::CHAR_VALUE:
|
| + collected_value.set_char_value(
|
| + std::string(1, recorded_value.GetChar()));
|
| + break;
|
| + case ActivityUserData::BOOL_VALUE:
|
| + collected_value.set_bool_value(recorded_value.GetBool());
|
| + break;
|
| + case ActivityUserData::SIGNED_VALUE:
|
| + collected_value.set_signed_value(recorded_value.GetInt());
|
| + break;
|
| + case ActivityUserData::UNSIGNED_VALUE:
|
| + collected_value.set_unsigned_value(recorded_value.GetUint());
|
| + break;
|
| + }
|
| +
|
| + (*collected_map)[name_and_value.first].Swap(&collected_value);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| PostmortemReportCollector::PostmortemReportCollector(
|
| const std::string& product_name,
|
| const std::string& version_number,
|
| @@ -169,8 +234,11 @@ PostmortemReportCollector::CollectionStatus PostmortemReportCollector::Collect(
|
|
|
| // Early exit if there is no data.
|
| std::vector<std::string> log_messages = global_analyzer->GetLogMessages();
|
| + ActivityUserData::Snapshot global_data_snapshot =
|
| + global_analyzer->GetGlobalUserDataSnapshot();
|
| ThreadActivityAnalyzer* thread_analyzer = global_analyzer->GetFirstAnalyzer();
|
| - if (log_messages.empty() && !thread_analyzer) {
|
| + if (log_messages.empty() && global_data_snapshot.empty() &&
|
| + !thread_analyzer) {
|
| return DEBUG_FILE_NO_DATA;
|
| }
|
|
|
| @@ -182,6 +250,9 @@ PostmortemReportCollector::CollectionStatus PostmortemReportCollector::Collect(
|
| (*report)->add_log_messages(message);
|
| }
|
|
|
| + // Collect global user data.
|
| + CollectUserData(global_data_snapshot, (*report)->mutable_global_data());
|
| +
|
| // Collect thread activity data.
|
| // Note: a single process is instrumented.
|
| ProcessState* process_state = (*report)->add_process_states();
|
| @@ -214,8 +285,11 @@ void PostmortemReportCollector::CollectThread(
|
| thread_state->set_thread_id(snapshot.thread_id);
|
| thread_state->set_activity_count(snapshot.activity_stack_depth);
|
|
|
| - for (const base::debug::Activity& recorded : snapshot.activity_stack) {
|
| + for (size_t i = 0; i < snapshot.activity_stack.size(); ++i) {
|
| + const base::debug::Activity& recorded = snapshot.activity_stack[i];
|
| Activity* collected = thread_state->add_activities();
|
| +
|
| + // Collect activity
|
| switch (recorded.activity_type) {
|
| case base::debug::Activity::ACT_TASK_RUN:
|
| collected->set_type(Activity::ACT_TASK_RUN);
|
| @@ -241,6 +315,12 @@ void PostmortemReportCollector::CollectThread(
|
| default:
|
| break;
|
| }
|
| +
|
| + // Collect user data
|
| + if (i < snapshot.user_data_stack.size()) {
|
| + CollectUserData(snapshot.user_data_stack[i],
|
| + collected->mutable_user_data());
|
| + }
|
| }
|
| }
|
|
|
|
|