0
Files
src/content/browser/child_process_launcher.cc
Bo Liu a13e7c09e0 Add frame depth to ChildProcessLauncherPriority
Frame depth is the depth of the FrameTreeNode in the frame tree, with
the root being depth 0. This will be used to rank render processes.

Note depth and visibility are not independent when ranking widgets.
A visible widget of higher depth has higher priority than a hidden
widget of lower depth.

Also make inactive widgets stop contributing priority to its
renderer process.

Bug: 813232
Change-Id: Id9acefc40d6d2f2d94b5d62a592630037766d786
Reviewed-on: https://chromium-review.googlesource.com/934311
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546622}
2018-03-28 22:24:02 +00:00

182 lines
6.0 KiB
C++

// Copyright 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 "content/browser/child_process_launcher.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "build/build_config.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
namespace content {
using internal::ChildProcessLauncherHelper;
ChildProcessLauncher::ChildProcessLauncher(
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate,
std::unique_ptr<base::CommandLine> command_line,
int child_process_id,
Client* client,
std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
broker_client_invitation,
const mojo::edk::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown)
: client_(client),
termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
exit_code_(RESULT_CODE_NORMAL_EXIT),
starting_(true),
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
defined(UNDEFINED_SANITIZER)
terminate_child_on_shutdown_(false),
#else
terminate_child_on_shutdown_(terminate_on_shutdown),
#endif
weak_factory_(this) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
helper_ = new ChildProcessLauncherHelper(
child_process_id, client_thread_id_, std::move(command_line),
std::move(delegate), weak_factory_.GetWeakPtr(), terminate_on_shutdown,
std::move(broker_client_invitation), process_error_callback);
helper_->StartLaunchOnClientThread();
}
ChildProcessLauncher::~ChildProcessLauncher() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (process_.process.IsValid() && terminate_child_on_shutdown_) {
// Client has gone away, so just kill the process.
ChildProcessLauncherHelper::ForceNormalProcessTerminationAsync(
std::move(process_));
}
}
void ChildProcessLauncher::SetProcessPriority(
const ChildProcessLauncherPriority& priority) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Process to_pass = process_.process.Duplicate();
GetProcessLauncherTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
&ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread,
helper_, std::move(to_pass), priority));
}
void ChildProcessLauncher::Notify(
ChildProcessLauncherHelper::Process process,
int error_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
starting_ = false;
process_ = std::move(process);
if (process_.process.IsValid()) {
client_->OnProcessLaunched();
} else {
termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
// NOTE: May delete |this|.
client_->OnProcessLaunchFailed(error_code);
}
}
bool ChildProcessLauncher::IsStarting() {
// TODO(crbug.com/469248): This fails in some tests.
// DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return starting_;
}
const base::Process& ChildProcessLauncher::GetProcess() const {
// TODO(crbug.com/469248): This fails in some tests.
// DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return process_.process;
}
base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
bool known_dead,
int* exit_code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!process_.process.IsValid()) {
// Process is already gone, so return the cached termination status.
if (exit_code)
*exit_code = exit_code_;
return termination_status_;
}
termination_status_ =
helper_->GetTerminationStatus(process_, known_dead, &exit_code_);
if (exit_code)
*exit_code = exit_code_;
// POSIX: If the process crashed, then the kernel closed the socket for it and
// so the child has already died by the time we get here. Since
// GetTerminationStatus called waitpid with WNOHANG, it'll reap the process.
// However, if GetTerminationStatus didn't reap the child (because it was
// still running), we'll need to Terminate via ProcessWatcher. So we can't
// close the handle here.
if (termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING) {
process_.process.Exited(exit_code_);
process_.process.Close();
}
return termination_status_;
}
bool ChildProcessLauncher::Terminate(int exit_code) {
return IsStarting() ? false
: ChildProcessLauncherHelper::TerminateProcess(
GetProcess(), exit_code);
}
// static
bool ChildProcessLauncher::TerminateProcess(const base::Process& process,
int exit_code) {
return ChildProcessLauncherHelper::TerminateProcess(process, exit_code);
}
// static
void ChildProcessLauncher::SetRegisteredFilesForService(
const std::string& service_name,
catalog::RequiredFileMap required_files) {
ChildProcessLauncherHelper::SetRegisteredFilesForService(
service_name, std::move(required_files));
}
// static
void ChildProcessLauncher::ResetRegisteredFilesForTesting() {
ChildProcessLauncherHelper::ResetRegisteredFilesForTesting();
}
#if defined(OS_ANDROID)
// static
size_t ChildProcessLauncher::GetNumberOfRendererSlots() {
return ChildProcessLauncherHelper::GetNumberOfRendererSlots();
}
#endif // OS_ANDROID
ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
Client* client) {
Client* ret = client_;
client_ = client;
return ret;
}
bool ChildProcessLauncherPriority::operator==(
const ChildProcessLauncherPriority& other) const {
return background == other.background && frame_depth == other.frame_depth &&
boost_for_pending_views == other.boost_for_pending_views
#if defined(OS_ANDROID)
&& importance == other.importance
#endif
;
}
} // namespace content