// Copyright 2012 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_CHILD_CHILD_THREAD_IMPL_H_ #define CONTENT_CHILD_CHILD_THREAD_IMPL_H_ #include #include #include #include #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread.h" #include "build/build_config.h" #include "components/variations/child_process_field_trial_syncer.h" #include "content/common/associated_interfaces.mojom.h" #include "content/common/child_process.mojom.h" #include "content/public/child/child_thread.h" #include "ipc/ipc.mojom.h" #include "ipc/ipc_buildflags.h" // For BUILDFLAG(IPC_MESSAGE_LOG_ENABLED). #include "ipc/ipc_platform_file.h" #include "ipc/message_router.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/binder_map.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "mojo/public/cpp/system/message_pipe.h" #include "services/tracing/public/mojom/background_tracing_agent.mojom.h" #include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h" #if BUILDFLAG(IS_WIN) #include "content/public/common/font_cache_win.mojom.h" #include "mojo/public/cpp/bindings/remote.h" #endif namespace IPC { class MessageFilter; class SyncChannel; class SyncMessageFilter; } // namespace IPC namespace mojo { class OutgoingInvitation; namespace core { class ScopedIPCSupport; } // namespace core } // namespace mojo namespace tracing { class BackgroundTracingAgentProviderImpl; } // namespace tracing namespace content { class InProcessChildThreadParams; // The main thread of a child process derives from this class. class ChildThreadImpl : public IPC::Listener, virtual public ChildThread { public: struct Options; // Creates the thread. explicit ChildThreadImpl(base::RepeatingClosure quit_closure); // Allow to be used for single-process mode and for in process gpu mode via // options. ChildThreadImpl(base::RepeatingClosure quit_closure, const Options& options); ChildThreadImpl(const ChildThreadImpl&) = delete; ChildThreadImpl& operator=(const ChildThreadImpl&) = delete; // ChildProcess::main_thread() is reset after Shutdown(), and before the // destructor, so any subsystem that relies on ChildProcess::main_thread() // must be terminated before Shutdown returns. In particular, if a subsystem // has a thread that post tasks to ChildProcess::main_thread(), that thread // should be joined in Shutdown(). ~ChildThreadImpl() override; virtual void Shutdown(); // Returns true if the thread should be destroyed. virtual bool ShouldBeDestroyed(); // IPC::Sender implementation: bool Send(IPC::Message* msg) override; // ChildThread implementation: #if BUILDFLAG(IS_WIN) void PreCacheFont(const LOGFONT& log_font) override; void ReleaseCachedFonts() override; #endif void RecordAction(const base::UserMetricsAction& action) override; void RecordComputedAction(const std::string& action) override; void BindHostReceiver(mojo::GenericPendingReceiver receiver) override; scoped_refptr GetIOTaskRunner() override; void SetFieldTrialGroup(const std::string& trial_name, const std::string& group_name) override; IPC::SyncChannel* channel() { return channel_.get(); } IPC::MessageRouter* GetRouter(); IPC::SyncMessageFilter* sync_message_filter() const { return sync_message_filter_.get(); } scoped_refptr main_thread_runner() const { return main_thread_runner_; } // Returns the one child thread. Can only be called on the main thread. static ChildThreadImpl* current(); void GetBackgroundTracingAgentProvider( mojo::PendingReceiver receiver); // Returns a reference to the thread-safe SharedRemote // interface endpoint. const mojo::SharedRemote& child_process_host() const { return child_process_host_; } // Explicitly closes the ChildProcessHost connection. This will cause the // host-side object to be torn down and clean up resources tied to this // process (or this thread object, in single-process mode). void DisconnectChildProcessHost(); virtual void RunServiceDeprecated(const std::string& service_name, mojo::ScopedMessagePipeHandle service_pipe); virtual void BindServiceInterface(mojo::GenericPendingReceiver receiver); virtual void OnBindReceiver(mojo::GenericPendingReceiver receiver); protected: friend class ChildProcess; // Called when the process refcount is 0. virtual void OnProcessFinalRelease(); // Must be called by subclasses during initialization if and only if they set // |Options::expose_interfaces_to_browser| to |true|. This makes |binders| // available to handle incoming interface requests from the browser. void ExposeInterfacesToBrowser(mojo::BinderMap binders); virtual bool OnControlMessageReceived(const IPC::Message& msg); // IPC::Listener implementation: bool OnMessageReceived(const IPC::Message& msg) override; void OnAssociatedInterfaceRequest( const std::string& interface_name, mojo::ScopedInterfaceEndpointHandle handle) override; void OnChannelConnected(int32_t peer_pid) override; void OnChannelError() override; bool on_channel_error_called() const { return on_channel_error_called_; } bool IsInBrowserProcess() const; private: // TODO(crbug.com/1111231): This class is a friend so that it can call our // private mojo implementation methods, acting as a pass-through. This is only // necessary during the associated interface migration, after which, // AgentSchedulingGroup will not act as a pass-through to the private methods // here. At that point we'll remove this friend class. friend class AgentSchedulingGroup; class IOThreadState; class ChildThreadMessageRouter : public IPC::MessageRouter { public: // |sender| must outlive this object. explicit ChildThreadMessageRouter(IPC::Sender* sender); bool Send(IPC::Message* msg) override; // MessageRouter overrides. bool RouteMessage(const IPC::Message& msg) override; private: const raw_ptr sender_; }; void Init(const Options& options); // IPC message handlers. void EnsureConnected(); #if BUILDFLAG(IS_WIN) const mojo::Remote& GetFontCacheWin(); #endif base::Thread mojo_ipc_thread_{"Mojo IPC"}; std::unique_ptr mojo_ipc_support_; #if BUILDFLAG(IS_WIN) mutable mojo::Remote font_cache_win_; #endif std::unique_ptr channel_; // Allows threads other than the main thread to send sync messages. scoped_refptr sync_message_filter_; // Implements message routing functionality to the consumers of // ChildThreadImpl. ChildThreadMessageRouter router_; // The OnChannelError() callback was invoked - the channel is dead, don't // attempt to communicate. bool on_channel_error_called_; // TaskRunner to post tasks to the main thread. scoped_refptr main_thread_runner_; // Used to quit the main thread. base::RepeatingClosure quit_closure_; std::unique_ptr background_tracing_agent_provider_; scoped_refptr browser_process_io_runner_; // Pointer to a global object which is never deleted. raw_ptr field_trial_syncer_ = nullptr; std::unique_ptr> channel_connected_factory_; scoped_refptr ipc_task_runner_; // An interface to the browser's process host object. mojo::SharedRemote child_process_host_; // ChildThreadImpl state which lives on the IO thread, including its // implementation of the mojom ChildProcess interface. scoped_refptr io_thread_state_; base::WeakPtrFactory weak_factory_{this}; }; struct ChildThreadImpl::Options { Options(const Options& other); ~Options(); class Builder; bool with_legacy_ipc_channel = true; bool connect_to_browser = false; scoped_refptr browser_process_io_runner; std::vector startup_filters; raw_ptr mojo_invitation = nullptr; scoped_refptr ipc_task_runner; // Indicates that this child process exposes one or more Mojo interfaces to // the browser process. Subclasses which initialize this to |true| must // explicitly call |ExposeInterfacesToBrowser()| some time during // initialization. bool exposes_interfaces_to_browser = false; using ServiceBinder = base::RepeatingCallback; ServiceBinder service_binder; private: Options(); }; class ChildThreadImpl::Options::Builder { public: Builder(); Builder(const Builder&) = delete; Builder& operator=(const Builder&) = delete; Builder& InBrowserProcess(const InProcessChildThreadParams& params); Builder& ConnectToBrowser(bool connect_to_browser); Builder& WithLegacyIPCChannel(bool with_legacy_ipc_channel); Builder& AddStartupFilter(IPC::MessageFilter* filter); Builder& IPCTaskRunner( scoped_refptr ipc_task_runner); Builder& ServiceBinder(ServiceBinder binder); Builder& ExposesInterfacesToBrowser(); Options Build(); private: struct Options options_; }; } // namespace content #endif // CONTENT_CHILD_CHILD_THREAD_IMPL_H_