summaryrefslogtreecommitdiffstats
path: root/chrome/tools
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/tools')
-rw-r--r--chrome/tools/DEPS2
-rw-r--r--chrome/tools/crash_service/crash_service.cc503
-rw-r--r--chrome/tools/crash_service/crash_service.h123
-rw-r--r--chrome/tools/crash_service/main.cc18
4 files changed, 15 insertions, 631 deletions
diff --git a/chrome/tools/DEPS b/chrome/tools/DEPS
index 2a98e95..adf68b9 100644
--- a/chrome/tools/DEPS
+++ b/chrome/tools/DEPS
@@ -1,9 +1,9 @@
include_rules = [
- "+breakpad",
"+chrome/browser",
"+chrome/third_party/hunspell/google",
"+chrome/utility/local_discovery",
"+content/browser",
"+content/public/browser",
+ "+components/breakpad",
"+third_party/re2",
]
diff --git a/chrome/tools/crash_service/crash_service.cc b/chrome/tools/crash_service/crash_service.cc
deleted file mode 100644
index 8face40..0000000
--- a/chrome/tools/crash_service/crash_service.cc
+++ /dev/null
@@ -1,503 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/tools/crash_service/crash_service.h"
-
-#include <windows.h>
-
-#include <sddl.h>
-#include <fstream>
-#include <map>
-
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/win/windows_version.h"
-#include "breakpad/src/client/windows/crash_generation/client_info.h"
-#include "breakpad/src/client/windows/crash_generation/crash_generation_server.h"
-#include "breakpad/src/client/windows/sender/crash_report_sender.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-
-namespace {
-
-const wchar_t kTestPipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
-
-const wchar_t kCrashReportURL[] = L"https://clients2.google.com/cr/report";
-const wchar_t kCheckPointFile[] = L"crash_checkpoint.txt";
-
-typedef std::map<std::wstring, std::wstring> CrashMap;
-
-bool CustomInfoToMap(const google_breakpad::ClientInfo* client_info,
- const std::wstring& reporter_tag, CrashMap* map) {
- google_breakpad::CustomClientInfo info = client_info->GetCustomInfo();
-
- for (uintptr_t i = 0; i < info.count; ++i) {
- (*map)[info.entries[i].name] = info.entries[i].value;
- }
-
- (*map)[L"rept"] = reporter_tag;
-
- return !map->empty();
-}
-
-bool WriteCustomInfoToFile(const std::wstring& dump_path, const CrashMap& map) {
- std::wstring file_path(dump_path);
- size_t last_dot = file_path.rfind(L'.');
- if (last_dot == std::wstring::npos)
- return false;
- file_path.resize(last_dot);
- file_path += L".txt";
-
- std::wofstream file(file_path.c_str(),
- std::ios_base::out | std::ios_base::app | std::ios::binary);
- if (!file.is_open())
- return false;
-
- CrashMap::const_iterator pos;
- for (pos = map.begin(); pos != map.end(); ++pos) {
- std::wstring line = pos->first;
- line += L':';
- line += pos->second;
- line += L'\n';
- file.write(line.c_str(), static_cast<std::streamsize>(line.length()));
- }
- return true;
-}
-
-// The window procedure task is to handle when a) the user logs off.
-// b) the system shuts down or c) when the user closes the window.
-LRESULT __stdcall CrashSvcWndProc(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam) {
- switch (message) {
- case WM_CLOSE:
- case WM_ENDSESSION:
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hwnd, message, wparam, lparam);
- }
- return 0;
-}
-
-// This is the main and only application window.
-HWND g_top_window = NULL;
-
-bool CreateTopWindow(HINSTANCE instance, bool visible) {
- WNDCLASSEXW wcx = {0};
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_HREDRAW | CS_VREDRAW;
- wcx.lpfnWndProc = CrashSvcWndProc;
- wcx.hInstance = instance;
- wcx.lpszClassName = L"crash_svc_class";
- ATOM atom = ::RegisterClassExW(&wcx);
- DWORD style = visible ? WS_POPUPWINDOW | WS_VISIBLE : WS_OVERLAPPED;
-
- // The window size is zero but being a popup window still shows in the
- // task bar and can be closed using the system menu or using task manager.
- HWND window = CreateWindowExW(0, wcx.lpszClassName, L"crash service", style,
- CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
- NULL, NULL, instance, NULL);
- if (!window)
- return false;
-
- ::UpdateWindow(window);
- VLOG(1) << "window handle is " << window;
- g_top_window = window;
- return true;
-}
-
-// Simple helper class to keep the process alive until the current request
-// finishes.
-class ProcessingLock {
- public:
- ProcessingLock() {
- ::InterlockedIncrement(&op_count_);
- }
- ~ProcessingLock() {
- ::InterlockedDecrement(&op_count_);
- }
- static bool IsWorking() {
- return (op_count_ != 0);
- }
- private:
- static volatile LONG op_count_;
-};
-
-volatile LONG ProcessingLock::op_count_ = 0;
-
-// This structure contains the information that the worker thread needs to
-// send a crash dump to the server.
-struct DumpJobInfo {
- DWORD pid;
- CrashService* self;
- CrashMap map;
- std::wstring dump_path;
-
- DumpJobInfo(DWORD process_id, CrashService* service,
- const CrashMap& crash_map, const std::wstring& path)
- : pid(process_id), self(service), map(crash_map), dump_path(path) {
- }
-};
-
-} // namespace
-
-// Command line switches:
-const char CrashService::kMaxReports[] = "max-reports";
-const char CrashService::kNoWindow[] = "no-window";
-const char CrashService::kReporterTag[] = "reporter";
-const char CrashService::kDumpsDir[] = "dumps-dir";
-const char CrashService::kPipeName[] = "pipe-name";
-
-CrashService::CrashService(const std::wstring& report_dir)
- : report_path_(report_dir),
- sender_(NULL),
- dumper_(NULL),
- requests_handled_(0),
- requests_sent_(0),
- clients_connected_(0),
- clients_terminated_(0) {
- chrome::RegisterPathProvider();
-}
-
-CrashService::~CrashService() {
- base::AutoLock lock(sending_);
- delete dumper_;
- delete sender_;
-}
-
-
-bool CrashService::Initialize(const std::wstring& command_line) {
- using google_breakpad::CrashReportSender;
- using google_breakpad::CrashGenerationServer;
-
- std::wstring pipe_name = kTestPipeName;
- int max_reports = -1;
-
- // The checkpoint file allows CrashReportSender to enforce the the maximum
- // reports per day quota. Does not seem to serve any other purpose.
- base::FilePath checkpoint_path = report_path_.Append(kCheckPointFile);
-
- // The dumps path is typically : '<user profile>\Local settings\
- // Application data\Goggle\Chrome\Crash Reports' and the report path is
- // Application data\Google\Chrome\Reported Crashes.txt
- base::FilePath user_data_dir;
- if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
- LOG(ERROR) << "could not get DIR_USER_DATA";
- return false;
- }
- report_path_ = user_data_dir.Append(chrome::kCrashReportLog);
-
- CommandLine cmd_line = CommandLine::FromString(command_line);
-
- base::FilePath dumps_path;
- if (cmd_line.HasSwitch(kDumpsDir)) {
- dumps_path = base::FilePath(cmd_line.GetSwitchValueNative(kDumpsDir));
- } else {
- if (!PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
- LOG(ERROR) << "could not get DIR_CRASH_DUMPS";
- return false;
- }
- }
-
- // We can override the send reports quota with a command line switch.
- if (cmd_line.HasSwitch(kMaxReports))
- max_reports = _wtoi(cmd_line.GetSwitchValueNative(kMaxReports).c_str());
-
- // Allow the global pipe name to be overridden for better testability.
- if (cmd_line.HasSwitch(kPipeName))
- pipe_name = cmd_line.GetSwitchValueNative(kPipeName);
-
-#ifdef _WIN64
- pipe_name += L"-x64";
-#endif
-
- if (max_reports > 0) {
- // Create the http sender object.
- sender_ = new CrashReportSender(checkpoint_path.value());
- sender_->set_max_reports_per_day(max_reports);
- }
-
- SECURITY_ATTRIBUTES security_attributes = {0};
- SECURITY_ATTRIBUTES* security_attributes_actual = NULL;
-
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- SECURITY_DESCRIPTOR* security_descriptor =
- reinterpret_cast<SECURITY_DESCRIPTOR*>(
- GetSecurityDescriptorForLowIntegrity());
- DCHECK(security_descriptor != NULL);
-
- security_attributes.nLength = sizeof(security_attributes);
- security_attributes.lpSecurityDescriptor = security_descriptor;
- security_attributes.bInheritHandle = FALSE;
-
- security_attributes_actual = &security_attributes;
- }
-
- // Create the OOP crash generator object.
- dumper_ = new CrashGenerationServer(pipe_name, security_attributes_actual,
- &CrashService::OnClientConnected, this,
- &CrashService::OnClientDumpRequest, this,
- &CrashService::OnClientExited, this,
- NULL, NULL,
- true, &dumps_path.value());
-
- if (!dumper_) {
- LOG(ERROR) << "could not create dumper";
- if (security_attributes.lpSecurityDescriptor)
- LocalFree(security_attributes.lpSecurityDescriptor);
- return false;
- }
-
- if (!CreateTopWindow(::GetModuleHandleW(NULL),
- !cmd_line.HasSwitch(kNoWindow))) {
- LOG(ERROR) << "could not create window";
- if (security_attributes.lpSecurityDescriptor)
- LocalFree(security_attributes.lpSecurityDescriptor);
- return false;
- }
-
- reporter_tag_ = L"crash svc";
- if (cmd_line.HasSwitch(kReporterTag))
- reporter_tag_ = cmd_line.GetSwitchValueNative(kReporterTag);
-
- // Log basic information.
- VLOG(1) << "pipe name is " << pipe_name
- << "\ndumps at " << dumps_path.value()
- << "\nreports at " << report_path_.value();
-
- if (sender_) {
- VLOG(1) << "checkpoint is " << checkpoint_path.value()
- << "\nserver is " << kCrashReportURL
- << "\nmaximum " << sender_->max_reports_per_day() << " reports/day"
- << "\nreporter is " << reporter_tag_;
- }
- // Start servicing clients.
- if (!dumper_->Start()) {
- LOG(ERROR) << "could not start dumper";
- if (security_attributes.lpSecurityDescriptor)
- LocalFree(security_attributes.lpSecurityDescriptor);
- return false;
- }
-
- if (security_attributes.lpSecurityDescriptor)
- LocalFree(security_attributes.lpSecurityDescriptor);
-
- // This is throwaway code. We don't need to sync with the browser process
- // once Google Update is updated to a version supporting OOP crash handling.
- // Create or open an event to signal the browser process that the crash
- // service is initialized.
- HANDLE running_event =
- ::CreateEventW(NULL, TRUE, TRUE, L"g_chrome_crash_svc");
- // If the browser already had the event open, the CreateEvent call did not
- // signal it. We need to do it manually.
- ::SetEvent(running_event);
-
- return true;
-}
-
-void CrashService::OnClientConnected(void* context,
- const google_breakpad::ClientInfo* client_info) {
- ProcessingLock lock;
- VLOG(1) << "client start. pid = " << client_info->pid();
- CrashService* self = static_cast<CrashService*>(context);
- ::InterlockedIncrement(&self->clients_connected_);
-}
-
-void CrashService::OnClientExited(void* context,
- const google_breakpad::ClientInfo* client_info) {
- ProcessingLock lock;
- VLOG(1) << "client end. pid = " << client_info->pid();
- CrashService* self = static_cast<CrashService*>(context);
- ::InterlockedIncrement(&self->clients_terminated_);
-
- if (!self->sender_)
- return;
-
- // When we are instructed to send reports we need to exit if there are
- // no more clients to service. The next client that runs will start us.
- // Only chrome.exe starts crash_service with a non-zero max_reports.
- if (self->clients_connected_ > self->clients_terminated_)
- return;
- if (self->sender_->max_reports_per_day() > 0) {
- // Wait for the other thread to send crashes, if applicable. The sender
- // thread takes the sending_ lock, so the sleep is just to give it a
- // chance to start.
- ::Sleep(1000);
- base::AutoLock lock(self->sending_);
- // Some people can restart chrome very fast, check again if we have
- // a new client before exiting for real.
- if (self->clients_connected_ == self->clients_terminated_) {
- VLOG(1) << "zero clients. exiting";
- ::PostMessage(g_top_window, WM_CLOSE, 0, 0);
- }
- }
-}
-
-void CrashService::OnClientDumpRequest(void* context,
- const google_breakpad::ClientInfo* client_info,
- const std::wstring* file_path) {
- ProcessingLock lock;
-
- if (!file_path) {
- LOG(ERROR) << "dump with no file path";
- return;
- }
- if (!client_info) {
- LOG(ERROR) << "dump with no client info";
- return;
- }
-
- CrashService* self = static_cast<CrashService*>(context);
- if (!self) {
- LOG(ERROR) << "dump with no context";
- return;
- }
-
- CrashMap map;
- CustomInfoToMap(client_info, self->reporter_tag_, &map);
-
- // Move dump file to the directory under client breakpad dump location.
- base::FilePath dump_location = base::FilePath(*file_path);
- CrashMap::const_iterator it = map.find(L"breakpad-dump-location");
- if (it != map.end()) {
- base::FilePath alternate_dump_location = base::FilePath(it->second);
- file_util::CreateDirectoryW(alternate_dump_location);
- alternate_dump_location = alternate_dump_location.Append(
- dump_location.BaseName());
- base::Move(dump_location, alternate_dump_location);
- dump_location = alternate_dump_location;
- }
-
- DWORD pid = client_info->pid();
- VLOG(1) << "dump for pid = " << pid << " is " << dump_location.value();
-
- if (!WriteCustomInfoToFile(dump_location.value(), map)) {
- LOG(ERROR) << "could not write custom info file";
- }
-
- if (!self->sender_)
- return;
-
- // Send the crash dump using a worker thread. This operation has retry
- // logic in case there is no internet connection at the time.
- DumpJobInfo* dump_job = new DumpJobInfo(pid, self, map,
- dump_location.value());
- if (!::QueueUserWorkItem(&CrashService::AsyncSendDump,
- dump_job, WT_EXECUTELONGFUNCTION)) {
- LOG(ERROR) << "could not queue job";
- }
-}
-
-// We are going to try sending the report several times. If we can't send,
-// we sleep from one minute to several hours depending on the retry round.
-unsigned long CrashService::AsyncSendDump(void* context) {
- if (!context)
- return 0;
-
- DumpJobInfo* info = static_cast<DumpJobInfo*>(context);
-
- std::wstring report_id = L"<unsent>";
-
- const DWORD kOneMinute = 60*1000;
- const DWORD kOneHour = 60*kOneMinute;
-
- const DWORD kSleepSchedule[] = {
- 24*kOneHour,
- 8*kOneHour,
- 4*kOneHour,
- kOneHour,
- 15*kOneMinute,
- 0};
-
- int retry_round = arraysize(kSleepSchedule) - 1;
-
- do {
- ::Sleep(kSleepSchedule[retry_round]);
- {
- // Take the server lock while sending. This also prevent early
- // termination of the service object.
- base::AutoLock lock(info->self->sending_);
- VLOG(1) << "trying to send report for pid = " << info->pid;
- google_breakpad::ReportResult send_result
- = info->self->sender_->SendCrashReport(kCrashReportURL, info->map,
- info->dump_path, &report_id);
- switch (send_result) {
- case google_breakpad::RESULT_FAILED:
- report_id = L"<network issue>";
- break;
- case google_breakpad::RESULT_REJECTED:
- report_id = L"<rejected>";
- ++info->self->requests_handled_;
- retry_round = 0;
- break;
- case google_breakpad::RESULT_SUCCEEDED:
- ++info->self->requests_sent_;
- ++info->self->requests_handled_;
- retry_round = 0;
- break;
- case google_breakpad::RESULT_THROTTLED:
- report_id = L"<throttled>";
- break;
- default:
- report_id = L"<unknown>";
- break;
- };
- }
-
- VLOG(1) << "dump for pid =" << info->pid << " crash2 id =" << report_id;
- --retry_round;
- } while (retry_round >= 0);
-
- if (!::DeleteFileW(info->dump_path.c_str()))
- LOG(WARNING) << "could not delete " << info->dump_path;
-
- delete info;
- return 0;
-}
-
-int CrashService::ProcessingLoop() {
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- VLOG(1) << "session ending..";
- while (ProcessingLock::IsWorking()) {
- ::Sleep(50);
- }
-
- VLOG(1) << "clients connected :" << clients_connected_
- << "\nclients terminated :" << clients_terminated_
- << "\ndumps serviced :" << requests_handled_
- << "\ndumps reported :" << requests_sent_;
-
- return static_cast<int>(msg.wParam);
-}
-
-PSECURITY_DESCRIPTOR CrashService::GetSecurityDescriptorForLowIntegrity() {
- // Build the SDDL string for the label.
- std::wstring sddl = L"S:(ML;;NW;;;S-1-16-4096)";
-
- DWORD error = ERROR_SUCCESS;
- PSECURITY_DESCRIPTOR sec_desc = NULL;
-
- PACL sacl = NULL;
- BOOL sacl_present = FALSE;
- BOOL sacl_defaulted = FALSE;
-
- if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(),
- SDDL_REVISION,
- &sec_desc, NULL)) {
- if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl,
- &sacl_defaulted)) {
- return sec_desc;
- }
- }
-
- return NULL;
-}
diff --git a/chrome/tools/crash_service/crash_service.h b/chrome/tools/crash_service/crash_service.h
deleted file mode 100644
index 9ea56c5..0000000
--- a/chrome/tools/crash_service/crash_service.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TOOLS_CRASH_SERVICE_CRASH_SERVICE_H_
-#define CHROME_TOOLS_CRASH_SERVICE_CRASH_SERVICE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/synchronization/lock.h"
-
-namespace google_breakpad {
-
-class CrashReportSender;
-class CrashGenerationServer;
-class ClientInfo;
-
-}
-
-// This class implements an out-of-process crash server. It uses breakpad's
-// CrashGenerationServer and CrashReportSender to generate and then send the
-// crash dumps. Internally, it uses OS specific pipe to allow applications to
-// register for crash dumps and later on when a registered application crashes
-// it will signal an event that causes this code to wake up and perform a
-// crash dump on the signaling process. The dump is then stored on disk and
-// possibly sent to the crash2 servers.
-class CrashService {
- public:
- // The ctor takes a directory that needs to be writable and will create
- // a subdirectory inside to keep logs, crashes and checkpoint files.
- explicit CrashService(const std::wstring& report_dir);
- ~CrashService();
-
- // Starts servicing crash dumps. The command_line specifies various behaviors,
- // see below for more information. Returns false if it failed. Do not use
- // other members in that case.
- bool Initialize(const std::wstring& command_line);
-
- // Command line switches:
- //
- // --max-reports=<number>
- // Allows to override the maximum number for reports per day. Normally
- // the crash dumps are never sent so if you want to send any you must
- // specify a positive number here.
- static const char kMaxReports[];
- // --no-window
- // Does not create a visible window on the desktop. The window does not have
- // any other functionality other than allowing the crash service to be
- // gracefully closed.
- static const char kNoWindow[];
- // --reporter=<string>
- // Allows to specify a custom string that appears on the detail crash report
- // page in the crash server. This should be a 25 chars or less string.
- // The default tag if not specified is 'crash svc'.
- static const char kReporterTag[];
- // --dumps-dir=<directory-path>
- // Override the directory to which crash dump files will be written.
- static const char kDumpsDir[];
- // --pipe-name=<string>
- // Override the name of the Windows named pipe on which we will
- // listen for crash dump request messages.
- static const char kPipeName[];
-
- // Returns number of crash dumps handled.
- int requests_handled() const {
- return requests_handled_;
- }
- // Returns number of crash clients registered.
- int clients_connected() const {
- return clients_connected_;
- }
- // Returns number of crash clients terminated.
- int clients_terminated() const {
- return clients_terminated_;
- }
-
- // Starts the processing loop. This function does not return unless the
- // user is logging off or the user closes the crash service window. The
- // return value is a good number to pass in ExitProcess().
- int ProcessingLoop();
-
- private:
- static void OnClientConnected(void* context,
- const google_breakpad::ClientInfo* client_info);
-
- static void OnClientDumpRequest(
- void* context,
- const google_breakpad::ClientInfo* client_info,
- const std::wstring* file_path);
-
- static void OnClientExited(void* context,
- const google_breakpad::ClientInfo* client_info);
-
- // This routine sends the crash dump to the server. It takes the sending_
- // lock when it is performing the send.
- static unsigned long __stdcall AsyncSendDump(void* context);
-
- // Returns the security descriptor which access to low integrity processes
- // The caller is supposed to free the security descriptor by calling
- // LocalFree.
- PSECURITY_DESCRIPTOR GetSecurityDescriptorForLowIntegrity();
-
- google_breakpad::CrashGenerationServer* dumper_;
- google_breakpad::CrashReportSender* sender_;
-
- // the path to dumps and logs directory.
- base::FilePath report_path_;
- // the extra tag sent to the server with each dump.
- std::wstring reporter_tag_;
-
- // clients serviced statistics:
- int requests_handled_;
- int requests_sent_;
- volatile long clients_connected_;
- volatile long clients_terminated_;
- base::Lock sending_;
-
- DISALLOW_COPY_AND_ASSIGN(CrashService);
-};
-
-#endif // CHROME_TOOLS_CRASH_SERVICE_CRASH_SERVICE_H_
diff --git a/chrome/tools/crash_service/main.cc b/chrome/tools/crash_service/main.cc
index c4889c7..9fd9e87 100644
--- a/chrome/tools/crash_service/main.cc
+++ b/chrome/tools/crash_service/main.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/tools/crash_service/crash_service.h"
-
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
@@ -12,6 +10,10 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "components/breakpad/tools/crash_service.h"
namespace {
@@ -39,6 +41,8 @@ int __stdcall wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd_line,
CommandLine::Init(0, NULL);
+ chrome::RegisterPathProvider();
+
// We use/create a directory under the user's temp folder, for logging.
base::FilePath operating_dir;
GetCrashServiceDirectory(&operating_dir);
@@ -55,8 +59,14 @@ int __stdcall wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd_line,
VLOG(1) << "session start. cmdline is [" << cmd_line << "]";
- CrashService crash_service(operating_dir.value());
- if (!crash_service.Initialize(::GetCommandLineW()))
+ base::FilePath dumps_path;
+ if (!PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
+ LOG(ERROR) << "could not get DIR_CRASH_DUMPS";
+ return 1;
+ }
+
+ breakpad::CrashService crash_service;
+ if (!crash_service.Initialize(operating_dir, dumps_path))
return 1;
VLOG(1) << "ready to process crash requests";