diff --git chrome/chrome_elf/BUILD.gn chrome/chrome_elf/BUILD.gn index 37e2d2a50aa2c..bb6ac82cd9cb7 100644 --- chrome/chrome_elf/BUILD.gn +++ chrome/chrome_elf/BUILD.gn @@ -7,6 +7,7 @@ import("//build/config/compiler/compiler.gni") import("//build/config/win/manifest.gni") +import("//cef/libcef/features/features.gni") import("//chrome/process_version_rc_template.gni") import("//testing/test.gni") @@ -106,9 +107,6 @@ source_set("constants") { static_library("crash") { sources = [ - "../app/chrome_crash_reporter_client_win.cc", - "../app/chrome_crash_reporter_client_win.h", - "../common/chrome_result_codes.h", "crash/crash_helper.cc", "crash/crash_helper.h", ] @@ -117,6 +115,7 @@ static_library("crash") { ":hook_util", "//base", # This needs to go. DEP of app, crash_keys, client. "//base:base_static", # pe_image + "//cef/libcef/features", "//chrome/install_static:install_static_util", "//components/crash/core/app", "//components/crash/core/common", # crash_keys @@ -124,6 +123,17 @@ static_library("crash") { "//content/public/common:result_codes", "//third_party/crashpad/crashpad/client", # DumpWithoutCrash ] + + if (enable_cef) { + deps += [ "//cef:chrome_elf_set" ] + include_dirs = [ "//cef" ] + } else { + sources += [ + "//chrome/app/chrome_crash_reporter_client_win.cc", + "//chrome/app/chrome_crash_reporter_client_win.h", + "//chrome/common/chrome_result_codes.h", + ] + } } source_set("dll_hash") { diff --git chrome/chrome_elf/crash/crash_helper.cc chrome/chrome_elf/crash/crash_helper.cc index 30a2c1adc4509..b60a7afaf1e5e 100644 --- chrome/chrome_elf/crash/crash_helper.cc +++ chrome/chrome_elf/crash/crash_helper.cc @@ -12,12 +12,17 @@ #include #include +#include "cef/libcef/features/features.h" #include "chrome/app/chrome_crash_reporter_client_win.h" #include "chrome/chrome_elf/hook_util/hook_util.h" #include "components/crash/core/app/crashpad.h" #include "components/crash/core/common/crash_keys.h" #include "third_party/crashpad/crashpad/client/crashpad_client.h" +#if BUILDFLAG(ENABLE_CEF) +#include "cef/libcef/common/crash_reporter_client.h" +#endif + namespace { // Crash handling from elf is only enabled for the chrome.exe process. @@ -78,7 +83,11 @@ bool InitializeCrashReporting() { g_crash_reports = new std::vector; g_set_unhandled_exception_filter = new elf_hook::IATHook(); +#if BUILDFLAG(ENABLE_CEF) + CefCrashReporterClient::InitializeCrashReportingForProcess(); +#else ChromeCrashReporterClient::InitializeCrashReportingForProcess(); +#endif g_crash_helper_enabled = true; return true; diff --git chrome/common/crash_keys.cc chrome/common/crash_keys.cc index d9c721376c855..e72b67e2a1a50 100644 --- chrome/common/crash_keys.cc +++ chrome/common/crash_keys.cc @@ -12,6 +12,8 @@ #include #include +#include + #include "base/base_switches.h" #include "base/command_line.h" #include "base/format_macros.h" @@ -110,8 +112,10 @@ void HandleEnableDisableFeatures(const base::CommandLine& command_line) { "commandline-disabled-feature"); } +} // namespace + // Return true if we DON'T want to upload this flag to the crash server. -bool IsBoringSwitch(const std::string& flag) { +bool IsBoringChromeSwitch(const std::string& flag) { static const std::string_view kIgnoreSwitches[] = { kStringAnnotationsSwitch, switches::kEnableLogging, @@ -171,6 +175,8 @@ bool IsBoringSwitch(const std::string& flag) { return false; } +namespace { + std::deque& GetCommandLineStringAnnotations() { static base::NoDestructor> command_line_string_annotations; @@ -216,7 +222,7 @@ void AppendStringAnnotationsCommandLineSwitch(base::CommandLine* command_line) { void SetCrashKeysFromCommandLine(const base::CommandLine& command_line) { SetStringAnnotations(command_line); HandleEnableDisableFeatures(command_line); - SetSwitchesFromCommandLine(command_line, &IsBoringSwitch); + SetSwitchesFromCommandLine(command_line, &IsBoringChromeSwitch); } } // namespace crash_keys diff --git chrome/common/crash_keys.h chrome/common/crash_keys.h index a274b3e364084..3d995cf643399 100644 --- chrome/common/crash_keys.h +++ chrome/common/crash_keys.h @@ -5,6 +5,7 @@ #ifndef CHROME_COMMON_CRASH_KEYS_H_ #define CHROME_COMMON_CRASH_KEYS_H_ +#include #include namespace base { @@ -24,6 +25,10 @@ void AllocateCrashKeyInBrowserAndChildren(std::string_view key, // SetCrashKeysFromCommandLine(). void AppendStringAnnotationsCommandLineSwitch(base::CommandLine* command_line); +// Returns true if the specified command-line flag should be excluded from +// crash reporting. +bool IsBoringChromeSwitch(const std::string& flag); + // Sets the kNumSwitches key and the set of keys named using kSwitchFormat based // on the given `command_line`. For non-browser processes, allocates crash keys // from the switch value set by AppendStringAnnotationsCommandLineSwitch(). diff --git components/crash/core/app/crash_reporter_client.cc components/crash/core/app/crash_reporter_client.cc index 0e9fe8892af82..7c1ce4b94fba5 100644 --- components/crash/core/app/crash_reporter_client.cc +++ components/crash/core/app/crash_reporter_client.cc @@ -93,7 +93,7 @@ bool CrashReporterClient::GetShouldDumpLargerDumps() { } #endif -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_POSIX) void CrashReporterClient::GetProductNameAndVersion(const char** product_name, const char** version) { } @@ -102,6 +102,7 @@ void CrashReporterClient::GetProductNameAndVersion(std::string* product_name, std::string* version, std::string* channel) {} +#if !BUILDFLAG(IS_MAC) base::FilePath CrashReporterClient::GetReporterLogFilename() { return base::FilePath(); } @@ -111,6 +112,7 @@ bool CrashReporterClient::HandleCrashDump(const char* crashdump_filename, return false; } #endif +#endif #if BUILDFLAG(IS_WIN) bool CrashReporterClient::GetCrashDumpLocation(std::wstring* crash_dir) { @@ -145,6 +147,28 @@ bool CrashReporterClient::ReportingIsEnforcedByPolicy(bool* breakpad_enabled) { return false; } +bool CrashReporterClient::EnableBreakpadForProcess( + const std::string& process_type) { + return false; +} + +void CrashReporterClient::GetCrashOptionalArguments( + std::vector* arguments) { +} + +#if BUILDFLAG(IS_WIN) +std::wstring CrashReporterClient::GetCrashExternalHandler( + const std::wstring& exe_dir) { + return exe_dir + L"\\crashpad_handler.exe"; +} +#endif + +#if BUILDFLAG(IS_MAC) +bool CrashReporterClient::EnableBrowserCrashForwarding() { + return true; +} +#endif + #if BUILDFLAG(IS_ANDROID) unsigned int CrashReporterClient::GetCrashDumpPercentage() { return 100; @@ -205,9 +229,4 @@ bool CrashReporterClient::ShouldMonitorCrashHandlerExpensively() { return false; } -bool CrashReporterClient::EnableBreakpadForProcess( - const std::string& process_type) { - return false; -} - } // namespace crash_reporter diff --git components/crash/core/app/crash_reporter_client.h components/crash/core/app/crash_reporter_client.h index a604df7a5ea6a..618fbde10a65c 100644 --- components/crash/core/app/crash_reporter_client.h +++ components/crash/core/app/crash_reporter_client.h @@ -7,7 +7,9 @@ #include +#include #include +#include #include "build/build_config.h" @@ -96,7 +98,7 @@ class CrashReporterClient { virtual bool GetShouldDumpLargerDumps(); #endif -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_POSIX) // Returns a textual description of the product type and version to include // in the crash report. Neither out parameter should be set to NULL. // TODO(jperaza): Remove the 2-parameter overload of this method once all @@ -107,6 +109,7 @@ class CrashReporterClient { std::string* version, std::string* channel); +#if !BUILDFLAG(IS_MAC) virtual base::FilePath GetReporterLogFilename(); // Custom crash minidump handler after the minidump is generated. @@ -116,6 +119,7 @@ class CrashReporterClient { // libc nor allocate memory normally. virtual bool HandleCrashDump(const char* crashdump_filename, uint64_t crash_pid); +#endif #endif // The location where minidump files should be written. Returns true if @@ -213,6 +217,20 @@ class CrashReporterClient { // Returns true if breakpad should run in the given process type. virtual bool EnableBreakpadForProcess(const std::string& process_type); + + // Populate |arguments| with additional optional arguments. + virtual void GetCrashOptionalArguments(std::vector* arguments); + +#if BUILDFLAG(IS_WIN) + // Returns the absolute path to the external crash handler exe. + virtual std::wstring GetCrashExternalHandler(const std::wstring& exe_dir); +#endif + +#if BUILDFLAG(IS_MAC) + // Returns true if forwarding of crashes to the system crash reporter is + // enabled for the browser process. + virtual bool EnableBrowserCrashForwarding(); +#endif }; } // namespace crash_reporter diff --git components/crash/core/app/crashpad.cc components/crash/core/app/crashpad.cc index 641c9cdba5011..20a8b9983a476 100644 --- components/crash/core/app/crashpad.cc +++ components/crash/core/app/crashpad.cc @@ -128,7 +128,8 @@ bool InitializeCrashpadImpl(bool initial_client, // fallback. Forwarding is turned off for debug-mode builds even for the // browser process, because the system's crash reporter can take a very long // time to chew on symbols. - if (!browser_process || is_debug_build) { + if (!browser_process || is_debug_build || + !GetCrashReporterClient()->EnableBrowserCrashForwarding()) { crashpad::CrashpadInfo::GetCrashpadInfo() ->set_system_crash_reporter_forwarding(crashpad::TriState::kDisabled); } diff --git components/crash/core/app/crashpad_linux.cc components/crash/core/app/crashpad_linux.cc index 171095381e8ac..13407a7809844 100644 --- components/crash/core/app/crashpad_linux.cc +++ components/crash/core/app/crashpad_linux.cc @@ -23,6 +23,7 @@ #include "components/crash/core/app/crash_reporter_client.h" #include "components/crash/core/app/crash_switches.h" #include "content/public/common/content_descriptors.h" +#include "content/public/common/content_paths.h" #include "sandbox/linux/services/namespace_sandbox.h" #include "third_party/crashpad/crashpad/client/crashpad_client.h" #include "third_party/crashpad/crashpad/client/crashpad_info.h" @@ -168,11 +169,10 @@ bool PlatformCrashpadInitialization( crash_reporter_client->GetCrashDumpLocation(database_path); crash_reporter_client->GetCrashMetricsLocation(&metrics_path); + // Use the same main (default) or subprocess helper exe. base::FilePath handler_path; - if (!base::PathService::Get(base::DIR_EXE, &handler_path)) { - return false; - } - handler_path = handler_path.Append("chrome_crashpad_handler"); + base::PathService::Get(content::CHILD_PROCESS_EXE, &handler_path); + DCHECK(!handler_path.empty()); // When --use-cros-crash-reporter is set (below), the handler passes dumps // to ChromeOS's /sbin/crash_reporter which in turn passes the dump to @@ -189,8 +189,8 @@ bool PlatformCrashpadInitialization( &product_version, &channel); std::map annotations; - annotations["prod"] = product_name; - annotations["ver"] = product_version; + annotations["product"] = product_name; + annotations["version"] = product_version; #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Empty means stable. @@ -207,7 +207,20 @@ bool PlatformCrashpadInitialization( annotations["channel"] = channel; } - annotations["plat"] = std::string("Linux"); +#if defined(ARCH_CPU_ARM_FAMILY) +#if defined(ARCH_CPU_32_BITS) + const char* platform = "linuxarm"; +#elif defined(ARCH_CPU_64_BITS) + const char* platform = "linuxarm64"; +#endif +#else +#if defined(ARCH_CPU_32_BITS) + const char* platform = "linux32"; +#elif defined(ARCH_CPU_64_BITS) + const char* platform = "linux64"; +#endif +#endif // defined(ARCH_CPU_ARM_FAMILY) + annotations["platform"] = platform; #if BUILDFLAG(IS_CHROMEOS_LACROS) // "build_time_millis" is used on LaCros chrome to determine when to stop @@ -252,6 +265,12 @@ bool PlatformCrashpadInitialization( } #endif + // Since we're using the same main or subprocess helper exe we must specify + // the process type. + arguments.push_back(std::string("--type=") + switches::kCrashpadHandler); + + crash_reporter_client->GetCrashOptionalArguments(&arguments); + CHECK(client.StartHandler(handler_path, *database_path, metrics_path, url, annotations, arguments, false, false)); } else { diff --git components/crash/core/app/crashpad_mac.mm components/crash/core/app/crashpad_mac.mm index 42fe73aefe44f..575ce6732ae43 100644 --- components/crash/core/app/crashpad_mac.mm +++ components/crash/core/app/crashpad_mac.mm @@ -17,10 +17,13 @@ #include "base/apple/foundation_util.h" #include "base/check.h" #include "base/files/file_path.h" +#include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" #include "build/branding_buildflags.h" #include "components/crash/core/app/crash_reporter_client.h" +#include "components/crash/core/app/crash_switches.h" +#include "content/public/common/content_paths.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" #include "third_party/crashpad/crashpad/client/crashpad_client.h" #include "third_party/crashpad/crashpad/client/crashpad_info.h" @@ -38,15 +41,25 @@ std::map GetProcessSimpleAnnotations() { std::map process_annotations; @autoreleasepool { NSBundle* outer_bundle = base::apple::OuterBundle(); + CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); + const char* product_name = ""; + const char* product_version = ""; + crash_reporter_client->GetProductNameAndVersion(&product_name, + &product_version); + + if (strlen(product_name) == 0) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - process_annotations["prod"] = "Chrome_Mac"; + process_annotations["product"] = "Chrome_Mac"; #else - NSString* product = base::apple::ObjCCast( - [outer_bundle objectForInfoDictionaryKey:base::apple::CFToNSPtrCast( - kCFBundleNameKey)]); - process_annotations["prod"] = - base::SysNSStringToUTF8(product).append("_Mac"); + NSString* product = base::apple::ObjCCast( + [outer_bundle objectForInfoDictionaryKey:base::apple::CFToNSPtrCast( + kCFBundleNameKey)]); + process_annotations["product"] = + base::SysNSStringToUTF8(product).append("_Mac"); #endif + } else { + process_annotations["product"] = product_name; + } #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Empty means stable. @@ -77,12 +90,20 @@ std::map GetProcessSimpleAnnotations() { } } - NSString* version = - base::apple::ObjCCast([base::apple::FrameworkBundle() - objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); - process_annotations["ver"] = base::SysNSStringToUTF8(version); + if (strlen(product_version) == 0) { + NSString* version = + base::apple::ObjCCast([base::apple::FrameworkBundle() + objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); + process_annotations["version"] = base::SysNSStringToUTF8(version); + } else { + process_annotations["version"] = product_version; + } - process_annotations["plat"] = std::string("OS X"); +#if defined(ARCH_CPU_ARM64) + process_annotations["platform"] = std::string("macosarm64"); +#else + process_annotations["platform"] = std::string("macos"); +#endif } // @autoreleasepool return process_annotations; }(); @@ -142,10 +163,10 @@ bool PlatformCrashpadInitialization( if (initial_client) { @autoreleasepool { - base::FilePath framework_bundle_path = base::apple::FrameworkBundlePath(); - base::FilePath handler_path = - framework_bundle_path.Append("Helpers").Append( - "chrome_crashpad_handler"); + // Use the same subprocess helper exe. + base::FilePath handler_path; + base::PathService::Get(content::CHILD_PROCESS_EXE, &handler_path); + DCHECK(!handler_path.empty()); // Is there a way to recover if this fails? CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); @@ -174,6 +195,12 @@ bool PlatformCrashpadInitialization( "--reset-own-crash-exception-port-to-system-default"); } + // Since we're using the same subprocess helper exe we must specify the + // process type. + arguments.push_back(std::string("--type=") + switches::kCrashpadHandler); + + crash_reporter_client->GetCrashOptionalArguments(&arguments); + bool result = GetCrashpadClient().StartHandler( handler_path, *database_path, metrics_path, url, GetProcessSimpleAnnotations(), arguments, true, false); diff --git components/crash/core/app/crashpad_win.cc components/crash/core/app/crashpad_win.cc index 0e00d26f79231..fdd2b4bc73f8e 100644 --- components/crash/core/app/crashpad_win.cc +++ components/crash/core/app/crashpad_win.cc @@ -37,8 +37,8 @@ void GetPlatformCrashpadAnnotations( std::wstring product_name, version, special_build, channel_name; crash_reporter_client->GetProductNameAndVersion( exe_file, &product_name, &version, &special_build, &channel_name); - (*annotations)["prod"] = base::WideToUTF8(product_name); - (*annotations)["ver"] = base::WideToUTF8(version); + (*annotations)["product"] = base::WideToUTF8(product_name); + (*annotations)["version"] = base::WideToUTF8(version); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Empty means stable. const bool allow_empty_channel = true; @@ -55,9 +55,11 @@ void GetPlatformCrashpadAnnotations( if (!special_build.empty()) (*annotations)["special"] = base::WideToUTF8(special_build); #if defined(ARCH_CPU_X86) - (*annotations)["plat"] = std::string("Win32"); + (*annotations)["platform"] = std::string("win32"); #elif defined(ARCH_CPU_X86_64) - (*annotations)["plat"] = std::string("Win64"); + (*annotations)["platform"] = std::string("win64"); +#elif defined(ARCH_CPU_ARM64) + (*annotations)["platform"] = std::string("winarm64"); #endif } @@ -72,7 +74,9 @@ bool PlatformCrashpadInitialization( base::FilePath metrics_path; // Only valid in the browser process. const char kPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME"; +#if defined(GOOGLE_CHROME_BUILD) const char kServerUrlVar[] = "CHROME_CRASHPAD_SERVER_URL"; +#endif std::unique_ptr env(base::Environment::Create()); CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); @@ -95,9 +99,11 @@ bool PlatformCrashpadInitialization( std::string url = crash_reporter_client->GetUploadUrl(); +#if defined(GOOGLE_CHROME_BUILD) // Allow the crash server to be overridden for testing. If the variable // isn't present in the environment then the default URL will remain. env->GetVar(kServerUrlVar, &url); +#endif base::FilePath exe_file(exe_path); if (exe_file.empty()) { @@ -108,13 +114,14 @@ bool PlatformCrashpadInitialization( exe_file = base::FilePath(exe_file_path); } - // If the handler is embedded in the binary (e.g. chrome, setup), we - // reinvoke it with --type=crashpad-handler. Otherwise, we use the - // standalone crashpad_handler.exe (for tests, etc.). std::vector start_arguments(initial_arguments); + + // Always add --type=crashpad-handler because the value is expected by + // CefExecuteProcess. + start_arguments.push_back( + std::string("--type=") + switches::kCrashpadHandler); + if (embedded_handler) { - start_arguments.push_back(std::string("--type=") + - switches::kCrashpadHandler); if (!user_data_dir.empty()) { start_arguments.push_back(std::string("--user-data-dir=") + user_data_dir); @@ -124,9 +131,12 @@ bool PlatformCrashpadInitialization( app_launch_prefetch::SubprocessType::kCrashpad))); } else { base::FilePath exe_dir = exe_file.DirName(); - exe_file = exe_dir.Append(FILE_PATH_LITERAL("crashpad_handler.exe")); + exe_file = base::FilePath( + crash_reporter_client->GetCrashExternalHandler(exe_dir.value())); } + crash_reporter_client->GetCrashOptionalArguments(&start_arguments); + std::vector arguments(start_arguments); if (crash_reporter_client->ShouldMonitorCrashHandlerExpensively()) {