crash_reporter.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chrome/updater/crash_reporter.h"
  5. #include <algorithm>
  6. #include <iterator>
  7. #include <map>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/command_line.h"
  12. #include "base/files/file_path.h"
  13. #include "base/logging.h"
  14. #include "base/no_destructor.h"
  15. #include "base/path_service.h"
  16. #include "base/strings/strcat.h"
  17. #include "base/strings/string_util.h"
  18. #include "base/strings/utf_string_conversions.h"
  19. #include "build/build_config.h"
  20. #include "chrome/updater/constants.h"
  21. #include "chrome/updater/updater_branding.h"
  22. #include "chrome/updater/updater_scope.h"
  23. #include "chrome/updater/util.h"
  24. #include "third_party/abseil-cpp/absl/types/optional.h"
  25. #include "third_party/crashpad/crashpad/client/crashpad_client.h"
  26. #include "third_party/crashpad/crashpad/handler/handler_main.h"
  27. namespace updater {
  28. namespace {
  29. crashpad::CrashpadClient& GetCrashpadClient() {
  30. static base::NoDestructor<crashpad::CrashpadClient> crashpad_client;
  31. return *crashpad_client;
  32. }
  33. // Returns the command line arguments to start the crash handler process with.
  34. std::vector<std::string> MakeCrashHandlerArgs(UpdaterScope updater_scope) {
  35. base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
  36. command_line.AppendSwitch(kCrashHandlerSwitch);
  37. command_line.AppendSwitch(kEnableLoggingSwitch);
  38. command_line.AppendSwitchASCII(kLoggingModuleSwitch,
  39. kLoggingModuleSwitchValue);
  40. if (updater_scope == UpdaterScope::kSystem) {
  41. command_line.AppendSwitch(kSystemSwitch);
  42. }
  43. // The first element in the command line arguments is the program name,
  44. // which must be skipped.
  45. #if BUILDFLAG(IS_WIN)
  46. std::vector<std::string> args;
  47. std::transform(++command_line.argv().begin(), command_line.argv().end(),
  48. std::back_inserter(args),
  49. [](const auto& arg) { return base::WideToUTF8(arg); });
  50. return args;
  51. #else
  52. return {++command_line.argv().begin(), command_line.argv().end()};
  53. #endif
  54. }
  55. } // namespace
  56. void StartCrashReporter(UpdaterScope updater_scope,
  57. const std::string& version) {
  58. static bool started = false;
  59. DCHECK(!started);
  60. started = true;
  61. base::FilePath handler_path;
  62. base::PathService::Get(base::FILE_EXE, &handler_path);
  63. const absl::optional<base::FilePath> database_path =
  64. GetVersionedDataDirectory(updater_scope);
  65. if (!database_path) {
  66. LOG(ERROR) << "Failed to get the database path.";
  67. return;
  68. }
  69. std::map<std::string, std::string> annotations;
  70. annotations["ver"] = version;
  71. annotations["prod"] = CRASH_PRODUCT_NAME;
  72. crashpad::CrashpadClient& client = GetCrashpadClient();
  73. if (!client.StartHandler(handler_path, *database_path,
  74. /*metrics_dir=*/base::FilePath(), CRASH_UPLOAD_URL,
  75. annotations, MakeCrashHandlerArgs(updater_scope),
  76. /*restartable=*/true,
  77. /*asynchronous_start=*/false)) {
  78. VLOG(1) << "Failed to start handler.";
  79. return;
  80. }
  81. VLOG(1) << "Crash handler launched and ready.";
  82. }
  83. int CrashReporterMain() {
  84. base::CommandLine command_line = *base::CommandLine::ForCurrentProcess();
  85. DCHECK(command_line.HasSwitch(kCrashHandlerSwitch));
  86. // Disable rate-limiting until this is fixed:
  87. // https://bugs.chromium.org/p/crashpad/issues/detail?id=23
  88. command_line.AppendSwitch(kNoRateLimitSwitch);
  89. // Because of https://bugs.chromium.org/p/crashpad/issues/detail?id=82,
  90. // Crashpad fails on the presence of flags it doesn't handle.
  91. command_line.RemoveSwitch(kCrashHandlerSwitch);
  92. command_line.RemoveSwitch(kSystemSwitch);
  93. command_line.RemoveSwitch(kEnableLoggingSwitch);
  94. command_line.RemoveSwitch(kLoggingModuleSwitch);
  95. const std::vector<base::CommandLine::StringType> argv = command_line.argv();
  96. // |storage| must be declared before |argv_as_utf8|, to ensure it outlives
  97. // |argv_as_utf8|, which will hold pointers into |storage|.
  98. std::vector<std::string> storage;
  99. auto argv_as_utf8 = std::make_unique<char*[]>(argv.size() + 1);
  100. storage.reserve(argv.size());
  101. for (size_t i = 0; i < argv.size(); ++i) {
  102. #if BUILDFLAG(IS_WIN)
  103. storage.push_back(base::WideToUTF8(argv[i]));
  104. #else
  105. storage.push_back(argv[i]);
  106. #endif
  107. argv_as_utf8[i] = &storage[i][0];
  108. }
  109. argv_as_utf8[argv.size()] = nullptr;
  110. return crashpad::HandlerMain(argv.size(), argv_as_utf8.get(),
  111. /*user_stream_sources=*/nullptr);
  112. }
  113. } // namespace updater