| // Copyright 2020 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_AGENT_SCHEDULING_GROUP_HOST_H_ |
| #define CONTENT_BROWSER_RENDERER_HOST_AGENT_SCHEDULING_GROUP_HOST_H_ |
| |
| #include <stdint.h> |
| |
| #include "base/containers/id_map.h" |
| #include "base/memory/raw_ref.h" |
| #include "base/memory/safe_ref.h" |
| #include "base/state_transitions.h" |
| #include "base/supports_user_data.h" |
| #include "content/browser/browser_interface_broker_impl.h" |
| #include "content/common/agent_scheduling_group.mojom.h" |
| #include "content/common/associated_interfaces.mojom.h" |
| #include "content/common/content_export.h" |
| #include "content/common/renderer.mojom-forward.h" |
| #include "content/public/browser/render_process_host_observer.h" |
| #include "content/public/common/content_features.h" |
| #include "ipc/ipc_listener.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_receiver_set.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "third_party/blink/public/common/tokens/tokens.h" |
| #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h" |
| #include "third_party/blink/public/mojom/frame/frame_replication_state.mojom-forward.h" |
| #include "third_party/blink/public/mojom/shared_storage/shared_storage_worklet_service.mojom-forward.h" |
| #include "third_party/blink/public/mojom/worker/worklet_global_scope_creation_params.mojom-forward.h" |
| |
| namespace IPC { |
| class ChannelProxy; |
| class Message; |
| } // namespace IPC |
| |
| namespace content { |
| |
| class AgentSchedulingGroupHostFactory; |
| class BrowserMessageFilter; |
| class RenderProcessHost; |
| class SiteInstanceGroup; |
| |
| // Browser-side host of an AgentSchedulingGroup, used for |
| // AgentSchedulingGroup-bound messaging. AgentSchedulingGroup is Blink's unit of |
| // scheduling and performance isolation, which is the only way to obtain |
| // ordering guarantees between different Mojo (associated) interfaces and legacy |
| // IPC messages. |
| // |
| // AgentSchedulingGroups can be assigned at various granularities, as coarse as |
| // process-wide or as specific as SiteInstanceGroup. There cannot be more than |
| // one AgentSchedulingGroup per SiteInstanceGroup without breaking IPC ordering |
| // for RenderWidgetHost. (SiteInstanceGroups themselves can be tuned to contain |
| // one or more SiteInstances, depending on platform and policy.) |
| // |
| // An AgentSchedulingGroupHost is stored as (and owned by) UserData on the |
| // RenderProcessHost. |
| class CONTENT_EXPORT AgentSchedulingGroupHost |
| : public base::SupportsUserData, |
| public RenderProcessHostObserver, |
| public IPC::Listener, |
| public mojom::AgentSchedulingGroupHost { |
| public: |
| // Get the appropriate AgentSchedulingGroupHost for the given |
| // `site_instance_group` and `process`. Depending on the value of |
| // `features::kMBIModeParam`, there may be a single AgentSchedulingGroupHost |
| // per RenderProcessHost, or a single one per SiteInstanceGroup, which may |
| // lead to multiple AgentSchedulingGroupHosts per RenderProcessHost. This |
| // method will never return null. |
| static AgentSchedulingGroupHost* GetOrCreate( |
| const SiteInstanceGroup& site_instance_group, |
| RenderProcessHost& process); |
| |
| // Should not be called explicitly. Use `GetOrCreate()` instead. |
| explicit AgentSchedulingGroupHost(RenderProcessHost& process); |
| ~AgentSchedulingGroupHost() override; |
| |
| void AddFilter(BrowserMessageFilter* filter); |
| |
| RenderProcessHost* GetProcess(); |
| // Ensure that the process this AgentSchedulingGroupHost belongs to is alive. |
| // Returns |false| if any part of the initialization failed. |
| bool Init(); |
| |
| // Returns a SafeRef to `this`. |
| base::SafeRef<AgentSchedulingGroupHost> GetSafeRef() const; |
| |
| int32_t id_for_debugging() const { return id_for_debugging_; } |
| |
| // IPC and mojo messages to be forwarded to the RenderProcessHost, for now. In |
| // the future they will be handled directly by the AgentSchedulingGroupHost. |
| // IPC: |
| IPC::ChannelProxy* GetChannel(); |
| // This is marked virtual for use in tests by `MockAgentSchedulingGroupHost`. |
| virtual bool Send(IPC::Message* message); |
| void AddRoute(int32_t routing_id, IPC::Listener* listener); |
| void RemoveRoute(int32_t routing_id); |
| |
| // Mojo: |
| mojom::RouteProvider* GetRemoteRouteProvider(); |
| void CreateFrame(mojom::CreateFrameParamsPtr params); |
| void CreateView(mojom::CreateViewParamsPtr params); |
| void CreateSharedStorageWorkletService( |
| mojo::PendingReceiver<blink::mojom::SharedStorageWorkletService> receiver, |
| blink::mojom::WorkletGlobalScopeCreationParamsPtr |
| global_scope_creation_params); |
| |
| void ReportNoBinderForInterface(const std::string& error); |
| |
| static void set_agent_scheduling_group_host_factory_for_testing( |
| AgentSchedulingGroupHostFactory* asgh_factory); |
| static AgentSchedulingGroupHostFactory* |
| get_agent_scheduling_group_host_factory_for_testing(); |
| |
| // mojom::AgentSchedulingGroupHost overrides. |
| void DidUnloadRenderFrame(const blink::LocalFrameToken& frame_token) override; |
| |
| private: |
| enum class LifecycleState { |
| // Just instantiated, no route assigned yet. |
| kNewborn, |
| |
| // Bound mojo connection to the renderer. |
| kBound, |
| |
| // Intermediate state between renderer process exit and rebinding mojo |
| // connections. |
| kRenderProcessExited, |
| |
| // RenderProcessHost is destroyed, and `this` is pending for deletion. |
| // kRenderProcessHostDestroyed is the terminal state of the state machine. |
| kRenderProcessHostDestroyed, |
| }; |
| friend base::StateTransitions<LifecycleState>; |
| friend std::ostream& operator<<(std::ostream& os, LifecycleState state); |
| |
| // IPC::Listener |
| bool OnMessageReceived(const IPC::Message& message) override; |
| void OnBadMessageReceived(const IPC::Message& message) override; |
| void OnAssociatedInterfaceRequest( |
| const std::string& interface_name, |
| mojo::ScopedInterfaceEndpointHandle handle) override; |
| |
| // RenderProcessHostObserver: |
| void RenderProcessExited(RenderProcessHost* host, |
| const ChildProcessTerminationInfo& info) override; |
| void RenderProcessHostDestroyed(RenderProcessHost* host) override; |
| |
| void ResetIPC(); |
| void SetUpIPC(); |
| |
| void SetState(LifecycleState state); |
| |
| IPC::Listener* GetListener(int32_t routing_id); |
| |
| static int32_t GetNextID(); |
| |
| // The RenderProcessHost this AgentSchedulingGroup is assigned to. |
| // |
| // TODO(https://crbug.com/1382971): Change back to `raw_ref` after the ad-hoc |
| // debugging is no longer needed to investigate the bug. |
| const base::SafeRef<RenderProcessHost> process_; |
| |
| int32_t id_for_debugging_{GetNextID()}; |
| |
| // This AgentSchedulingGroup's legacy IPC channel. Will only be used in |
| // `features::MBIMode::kEnabledPerRenderProcessHost` or |
| // `features::MBIMode::kEnabledPerSiteInstance` mode. |
| std::unique_ptr<IPC::ChannelProxy> channel_; |
| |
| // Map of registered IPC listeners. |
| base::IDMap<IPC::Listener*> listener_map_; |
| |
| // Remote stub of `mojom::AgentSchedulingGroup`, used for sending calls to the |
| // (renderer-side) `AgentSchedulingGroup`. |
| mojo::AssociatedRemote<mojom::AgentSchedulingGroup> mojo_remote_; |
| |
| // Implementation of `mojom::AgentSchedulingGroupHost`, used for responding to |
| // calls from the (renderer-side) `AgentSchedulingGroup`. |
| mojo::AssociatedReceiver<mojom::AgentSchedulingGroupHost> receiver_; |
| |
| // BrowserInterfaceBroker implementation through which this |
| // AgentSchedulingGroupHost exposes ASG-scoped Mojo services to the |
| // currently active document. |
| // |
| // The interfaces that can be requested from this broker are defined in the |
| // content/browser/browser_interface_binders.cc file, in the functions which |
| // take a `AgentSchedulingGroupHost*` parameter. |
| // |
| // TODO(crbug.com/1132752): Enable capability control for Prerender2 by |
| // initializing BrowserInterfaceBrokerImpl with a non-null |
| // MojoBinderPolicyApplier pointer. |
| BrowserInterfaceBrokerImpl<AgentSchedulingGroupHost, |
| AgentSchedulingGroupHost*> |
| broker_{this}; |
| mojo::Receiver<blink::mojom::BrowserInterfaceBroker> broker_receiver_{ |
| &broker_}; |
| |
| // The `mojom::RouteProvider` mojo pair to setup |
| // `blink::AssociatedInterfaceProvider` routes between this and the |
| // renderer-side `AgentSchedulingGroup`. |
| mojo::AssociatedRemote<mojom::RouteProvider> remote_route_provider_; |
| |
| LifecycleState state_{LifecycleState::kNewborn}; |
| |
| // This is used to create SafeRefs, and as a result, cannot be reset. |
| base::WeakPtrFactory<AgentSchedulingGroupHost> weak_ptr_factory_{this}; |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, |
| AgentSchedulingGroupHost::LifecycleState state); |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_RENDERER_HOST_AGENT_SCHEDULING_GROUP_HOST_H_ |