Commit 14f8ffb5 authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Add process priority override logic.

This adds the ability for the RenderProcessHost calculated priority to be
overridden by external logic. This will allow overriding process priority with
embedder-specific calculated values.

BUG=971272


Change-Id: I0524c678de03b17efa01f7caac6cc791c4a52d45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1894705Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712997}
parent 7d1bdf08
......@@ -1274,6 +1274,53 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, LowPriorityFramesDisabled) {
RenderProcessHost::SetRunRendererInProcess(false);
}
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, PriorityOverride) {
// RenderProcessHostImpl::UpdateProcessPriority has an early check of
// run_renderer_in_process and exits for RenderProcessHosts without a child
// process launcher. In order to skip initializing that here and the layer of
// indirection, we explicitly run in-process, which we must also disable once
// the test has finished to prevent crashing on exit.
RenderProcessHost::SetRunRendererInProcess(true);
RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
RenderProcessHostImpl::CreateRenderProcessHost(
ShellContentBrowserClient::Get()->browser_context(), nullptr, nullptr,
false /* is_for_guests_only */));
// It starts off as normal priority with no override.
EXPECT_FALSE(process->HasPriorityOverride());
EXPECT_FALSE(process->IsProcessBackgrounded());
process->SetPriorityOverride(false /* foreground */);
EXPECT_TRUE(process->HasPriorityOverride());
EXPECT_TRUE(process->IsProcessBackgrounded());
process->SetPriorityOverride(true /* foreground */);
EXPECT_TRUE(process->HasPriorityOverride());
EXPECT_FALSE(process->IsProcessBackgrounded());
process->SetPriorityOverride(false /* foreground */);
EXPECT_TRUE(process->HasPriorityOverride());
EXPECT_TRUE(process->IsProcessBackgrounded());
// Add a pending view, and expect the process to *stay* backgrounded.
process->AddPendingView();
EXPECT_TRUE(process->HasPriorityOverride());
EXPECT_TRUE(process->IsProcessBackgrounded());
// Clear the override. The pending view should cause the process to go back to
// being foregrounded.
process->ClearPriorityOverride();
EXPECT_FALSE(process->HasPriorityOverride());
EXPECT_FALSE(process->IsProcessBackgrounded());
// Clear the pending view so the test doesn't explode.
process->RemovePendingView();
EXPECT_FALSE(process->HasPriorityOverride());
EXPECT_TRUE(process->IsProcessBackgrounded());
RenderProcessHost::SetRunRendererInProcess(false);
}
// This test verifies properties of RenderProcessHostImpl *before* Init method
// is called.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ConstructedButNotInitializedYet) {
......
......@@ -3638,6 +3638,20 @@ void RenderProcessHostImpl::RemovePriorityClient(
UpdateProcessPriorityInputs();
}
void RenderProcessHostImpl::SetPriorityOverride(bool foregrounded) {
priority_override_ = foregrounded;
UpdateProcessPriority();
}
bool RenderProcessHostImpl::HasPriorityOverride() {
return priority_override_.has_value();
}
void RenderProcessHostImpl::ClearPriorityOverride() {
priority_override_.reset();
UpdateProcessPriority();
}
void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
sudden_termination_allowed_ = enabled;
}
......@@ -4492,7 +4506,7 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
has_recorded_media_stream_frame_depth_metric_ = true;
}
const ChildProcessLauncherPriority priority(
ChildProcessLauncherPriority priority(
visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererBackgrounding),
media_stream_count_ > 0, foreground_service_worker_count_ > 0,
......@@ -4504,6 +4518,28 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
#endif
);
// If a priority override has been specified, use it instead.
// TODO(chrisha): After experimentation, either integrate the experimental
// logic into this class, or rip out the existing logic entirely.
if (priority_override_.has_value()) {
bool foregrounded = priority_override_.value();
priority = ChildProcessLauncherPriority(
foregrounded, /* is_visible */
foregrounded, /* has_media_stream */
foregrounded, /* has_foreground_service_worker */
false, /* has_only_low_priority_frames */
0, /* frame_depth */
foregrounded, /* intersects_viewport */
false /* boost_for_pending_views */
#if defined(OS_ANDROID)
,
foregrounded ? ChildProcessImportance::NORMAL
: ChildProcessImportance::MODERATE /* importance */
#endif
);
DCHECK_EQ(!foregrounded, priority.is_background());
}
if (priority_ == priority)
return;
const bool background_state_changed =
......
......@@ -207,6 +207,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
void RemovePendingView() override;
void AddPriorityClient(PriorityClient* priority_client) override;
void RemovePriorityClient(PriorityClient* priority_client) override;
void SetPriorityOverride(bool foreground) override;
bool HasPriorityOverride() override;
void ClearPriorityOverride() override;
#if defined(OS_ANDROID)
ChildProcessImportance GetEffectiveImportance() override;
void DumpProcessStack() override;
......@@ -917,6 +920,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
ChildProcessLauncherPriority priority_;
// If this is set then the built-in process priority calculation system is
// ignored, and an externally computed process priority is used. Set to true
// and the process will stay foreground priority; set to false and it will
// stay background priority.
base::Optional<bool> priority_override_;
// Used to allow a RenderWidgetHost to intercept various messages on the
// IO thread.
scoped_refptr<RenderWidgetHelper> widget_helper_;
......
......@@ -295,6 +295,12 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual void AddPriorityClient(PriorityClient* priority_client) = 0;
virtual void RemovePriorityClient(PriorityClient* priority_client) = 0;
// Sets a process priority override. This overrides the entire built-in
// priority setting mechanism for the process.
virtual void SetPriorityOverride(bool foreground) = 0;
virtual bool HasPriorityOverride() = 0;
virtual void ClearPriorityOverride() = 0;
#if defined(OS_ANDROID)
// Return the highest importance of all widgets in this process.
virtual ChildProcessImportance GetEffectiveImportance() = 0;
......
......@@ -305,6 +305,14 @@ void MockRenderProcessHost::RemovePriorityClient(
priority_clients_.erase(priority_client);
}
void MockRenderProcessHost::SetPriorityOverride(bool foreground) {}
bool MockRenderProcessHost::HasPriorityOverride() {
return false;
}
void MockRenderProcessHost::ClearPriorityOverride() {}
#if defined(OS_ANDROID)
ChildProcessImportance MockRenderProcessHost::GetEffectiveImportance() {
NOTIMPLEMENTED();
......
......@@ -121,6 +121,9 @@ class MockRenderProcessHost : public RenderProcessHost {
void RemovePendingView() override;
void AddPriorityClient(PriorityClient* priority_client) override;
void RemovePriorityClient(PriorityClient* priority_client) override;
void SetPriorityOverride(bool foreground) override;
bool HasPriorityOverride() override;
void ClearPriorityOverride() override;
#if defined(OS_ANDROID)
ChildProcessImportance GetEffectiveImportance() override;
void DumpProcessStack() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment