blob: a53cae559a737451a0012538df4c0c91d9affc2f [file] [log] [blame]
// Copyright 2019 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/chrome_cleaner/test/child_process_logger.h"
#include <vector>
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
namespace chrome_cleaner {
ChildProcessLogger::ChildProcessLogger() = default;
ChildProcessLogger::~ChildProcessLogger() = default;
bool ChildProcessLogger::Initialize() {
// Adapted from
// https://cs.chromium.org/chromium/src/sandbox/win/src/handle_inheritance_test.cc
if (!temp_dir_.CreateUniqueTempDir()) {
PLOG(ERROR) << "Could not create temp dir for child stdout";
return false;
}
if (!CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_name_)) {
PLOG(ERROR) << "Could not create temp file for child stdout";
return false;
}
SECURITY_ATTRIBUTES attrs = {};
attrs.nLength = sizeof(attrs);
attrs.bInheritHandle = true;
child_stdout_handle_.Set(
::CreateFile(temp_file_name_.value().c_str(), GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
&attrs, OPEN_EXISTING, 0, nullptr));
if (!child_stdout_handle_.IsValid()) {
PLOG(ERROR) << "Could not open child stdout file";
return false;
}
return true;
}
void ChildProcessLogger::UpdateLaunchOptions(
base::LaunchOptions* options) const {
DCHECK(child_stdout_handle_.IsValid());
options->handles_to_inherit.push_back(child_stdout_handle_.Get());
options->stdin_handle = INVALID_HANDLE_VALUE;
options->stdout_handle = child_stdout_handle_.Get();
options->stderr_handle = child_stdout_handle_.Get();
}
void ChildProcessLogger::UpdateSandboxPolicy(
sandbox::TargetPolicy* policy) const {
DCHECK(child_stdout_handle_.IsValid());
policy->SetStdoutHandle(child_stdout_handle_.Get());
policy->SetStderrHandle(child_stdout_handle_.Get());
}
void ChildProcessLogger::DumpLogs() const {
DCHECK(!temp_file_name_.empty());
if (!base::PathExists(temp_file_name_)) {
LOG(ERROR) << "Child process log file doesn't exist";
return;
}
// Collect the child process log file, and dump the contents, to help
// debugging failures.
std::string log_file_contents;
if (!base::ReadFileToString(temp_file_name_, &log_file_contents)) {
LOG(ERROR) << "Failed to read child process log file";
return;
}
std::vector<base::StringPiece> lines =
base::SplitStringPiece(log_file_contents, "\n", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (lines.empty()) {
LOG(ERROR) << "Child process log file is empty";
return;
}
LOG(ERROR) << "Dumping child process logs";
for (const auto& line : lines) {
LOG(ERROR) << "Child process: " << line;
}
LOG(ERROR) << "Finished dumping child process logs";
}
} // namespace chrome_cleaner