crash_service.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/crash/tools/crash_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sddl.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/crash_generation/client_info.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/crash_generation/crash_generation_server.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/sender/crash_report_sender.h"
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace breakpad {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kTestPipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCrashReportURL[] = L"https://clients2.google.com/cr/report";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCheckPointFile[] = L"crash_checkpoint.txt";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<std::wstring, std::wstring> CrashMap;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CustomInfoToMap(const google_breakpad::ClientInfo* client_info,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::wstring& reporter_tag, CrashMap* map) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  google_breakpad::CustomClientInfo info = client_info->GetCustomInfo();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uintptr_t i = 0; i < info.count; ++i) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*map)[info.entries[i].name] = info.entries[i].value;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*map)[L"rept"] = reporter_tag;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !map->empty();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WriteCustomInfoToFile(const std::wstring& dump_path, const CrashMap& map) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring file_path(dump_path);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t last_dot = file_path.rfind(L'.');
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_dot == std::wstring::npos)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_path.resize(last_dot);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_path += L".txt";
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wofstream file(file_path.c_str(),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::ios_base::out | std::ios_base::app | std::ios::binary);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file.is_open())
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashMap::const_iterator pos;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (pos = map.begin(); pos != map.end(); ++pos) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring line = pos->first;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line += L':';
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line += pos->second;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line += L'\n';
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file.write(line.c_str(), static_cast<std::streamsize>(line.length()));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The window procedure task is to handle when a) the user logs off.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// b) the system shuts down or c) when the user closes the window.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT __stdcall CrashSvcWndProc(HWND hwnd, UINT message,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  WPARAM wparam, LPARAM lparam) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (message) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_CLOSE:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_ENDSESSION:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_DESTROY:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PostQuitMessage(0);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return DefWindowProc(hwnd, message, wparam, lparam);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the main and only application window.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWND g_top_window = NULL;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateTopWindow(HINSTANCE instance, bool visible) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WNDCLASSEXW wcx = {0};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcx.cbSize = sizeof(wcx);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcx.style = CS_HREDRAW | CS_VREDRAW;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcx.lpfnWndProc = CrashSvcWndProc;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcx.hInstance = instance;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wcx.lpszClassName = L"crash_svc_class";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ATOM atom = ::RegisterClassExW(&wcx);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD style = visible ? WS_POPUPWINDOW | WS_VISIBLE : WS_OVERLAPPED;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The window size is zero but being a popup window still shows in the
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task bar and can be closed using the system menu or using task manager.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HWND window = CreateWindowExW(0, wcx.lpszClassName, L"crash service", style,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                NULL, NULL, instance, NULL);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::UpdateWindow(window);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "window handle is " << window;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_top_window = window;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple helper class to keep the process alive until the current request
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finishes.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProcessingLock {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessingLock() {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::InterlockedIncrement(&op_count_);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ProcessingLock() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::InterlockedDecrement(&op_count_);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsWorking() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (op_count_ != 0);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static volatile LONG op_count_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)volatile LONG ProcessingLock::op_count_ = 0;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure contains the information that the worker thread needs to
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// send a crash dump to the server.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DumpJobInfo {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD pid;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashService* self;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashMap map;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring dump_path;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DumpJobInfo(DWORD process_id, CrashService* service,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const CrashMap& crash_map, const std::wstring& path)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : pid(process_id), self(service), map(crash_map), dump_path(path) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command line switches:
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kMaxReports[]        = "max-reports";
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kNoWindow[]          = "no-window";
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kReporterTag[]       = "reporter";
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kDumpsDir[]          = "dumps-dir";
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kPipeName[]          = "pipe-name";
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CrashService::CrashService()
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : sender_(NULL),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dumper_(NULL),
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requests_handled_(0),
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requests_sent_(0),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clients_connected_(0),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clients_terminated_(0) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrashService::~CrashService() {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(sending_);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete dumper_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete sender_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool CrashService::Initialize(const base::FilePath& operating_dir,
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                              const base::FilePath& dumps_path) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using google_breakpad::CrashReportSender;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using google_breakpad::CrashGenerationServer;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring pipe_name = kTestPipeName;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_reports = -1;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The checkpoint file allows CrashReportSender to enforce the the maximum
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reports per day quota. Does not seem to serve any other purpose.
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::FilePath checkpoint_path = operating_dir.Append(kCheckPointFile);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::FilePath dumps_path_to_use = dumps_path;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cmd_line.HasSwitch(kDumpsDir)) {
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    dumps_path_to_use =
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        base::FilePath(cmd_line.GetSwitchValueNative(kDumpsDir));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can override the send reports quota with a command line switch.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cmd_line.HasSwitch(kMaxReports))
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_reports = _wtoi(cmd_line.GetSwitchValueNative(kMaxReports).c_str());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the global pipe name to be overridden for better testability.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cmd_line.HasSwitch(kPipeName))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pipe_name = cmd_line.GetSwitchValueNative(kPipeName);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN64
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pipe_name += L"-x64";
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (max_reports > 0) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create the http sender object.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sender_ = new CrashReportSender(checkpoint_path.value());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sender_->set_max_reports_per_day(max_reports);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECURITY_ATTRIBUTES security_attributes = {0};
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECURITY_ATTRIBUTES* security_attributes_actual = NULL;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECURITY_DESCRIPTOR* security_descriptor =
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<SECURITY_DESCRIPTOR*>(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetSecurityDescriptorForLowIntegrity());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(security_descriptor != NULL);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_attributes.nLength = sizeof(security_attributes);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_attributes.lpSecurityDescriptor = security_descriptor;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_attributes.bInheritHandle = FALSE;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_attributes_actual = &security_attributes;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the OOP crash generator object.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dumper_ = new CrashGenerationServer(pipe_name, security_attributes_actual,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &CrashService::OnClientConnected, this,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &CrashService::OnClientDumpRequest, this,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &CrashService::OnClientExited, this,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NULL, NULL,
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                      true, &dumps_path_to_use.value());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dumper_) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "could not create dumper";
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (security_attributes.lpSecurityDescriptor)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LocalFree(security_attributes.lpSecurityDescriptor);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CreateTopWindow(::GetModuleHandleW(NULL),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       !cmd_line.HasSwitch(kNoWindow))) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "could not create window";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (security_attributes.lpSecurityDescriptor)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LocalFree(security_attributes.lpSecurityDescriptor);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reporter_tag_ = L"crash svc";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cmd_line.HasSwitch(kReporterTag))
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reporter_tag_ = cmd_line.GetSwitchValueNative(kReporterTag);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log basic information.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "pipe name is " << pipe_name
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          << "\ndumps at " << dumps_path_to_use.value();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sender_) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "checkpoint is " << checkpoint_path.value()
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "\nserver is " << kCrashReportURL
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "\nmaximum " << sender_->max_reports_per_day() << " reports/day"
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "\nreporter is " << reporter_tag_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start servicing clients.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dumper_->Start()) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "could not start dumper";
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (security_attributes.lpSecurityDescriptor)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LocalFree(security_attributes.lpSecurityDescriptor);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (security_attributes.lpSecurityDescriptor)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocalFree(security_attributes.lpSecurityDescriptor);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is throwaway code. We don't need to sync with the browser process
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // once Google Update is updated to a version supporting OOP crash handling.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create or open an event to signal the browser process that the crash
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // service is initialized.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE running_event =
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::CreateEventW(NULL, TRUE, TRUE, L"g_chrome_crash_svc");
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the browser already had the event open, the CreateEvent call did not
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // signal it. We need to do it manually.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::SetEvent(running_event);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientConnected(void* context,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const google_breakpad::ClientInfo* client_info) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessingLock lock;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "client start. pid = " << client_info->pid();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashService* self = static_cast<CrashService*>(context);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::InterlockedIncrement(&self->clients_connected_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientExited(void* context,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const google_breakpad::ClientInfo* client_info) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessingLock lock;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "client end. pid = " << client_info->pid();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashService* self = static_cast<CrashService*>(context);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::InterlockedIncrement(&self->clients_terminated_);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!self->sender_)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When we are instructed to send reports we need to exit if there are
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no more clients to service. The next client that runs will start us.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only chrome.exe starts crash_service with a non-zero max_reports.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (self->clients_connected_ > self->clients_terminated_)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (self->sender_->max_reports_per_day() > 0) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for the other thread to send crashes, if applicable. The sender
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread takes the sending_ lock, so the sleep is just to give it a
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // chance to start.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::Sleep(1000);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(self->sending_);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Some people can restart chrome very fast, check again if we have
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a new client before exiting for real.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (self->clients_connected_ == self->clients_terminated_) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "zero clients. exiting";
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::PostMessage(g_top_window, WM_CLOSE, 0, 0);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientDumpRequest(void* context,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const google_breakpad::ClientInfo* client_info,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::wstring* file_path) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessingLock lock;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_path) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "dump with no file path";
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!client_info) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "dump with no client info";
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashService* self = static_cast<CrashService*>(context);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!self) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "dump with no context";
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrashMap map;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CustomInfoToMap(client_info, self->reporter_tag_, &map);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Move dump file to the directory under client breakpad dump location.
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath dump_location = base::FilePath(*file_path);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CrashMap::const_iterator it = map.find(L"breakpad-dump-location");
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it != map.end()) {
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath alternate_dump_location = base::FilePath(it->second);
351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::CreateDirectoryW(alternate_dump_location);
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    alternate_dump_location = alternate_dump_location.Append(
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dump_location.BaseName());
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::Move(dump_location, alternate_dump_location);
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dump_location = alternate_dump_location;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DWORD pid = client_info->pid();
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VLOG(1) << "dump for pid = " << pid << " is " << dump_location.value();
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!WriteCustomInfoToFile(dump_location.value(), map)) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "could not write custom info file";
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!self->sender_)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the crash dump using a worker thread. This operation has retry
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // logic in case there is no internet connection at the time.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DumpJobInfo* dump_job = new DumpJobInfo(pid, self, map,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          dump_location.value());
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::QueueUserWorkItem(&CrashService::AsyncSendDump,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           dump_job, WT_EXECUTELONGFUNCTION)) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "could not queue job";
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are going to try sending the report several times. If we can't send,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we sleep from one minute to several hours depending on the retry round.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned long CrashService::AsyncSendDump(void* context) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DumpJobInfo* info = static_cast<DumpJobInfo*>(context);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring report_id = L"<unsent>";
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD kOneMinute = 60*1000;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD kOneHour = 60*kOneMinute;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD kSleepSchedule[] = {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      24*kOneHour,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      8*kOneHour,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      4*kOneHour,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kOneHour,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      15*kOneMinute,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0};
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int retry_round = arraysize(kSleepSchedule) - 1;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::Sleep(kSleepSchedule[retry_round]);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Take the server lock while sending. This also prevent early
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // termination of the service object.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(info->self->sending_);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "trying to send report for pid = " << info->pid;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_breakpad::ReportResult send_result
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          = info->self->sender_->SendCrashReport(kCrashReportURL, info->map,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 info->dump_path, &report_id);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (send_result) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case google_breakpad::RESULT_FAILED:
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          report_id = L"<network issue>";
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case google_breakpad::RESULT_REJECTED:
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          report_id = L"<rejected>";
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++info->self->requests_handled_;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          retry_round = 0;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case google_breakpad::RESULT_SUCCEEDED:
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++info->self->requests_sent_;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++info->self->requests_handled_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          retry_round = 0;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case google_breakpad::RESULT_THROTTLED:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          report_id = L"<throttled>";
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          report_id = L"<unknown>";
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "dump for pid =" << info->pid << " crash2 id =" << report_id;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --retry_round;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (retry_round >= 0);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::DeleteFileW(info->dump_path.c_str()))
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "could not delete " << info->dump_path;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete info;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CrashService::ProcessingLoop() {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MSG msg;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (GetMessage(&msg, NULL, 0, 0)) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TranslateMessage(&msg);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatchMessage(&msg);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "session ending..";
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (ProcessingLock::IsWorking()) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::Sleep(50);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "clients connected :" << clients_connected_
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\nclients terminated :" << clients_terminated_
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\ndumps serviced :" << requests_handled_
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\ndumps reported :" << requests_sent_;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(msg.wParam);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PSECURITY_DESCRIPTOR CrashService::GetSecurityDescriptorForLowIntegrity() {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build the SDDL string for the label.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring sddl = L"S:(ML;;NW;;;S-1-16-4096)";
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD error = ERROR_SUCCESS;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PSECURITY_DESCRIPTOR sec_desc = NULL;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PACL sacl = NULL;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL sacl_present = FALSE;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL sacl_defaulted = FALSE;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(),
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                             SDDL_REVISION,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                             &sec_desc, NULL)) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &sacl_defaulted)) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return sec_desc;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace breakpad
489