1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141

content / browser / child_process_host_impl.h [blame]

// 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_BROWSER_CHILD_PROCESS_HOST_IMPL_H_
#define CONTENT_BROWSER_CHILD_PROCESS_HOST_IMPL_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/common/child_process.mojom.h"
#include "content/common/content_export.h"
#include "content/public/browser/child_process_host.h"
#include "ipc/ipc_listener.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/invitation.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/memory/memory_pressure_listener.h"
#endif

namespace IPC {
class Channel;
#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC)
class MessageFilter;
#endif
}  // namespace IPC

namespace content {
class ChildProcessHostDelegate;

// Provides common functionality for hosting a child process and processing IPC
// messages between the host and the child process. Users are responsible
// for the actual launching and terminating of the child processes.
class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
                                            public IPC::Listener,
                                            public mojom::ChildProcessHost {
 public:
  ChildProcessHostImpl(const ChildProcessHostImpl&) = delete;
  ChildProcessHostImpl& operator=(const ChildProcessHostImpl&) = delete;

  ~ChildProcessHostImpl() override;

  // Derives a tracing process id from a child process id. Child process ids
  // cannot be used directly in child process for tracing due to security
  // reasons (see: discussion in crrev.com/1173263004). This method is meant to
  // be used when tracing for identifying cross-process shared memory from a
  // process which knows the child process id of its endpoints. The value
  // returned by this method is guaranteed to be equal to the value returned by
  // MemoryDumpManager::GetTracingProcessId() in the corresponding child
  // process.
  //
  // Never returns MemoryDumpManager::kInvalidTracingProcessId.
  // Returns only memory_instrumentation::mojom::kServiceTracingProcessId in
  // single-process mode.
  static uint64_t ChildProcessUniqueIdToTracingProcessId(int child_process_id);

  // ChildProcessHost implementation
  bool Send(IPC::Message* message) override;
  void ForceShutdown() override;
  std::optional<mojo::OutgoingInvitation>& GetMojoInvitation() override;
  void CreateChannelMojo() override;
  bool IsChannelOpening() override;
#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC)
  void AddFilter(IPC::MessageFilter* filter) override;
#endif
  void BindReceiver(mojo::GenericPendingReceiver receiver) override;
  void SetBatterySaverMode(bool battery_saver_mode_enabled) override;

#if BUILDFLAG(IS_CHROMEOS_ASH)
  void ReinitializeLogging(uint32_t logging_dest,
                           base::ScopedFD log_file_descriptor) override;
#endif

  base::Process& GetPeerProcess();
  mojom::ChildProcess* child_process() { return child_process_.get(); }

#if BUILDFLAG(IS_ANDROID)
  // Notifies the child process of memory pressure level.
  void NotifyMemoryPressureToChildProcess(
      base::MemoryPressureListener::MemoryPressureLevel level);
#endif

 private:
  friend class content::ChildProcessHost;

  ChildProcessHostImpl(ChildProcessHostDelegate* delegate, IpcMode ipc_mode);

  // mojom::ChildProcessHost implementation:
  void Ping(PingCallback callback) override;
  void BindHostReceiver(mojo::GenericPendingReceiver receiver) override;

  // IPC::Listener methods:
  bool OnMessageReceived(const IPC::Message& msg) override;
  void OnChannelConnected(int32_t peer_pid) override;
  void OnChannelError() override;
  void OnBadMessageReceived(const IPC::Message& message) override;

  // Initializes the IPC channel and returns true on success. |channel_| must be
  // non-null.
  bool InitChannel();

  void OnDisconnectedFromChildProcess();

#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
  void DumpProfilingData(base::OnceClosure callback) override;
  void SetProfilingFile(base::File file) override;
#endif

  // The outgoing Mojo invitation which must be consumed to bootstrap Mojo IPC
  // to the child process.
  std::optional<mojo::OutgoingInvitation> mojo_invitation_{std::in_place};

  const IpcMode ipc_mode_;
  raw_ptr<ChildProcessHostDelegate> delegate_;
  base::Process peer_process_;
  bool opening_channel_;  // True while we're waiting the channel to be opened.
  std::unique_ptr<IPC::Channel> channel_;
  mojo::Remote<mojom::ChildProcess> child_process_;
  mojo::Receiver<mojom::ChildProcessHost> receiver_{this};

#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC)
  // Holds all the IPC message filters.  Since this object lives on the IO
  // thread, we don't have a IPC::ChannelProxy and so we manage filters
  // manually.
  std::vector<scoped_refptr<IPC::MessageFilter>> filters_;
#endif
};

}  // namespace content

#endif  // CONTENT_BROWSER_CHILD_PROCESS_HOST_IMPL_H_