blob: 663283a52f67ffd2ec4e2da7b1e50711915fdb4d [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_SPARE_RENDER_PROCESS_HOST_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_SPARE_RENDER_PROCESS_HOST_MANAGER_H_
#include <optional>
#include "base/callback_list.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/browser/render_process_host_observer.h"
namespace content {
class BrowserContext;
class SiteInstanceImpl;
class RenderProcessHost;
// This class manages spare RenderProcessHosts.
//
// There is a singleton instance of this class which manages a single spare
// renderer (SpareRenderProcessHostManager::GetInstance(), below). This class
// encapsulates the implementation of
// RenderProcessHost::WarmupSpareRenderProcessHost()
//
// RenderProcessHostImpl should call
// SpareRenderProcessHostManager::MaybeTakeSpareRenderProcessHost when creating
// a new RPH. In this implementation, the spare renderer is bound to a
// BrowserContext and its default StoragePartition. If
// MaybeTakeSpareRenderProcessHost is called with a BrowserContext that does not
// match, the spare renderer is discarded. Only the default StoragePartition
// will be able to use a spare renderer. The spare renderer will also not be
// used as a guest renderer (flags_ contains kForGuestsOnly).
//
// It is safe to call WarmupSpareRenderProcessHost multiple times, although if
// called in a context where the spare renderer is not likely to be used
// performance may suffer due to the unnecessary RPH creation.
class CONTENT_EXPORT SpareRenderProcessHostManager
: public RenderProcessHostObserver {
public:
SpareRenderProcessHostManager();
~SpareRenderProcessHostManager() override;
SpareRenderProcessHostManager(const SpareRenderProcessHostManager& other) =
delete;
SpareRenderProcessHostManager& operator=(
const SpareRenderProcessHostManager& other) = delete;
static SpareRenderProcessHostManager& GetInstance();
// Start a spare renderer immediately if there isn't one.
// If the timeout is given, the spare render process will not be created
// if there is a delayed creation which indicates no timeout.
//
// The created spare render process will be destroyed after the timeout
// if it is given and accepted. Otherwise, the spare renderer will be kept
// until used by some navigation or cleared for memory pressure.
//
// The general rule for the timeout update is to always keep the value with
// a larger timeout. The timeout will be accepted when:
// * There is no spare render process or the spare render process was created
// for a different browser context.
// * The current timeout will be fired before the specified timeout.
// If the function is called again without a timeout, the current timeout will
// be cancelled. If the function is called again with a timeout firing after
// the current timeout, the timeout will be updated.
void WarmupSpareRenderProcessHost(
BrowserContext* browser_context,
std::optional<base::TimeDelta> timeout = std::nullopt);
RenderProcessHost* MaybeTakeSpareRenderProcessHost(
BrowserContext* browser_context,
SiteInstanceImpl* site_instance);
// Prepares for future requests (with an assumption that a future navigation
// might require a new process for |browser_context|).
//
// Note that depending on the caller PrepareForFutureRequests can be called
// after the spare_render_process_host_ has either been 1) matched and taken
// or 2) mismatched and ignored or 3) matched and ignored.
//
// The creation of new spare renderer will be delayed by `delay` if present.
// This is used to mitigate resource contention.
void PrepareForFutureRequests(
BrowserContext* browser_context,
std::optional<base::TimeDelta> delay = std::nullopt);
// Gracefully remove and cleanup a spare RenderProcessHost if it exists.
void CleanupSpareRenderProcessHost();
RenderProcessHost* spare_render_process_host() {
return spare_render_process_host_;
}
base::CallbackListSubscription RegisterSpareRenderProcessHostChangedCallback(
const base::RepeatingCallback<void(RenderProcessHost*)>& cb);
void SetDeferTimerTaskRunnerForTesting(
scoped_refptr<base::SequencedTaskRunner> task_runner);
private:
// Release ownership of the spare renderer. Called when the spare has either
// been 1) claimed to be used in a navigation or 2) shutdown somewhere else.
void ReleaseSpareRenderProcessHost();
// RenderProcessHostObserver:
void RenderProcessReady(RenderProcessHost* host) override;
void RenderProcessExited(RenderProcessHost* host,
const ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
// Start a spare renderer at a later time if there isn't one.
// This is to avoid resource contention between existing renderers and a
// new spare renderer.
void DeferredWarmupSpareRenderProcessHost(
BrowserContext* browser_context,
base::TimeDelta delay,
std::optional<base::TimeDelta> timeout);
void StartDestroyTimer(std::optional<base::TimeDelta> timeout);
bool DestroyTimerWillFireBefore(base::TimeDelta timeout);
// The clients who want to know when the spare render process host has
// changed.
base::RepeatingCallbackList<void(RenderProcessHost*)>
spare_render_process_host_changed_callback_list_;
// This is a bare pointer, because RenderProcessHost manages the lifetime of
// all its instances; see GetAllHosts().
raw_ptr<RenderProcessHost> spare_render_process_host_ = nullptr;
// The timer used to track the startup time of the spare renderer process.
std::unique_ptr<base::ElapsedTimer> process_startup_timer_;
// The timer used to track the delay of spare renderer creation.
std::unique_ptr<base::ElapsedTimer> delay_timer_;
base::OneShotTimer deferred_warmup_timer_;
base::OneShotTimer deferred_destroy_timer_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_SPARE_RENDER_PROCESS_HOST_MANAGER_H_