blob: 0d435292411fe96d2c29e556a462085d27c5cd64 [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_LOADER_RESOURCE_CACHE_MANAGER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_CACHE_MANAGER_H_
#include <map>
#include <memory>
#include <set>
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/process_lock.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/loader/resource_cache.mojom.h"
#include "url/origin.h"
namespace content {
class NavigationRequest;
class RenderFrameHostImpl;
class ResourceCacheHostObserver;
// Used as a key to group ResourceCache.
struct ResourceCacheKey {
ResourceCacheKey(const ProcessLock& process_lock, const url::Origin& origin);
bool operator==(const ResourceCacheKey& rhs) const;
bool operator<(const ResourceCacheKey& rhs) const;
const ProcessLock process_lock;
const url::Origin origin;
};
// Manages ResourceCache. Refer to
// //third_party/blink/public/mojom/loader/resource_cache.mojom for what
// ResourceCache does.
// ResourceCacheManager maintains mojo connections to ResourceCache instances,
// which live in renderers, keyed with ProcessLock and origin. Upon navigation
// commit, it tries to find or create a mojo remote to ResourceCache when there
// is no active ResourceCache for the newly committing document for the given
// ProcessLock/origin. The ResourceCache will be created and hosted by another
// existing renderer, not the one that we're about to commit to. The remote
// might also be used for subsequent navigation commits to pass the (cloned)
// remote to another frame in a new renderer that has the same
// ProcessLock/origin. When a remote is disconnected, ResourceCacheManager tries
// to find a renderer to host a ResourceCache for the same ProcessLock/origin.
//
// ResourceCacheManager and ResourceCache exist only to record histograms.
// These shouldn't plumb resources among renderers.
// Exists per profile (i.e. owned by StoragePartition).
class CONTENT_EXPORT ResourceCacheManager {
public:
ResourceCacheManager();
~ResourceCacheManager();
// Initializes `pending_remote` when an existing renderer has the same
// process lock and the renderer has a ResourceCache with the same
// Process lock/origin as the navigation. If the existing renderer
// doesn't host a ResourceCache, creates a ResourceCache in an existing
// renderer and initializes `pending_remote` with it. If no matching renderer
// exists, `pending_remote` stays uninitialized.
// `navigation_request` must be about to commit navigation.
void MaybeInitializeResourceCacheRemoteOnCommitNavigation(
mojo::PendingRemote<blink::mojom::ResourceCache>& pending_remote,
NavigationRequest& navigation_request);
// Called when a RenderFrameHostImpl became ineligible to host a
// ResourceCache, e.g., the renderer is deleted or is stored in BFCache.
void RenderFrameHostBecameIneligible(RenderFrameHostImpl& render_frame_host);
// Called when lifecycle state of `render_frame_host` has changed.
void RenderFrameHostStateChanged(RenderFrameHostImpl& render_frame_host,
RenderFrameHost::LifecycleState old_state,
RenderFrameHost::LifecycleState new_state);
// Destroys a host observer.
void DestroyHostObserver(ResourceCacheHostObserver* observer);
// Returns true when a frame associated with `render_frame_host` is
// hosting a ResourceCache.
bool IsRenderFrameHostHostingRemoteCache(
RenderFrameHostImpl& render_frame_host);
private:
struct ResourceCacheEntry {
ResourceCacheEntry(mojo::Remote<blink::mojom::ResourceCache> remote,
GlobalRenderFrameHostId render_frame_host_id);
~ResourceCacheEntry();
ResourceCacheEntry(const ResourceCacheEntry&) = delete;
ResourceCacheEntry& operator=(const ResourceCacheEntry&) = delete;
mojo::Remote<blink::mojom::ResourceCache> remote;
GlobalRenderFrameHostId render_frame_host_id;
};
// Inserts `render_frame_host_id` to `non_hosting_frame_hosts_`.
void InsertNonHostingRenderFrameId(
const ResourceCacheKey& key,
GlobalRenderFrameHostId render_frame_host_id);
// Looks for an active ResourceCache. If not found, tries to create a new
// ResourceCache in a renderer. Returns a RenderFrameHostImpl that hosts the
// ResourceCache. Returns nullptr when no resource cache is/ found nor
// created.
RenderFrameHostImpl* FindOrMaybeCreateResourceCache(
const ResourceCacheKey& key);
// Makes `render_frame_host` host a ResourceCache.
void HostResourceCache(RenderFrameHostImpl& render_frame_host,
const ResourceCacheKey& key);
// Creates blink::mojom::ResourceCache interface from `render_frame_host`.
mojo::Remote<blink::mojom::ResourceCache> CreateResourceCacheRemote(
RenderFrameHostImpl& render_frame_host,
const ResourceCacheKey& key);
// Called when a mojo remote to a ResourceCache is disconnected, to pick
// a new renderer to host a ResourceCache for the `key`.
void OnRemoteCacheDisconnected(const ResourceCacheKey& key,
GlobalRenderFrameHostId render_frame_host_id);
// Contains active remote caches.
std::map<ResourceCacheKey, ResourceCacheEntry> remote_caches_;
// Keeps track of renderers that don't host ResourceCache. Used to select
// a new host for a ResourceCache when a renderer that hosted the
// ResourceCache is disconnected.
std::map<ResourceCacheKey, std::set<GlobalRenderFrameHostId>>
non_hosting_frame_hosts_;
// A set of WebContentsObservers to keep track of lifecycle state changes of
// RenderFrameHosts that host ResourceCaches. Used to handle lifecycle state
// changes. If a RenderFrameHost becomes inactive (e.g. pending deletion,
// BFCached), the host becomes ineligible to host a ResourceCache. If the
// RenderFrameHost becomes active again, the RenderFrameHost becomes eligible
// to use/host a ResourceCache.
std::set<std::unique_ptr<ResourceCacheHostObserver>,
base::UniquePtrComparator>
host_observers_;
base::WeakPtrFactory<ResourceCacheManager> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_LOADER_RESOURCE_CACHE_MANAGER_H_