Index: chrome/chrome_watcher/chrome_watcher_main.cc |
diff --git a/chrome/chrome_watcher/chrome_watcher_main.cc b/chrome/chrome_watcher/chrome_watcher_main.cc |
index 1976c7ae099e09150b70fcb2ba2f9a86afdb4df5..95ead7765eb414e75cccb197379dcd42485d7e81 100644 |
--- a/chrome/chrome_watcher/chrome_watcher_main.cc |
+++ b/chrome/chrome_watcher/chrome_watcher_main.cc |
@@ -34,17 +34,13 @@ |
#include "base/win/win_util.h" |
#include "chrome/chrome_watcher/chrome_watcher_main_api.h" |
+#include "chrome/chrome_watcher/kasko_util.h" |
#include "chrome/installer/util/util_constants.h" |
#include "components/browser_watcher/endsession_watcher_window_win.h" |
#include "components/browser_watcher/exit_code_watcher_win.h" |
#include "components/browser_watcher/window_hang_monitor_win.h" |
#include "third_party/kasko/kasko_features.h" |
-#if BUILDFLAG(ENABLE_KASKO) |
-#include "components/crash/content/app/crashpad.h" |
-#include "syzygy/kasko/api/reporter.h" |
-#endif |
- |
namespace { |
// Use the same log facility as Chrome for convenience. |
@@ -197,161 +193,6 @@ void OnWindowEvent( |
} |
} |
-#if BUILDFLAG(ENABLE_KASKO) |
-// Helper function for determining the crash server to use. Defaults to the |
-// standard crash server, but can be overridden via an environment variable. |
-// Enables easy integration testing. |
-void GetKaskoCrashServerUrl(base::string16* crash_server) { |
- const char kKaskoCrashServerUrl[] = "KASKO_CRASH_SERVER_URL"; |
- static const wchar_t kDefaultKaskoCrashServerUrl[] = |
- L"https://clients2.google.com/cr/report"; |
- |
- auto env = base::Environment::Create(); |
- std::string env_var; |
- if (env->GetVar(kKaskoCrashServerUrl, &env_var)) { |
- base::UTF8ToWide(env_var.c_str(), env_var.size(), crash_server); |
- } else { |
- *crash_server = kDefaultKaskoCrashServerUrl; |
- } |
-} |
- |
-// Helper function for determining the crash reports directory to use. Defaults |
-// to the browser data directory, but can be overridden via an environment |
-// variable. Enables easy integration testing. |
-void GetKaskoCrashReportsBaseDir(const base::char16* browser_data_directory, |
- base::FilePath* base_dir) { |
- const char kKaskoCrashReportBaseDir[] = "KASKO_CRASH_REPORTS_BASE_DIR"; |
- auto env = base::Environment::Create(); |
- std::string env_var; |
- if (env->GetVar(kKaskoCrashReportBaseDir, &env_var)) { |
- base::string16 wide_env_var; |
- base::UTF8ToWide(env_var.c_str(), env_var.size(), &wide_env_var); |
- *base_dir = base::FilePath(wide_env_var); |
- } else { |
- *base_dir = base::FilePath(browser_data_directory); |
- } |
-} |
- |
-void DumpHungBrowserProcess(DWORD main_thread_id, |
- const base::string16& channel, |
- const base::Process& process) { |
- // Read the Crashpad module annotations for the process. |
- std::vector<kasko::api::CrashKey> annotations; |
- crash_reporter::ReadMainModuleAnnotationsForKasko(process, &annotations); |
- |
- // Add a special crash key to distinguish reports generated for a hung |
- // process. |
- annotations.push_back(kasko::api::CrashKey{L"hung-process", L"1"}); |
- |
- std::vector<const base::char16*> key_buffers; |
- std::vector<const base::char16*> value_buffers; |
- for (const auto& crash_key : annotations) { |
- key_buffers.push_back(crash_key.name); |
- value_buffers.push_back(crash_key.value); |
- } |
- key_buffers.push_back(nullptr); |
- value_buffers.push_back(nullptr); |
- |
- // Synthesize an exception for the main thread. Populate the record with the |
- // current context of the thread to get the stack trace bucketed on the crash |
- // backend. |
- CONTEXT thread_context = {}; |
- EXCEPTION_RECORD exception_record = {}; |
- exception_record.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; |
- EXCEPTION_POINTERS exception_pointers = {&exception_record, &thread_context}; |
- |
- base::win::ScopedHandle main_thread(::OpenThread( |
- THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, |
- FALSE, main_thread_id)); |
- |
- bool have_context = false; |
- if (main_thread.IsValid()) { |
- DWORD suspend_count = ::SuspendThread(main_thread.Get()); |
- const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
- if (suspend_count != kSuspendFailed) { |
- // Best effort capture of the context. |
- thread_context.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_SEGMENTS | |
- CONTEXT_INTEGER | CONTEXT_CONTROL; |
- if (::GetThreadContext(main_thread.Get(), &thread_context) == TRUE) |
- have_context = true; |
- |
- ::ResumeThread(main_thread.Get()); |
- } |
- } |
- |
- // TODO(erikwright): Make the dump-type channel-dependent. |
- if (have_context) { |
- kasko::api::SendReportForProcess( |
- process.Handle(), main_thread_id, &exception_pointers, |
- kasko::api::LARGER_DUMP_TYPE, key_buffers.data(), value_buffers.data()); |
- } else { |
- kasko::api::SendReportForProcess(process.Handle(), 0, nullptr, |
- kasko::api::LARGER_DUMP_TYPE, |
- key_buffers.data(), value_buffers.data()); |
- } |
-} |
- |
-void LoggedDeregisterEventSource(HANDLE event_source_handle) { |
- if (!::DeregisterEventSource(event_source_handle)) |
- DPLOG(ERROR) << "DeregisterEventSource"; |
-} |
- |
-void LoggedLocalFree(PSID sid) { |
- if (::LocalFree(sid) != nullptr) |
- DPLOG(ERROR) << "LocalFree"; |
-} |
- |
-void OnCrashReportUpload(void* context, |
- const base::char16* report_id, |
- const base::char16* minidump_path, |
- const base::char16* const* keys, |
- const base::char16* const* values) { |
- // Open the event source. |
- HANDLE event_source_handle = ::RegisterEventSource(NULL, L"Chrome"); |
- if (!event_source_handle) { |
- PLOG(ERROR) << "RegisterEventSource"; |
- return; |
- } |
- // Ensure cleanup on scope exit. |
- base::ScopedClosureRunner deregister_event_source( |
- base::Bind(&LoggedDeregisterEventSource, event_source_handle)); |
- |
- // Get the user's SID for the log record. |
- base::string16 sid_string; |
- PSID sid = nullptr; |
- if (base::win::GetUserSidString(&sid_string)) { |
- if (!sid_string.empty()) { |
- if (!::ConvertStringSidToSid(sid_string.c_str(), &sid)) |
- DPLOG(ERROR) << "ConvertStringSidToSid"; |
- DCHECK(sid); |
- } |
- } |
- // Ensure cleanup on scope exit. |
- base::ScopedClosureRunner free_sid( |
- base::Bind(&LoggedLocalFree, base::Unretained(sid))); |
- |
- // Generate the message. |
- // Note that the format of this message must match the consumer in |
- // chrome/browser/crash_upload_list_win.cc. |
- base::string16 message = |
- L"Crash uploaded. Id=" + base::string16(report_id) + L"."; |
- |
- // Matches Omaha. |
- const int kCrashUploadEventId = 2; |
- |
- // Report the event. |
- const base::char16* strings[] = {message.c_str()}; |
- if (!::ReportEvent(event_source_handle, EVENTLOG_INFORMATION_TYPE, |
- 0, // category |
- kCrashUploadEventId, sid, |
- 1, // count |
- 0, strings, nullptr)) { |
- DPLOG(ERROR); |
- } |
-} |
- |
-#endif // BUILDFLAG(ENABLE_KASKO) |
- |
} // namespace |
// The main entry point to the watcher, declared as extern "C" to avoid name |
@@ -379,31 +220,17 @@ extern "C" int WatcherMain(const base::char16* registry_path, |
base::Callback<void(const base::Process&)> on_hung_callback; |
#if BUILDFLAG(ENABLE_KASKO) |
- base::string16 crash_server; |
- GetKaskoCrashServerUrl(&crash_server); |
- |
- base::FilePath crash_reports_base_dir; |
- GetKaskoCrashReportsBaseDir(browser_data_directory, &crash_reports_base_dir); |
- bool launched_kasko = kasko::api::InitializeReporter( |
- GetKaskoEndpoint(process.Pid()).c_str(), |
- crash_server.c_str(), |
- crash_reports_base_dir |
- .Append(L"Crash Reports") |
- .value() |
- .c_str(), |
- crash_reports_base_dir |
- .Append(kPermanentlyFailedReportsSubdir) |
- .value() |
- .c_str(), |
- &OnCrashReportUpload, nullptr); |
+ bool launched_kasko = InitializeKaskoReporter(GetKaskoEndpoint(process.Pid()), |
+ browser_data_directory); |
+ |
#if BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) |
// Only activate hang reports for the canary channel. For testing purposes, |
// Chrome instances with no channels will also report hangs. |
if (launched_kasko && |
(base::StringPiece16(channel_name) == L"" || |
base::StringPiece16(channel_name) == installer::kChromeChannelCanary)) { |
- on_hung_callback = |
- base::Bind(&DumpHungBrowserProcess, main_thread_id, channel_name); |
+ on_hung_callback = base::Bind(&DumpHungProcess, main_thread_id, |
+ channel_name, L"hung-process"); |
} |
#endif // BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) |
#endif // BUILDFLAG(ENABLE_KASKO) |
@@ -432,7 +259,7 @@ extern "C" int WatcherMain(const base::char16* registry_path, |
#if BUILDFLAG(ENABLE_KASKO) |
if (launched_kasko) |
- kasko::api::ShutdownReporter(); |
+ ShutdownKaskoReporter(); |
#endif // BUILDFLAG(ENABLE_KASKO) |
// Wind logging down. |