[go: nahoru, domu]

blob: 9f2f424d5dfd67809b76a3694aec162b0ddd4e23 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/logging.h"
#include <cstdio>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/platform_file.h"
#include "base/files/scoped_file.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/zygote_host/zygote_host_linux.h"
namespace ash {
namespace {
// This is true when logging redirect was tried for the first user in the
// session.
bool g_chrome_logging_redirect_tried = false;
// This should be set to true for tests that rely on log redirection.
bool g_force_log_redirection = false;
template <typename ProcessHost>
void ReinitializeLoggingForProcessHost(ProcessHost* process_host,
const logging::LoggingSettings& settings,
base::PlatformFile raw_log_file_fd) {
static_assert(std::is_same<content::ChildProcessHost, ProcessHost>() ||
std::is_same<content::RenderProcessHost, ProcessHost>());
base::ScopedFD log_file_descriptor(HANDLE_EINTR(dup(raw_log_file_fd)));
if (log_file_descriptor.get() < 0) {
DLOG(WARNING) << "Unable to duplicate log file handle";
return;
}
process_host->ReinitializeLogging(settings.logging_dest,
std::move(log_file_descriptor));
}
void LogFileSetUp(const base::CommandLine& command_line,
const base::FilePath& log_path,
const base::FilePath& target_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The |log_path| is the new log file after log rotation. so it shouldn't be
// deleted even if it already exists.
logging::LoggingSettings settings;
settings.logging_dest = logging::DetermineLoggingDestination(command_line);
settings.log_file_path = log_path.value().c_str();
if (!logging::InitLogging(settings)) {
DLOG(ERROR) << "Unable to initialize logging to " << log_path.value();
base::ThreadPool::PostTask(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&logging::RemoveSymlinkAndLog, log_path, target_path));
return;
}
base::ScopedFILE log_file(logging::DuplicateLogFILE());
base::PlatformFile log_file_fd = fileno(log_file.get());
if (log_file_fd < 0) {
DLOG(WARNING) << "Unable to duplicate log file handle";
return;
}
// Redirect Zygote and future children's logs.
content::ZygoteHost::GetInstance()->ReinitializeLogging(settings.logging_dest,
log_file_fd);
// Redirect child processes' logs.
for (content::BrowserChildProcessHostIterator it; !it.Done(); ++it)
ReinitializeLoggingForProcessHost(it.GetHost(), settings, log_file_fd);
for (auto it(content::RenderProcessHost::AllHostsIterator()); !it.IsAtEnd();
it.Advance()) {
ReinitializeLoggingForProcessHost(it.GetCurrentValue(), settings,
log_file_fd);
}
}
} // namespace
void ForceLogRedirectionForTesting() {
g_force_log_redirection = true;
}
void RedirectChromeLogging(const base::CommandLine& command_line) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Only redirect when on an actual device. To do otherwise conflicts with
// --vmodule that developers may want to use.
if (!base::SysInfo::IsRunningOnChromeOS() && !g_force_log_redirection)
return;
if (g_chrome_logging_redirect_tried) {
LOG(WARNING) << "NOT redirecting logging for multi-profiles case.";
return;
}
g_chrome_logging_redirect_tried = true;
if (command_line.HasSwitch(switches::kDisableLoggingRedirect))
return;
// Redirect logs to the session log directory, if set. Otherwise
// defaults to the profile dir.
const base::FilePath log_path = logging::GetSessionLogFile(command_line);
LOG(WARNING) << "Redirecting post-login logging to " << log_path.value();
// Rotate the old log files when redirecting.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&logging::SetUpLogFile, log_path, /*new_log=*/true),
base::BindOnce(&LogFileSetUp, command_line, log_path));
}
} // namespace ash