#include <memory>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/win/access_control_list.h"
#include "base/win/security_descriptor.h"
#include "base/win/sid.h"
#include "remoting/base/crash/breakpad_utils.h"
#include "remoting/base/crash/crash_reporting_breakpad.h"
#include "remoting/base/logging.h"
#include "remoting/base/version.h"
#include "third_party/breakpad/breakpad/src/client/windows/crash_generation/crash_generation_server.h"
namespace remoting {
namespace {
using base::win::SecurityDescriptor;
using base::win::Sid;
using base::win::SecurityAccessMode::kGrant;
using base::win::WellKnownSid::kLocalSystem;
constexpr bool kNoInheritance = false;
class BreakpadServer {
public:
BreakpadServer();
BreakpadServer(const BreakpadServer&) = delete;
BreakpadServer& operator=(const BreakpadServer&) = delete;
~BreakpadServer();
static BreakpadServer& GetInstance();
void set_client_connected_time(base::Time client_connected_time) {
client_connected_time_ = client_connected_time;
}
base::Time get_client_connected_time() { return client_connected_time_; }
private:
base::Time client_connected_time_;
std::unique_ptr<google_breakpad::CrashGenerationServer> crash_server_;
};
void OnClientConnectedCallback(void* context,
const google_breakpad::ClientInfo* client_info) {
HOST_LOG << "OOP Crash client connected";
BreakpadServer::GetInstance().set_client_connected_time(
base::Time::NowFromSystemTime());
}
void OnClientDumpRequestCallback(void* context,
const google_breakpad::ClientInfo* client_info,
const std::wstring* file_path) {
if (!file_path) {
LOG(ERROR) << "OnClientDumpRequestCallback called with invalid file_path";
return;
}
base::FilePath dump_file(*file_path);
if (!GetMinidumpDirectoryPath().IsParent(dump_file)) {
LOG(ERROR) << "Minidump written to an unexpected location: " << dump_file;
return;
}
base::Value::Dict metadata;
metadata.Set(kBreakpadProductVersionKey, REMOTING_VERSION_STRING);
auto process_start_time =
BreakpadServer::GetInstance().get_client_connected_time();
auto process_uptime = base::Time::NowFromSystemTime() - process_start_time;
metadata.Set(kBreakpadProcessUptimeKey,
base::NumberToString(process_uptime.InMilliseconds()));
WriteMetadataForMinidump(dump_file, std::move(metadata));
}
BreakpadServer::BreakpadServer() {
base::win::SecurityDescriptor sd;
sd.set_owner(Sid(kLocalSystem));
sd.set_group(Sid(kLocalSystem));
if (!sd.SetDaclEntry(kLocalSystem, kGrant, FILE_ALL_ACCESS, kNoInheritance)) {
LOG(ERROR) << "Failed to set named pipe security attributes, skipping "
<< "out-of-process crash handler initialization.";
return;
}
SECURITY_DESCRIPTOR security_descriptor = sd.ToAbsolute();
SECURITY_ATTRIBUTES security_attributes = {0};
security_attributes.nLength = sizeof(security_attributes);
security_attributes.lpSecurityDescriptor = &security_descriptor;
security_attributes.bInheritHandle = false;
crash_server_ = std::make_unique<google_breakpad::CrashGenerationServer>(
kCrashServerPipeName, &security_attributes,
OnClientConnectedCallback,
nullptr,
OnClientDumpRequestCallback,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
true, &GetMinidumpDirectoryPath().value());
crash_server_->Start();
}
BreakpadServer::~BreakpadServer() = default;
BreakpadServer& BreakpadServer::GetInstance() {
static base::NoDestructor<BreakpadServer> instance;
return *instance;
}
}
void InitializeOopCrashServer() {
BreakpadServer::GetInstance();
}
}