// 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.

#include "content/browser/child_process_host_impl.h"

#include <limits>
#include <tuple>

#include "base/atomic_sequence_num.h"
#include "base/clang_profiling_buildflags.h"
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/hash/hash.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/path_service.h"
#include "base/process/process_metrics.h"
#include "base/rand_util.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/common/content_constants_internal.h"
#include "content/common/pseudonymization_salt.h"
#include "content/public/browser/child_process_host_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_logging.h"
#include "ipc/message_filter.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "base/linux_util.h"
#elif BUILDFLAG(IS_MAC)
#include "base/mac/foundation_util.h"
#include "content/browser/mac_helpers.h"
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

namespace {

// Global atomic to generate child process unique IDs.
base::AtomicSequenceNumber g_unique_id;

}  // namespace

namespace content {

ChildProcessHost::~ChildProcessHost() = default;

// static
std::unique_ptr<ChildProcessHost> ChildProcessHost::Create(
    ChildProcessHostDelegate* delegate,
    IpcMode ipc_mode) {
  return base::WrapUnique(new ChildProcessHostImpl(delegate, ipc_mode));
}

// static
base::FilePath ChildProcessHost::GetChildPath(int flags) {
  base::FilePath child_path;

  child_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
      switches::kBrowserSubprocessPath);

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  // Use /proc/self/exe rather than our known binary path so updates
  // can't swap out the binary from underneath us.
  if (child_path.empty() && flags & CHILD_ALLOW_SELF) {
    child_path = base::FilePath(base::kProcSelfExe);
  }
#endif

  // On most platforms, the child executable is the same as the current
  // executable.
  if (child_path.empty()) {
    base::PathService::Get(CHILD_PROCESS_EXE, &child_path);
  }

#if BUILDFLAG(IS_MAC)
  std::string child_base_name = child_path.BaseName().value();

  if (flags != CHILD_NORMAL && base::mac::AmIBundled()) {
    // This is a specialized helper, with the |child_path| at
    // ../Framework.framework/Versions/X/Helpers/Chromium Helper.app/Contents/
    // MacOS/Chromium Helper. Go back up to the "Helpers" directory to select
    // a different variant.
    child_path = child_path.DirName().DirName().DirName().DirName();

    if (flags == CHILD_RENDERER) {
      child_base_name += kMacHelperSuffix_renderer;
    } else if (flags == CHILD_GPU) {
      child_base_name += kMacHelperSuffix_gpu;
    } else if (flags == CHILD_PLUGIN) {
      child_base_name += kMacHelperSuffix_plugin;
    } else if (flags > CHILD_EMBEDDER_FIRST) {
      child_base_name +=
          GetContentClient()->browser()->GetChildProcessSuffix(flags);
    } else {
      NOTREACHED();
    }

    child_path = child_path.Append(child_base_name + ".app")
                     .Append("Contents")
                     .Append("MacOS")
                     .Append(child_base_name);
  }
#endif  // BUILDFLAG(IS_MAC)

  return child_path;
}

ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate,
                                           IpcMode ipc_mode)
    : ipc_mode_(ipc_mode), delegate_(delegate), opening_channel_(false) {
  if (ipc_mode_ == IpcMode::kLegacy) {
    // In legacy mode, we only have an IPC Channel. Bind ChildProcess to a
    // disconnected pipe so it quietly discards messages.
    std::ignore = child_process_.BindNewPipeAndPassReceiver();
    channel_ = IPC::ChannelMojo::Create(
        mojo_invitation_->AttachMessagePipe(
            kChildProcessReceiverAttachmentName),
        IPC::Channel::MODE_SERVER, this,
        base::SingleThreadTaskRunner::GetCurrentDefault(),
        base::SingleThreadTaskRunner::GetCurrentDefault());
  } else if (ipc_mode_ == IpcMode::kNormal) {
    child_process_.Bind(mojo::PendingRemote<mojom::ChildProcess>(
        mojo_invitation_->AttachMessagePipe(
            kChildProcessReceiverAttachmentName),
        /*version=*/0));
    receiver_.Bind(mojo::PendingReceiver<mojom::ChildProcessHost>(
        mojo_invitation_->AttachMessagePipe(
            kChildProcessHostRemoteAttachmentName)));
    receiver_.set_disconnect_handler(
        base::BindOnce(&ChildProcessHostImpl::OnDisconnectedFromChildProcess,
                       base::Unretained(this)));
  }
}

ChildProcessHostImpl::~ChildProcessHostImpl() {
  // If a channel was never created than it wasn't registered and the filters
  // weren't notified. For the sake of symmetry don't call the matching teardown
  // functions. This is analogous to how RenderProcessHostImpl handles things.
  if (!channel_) {
    return;
  }

  for (auto& filter : filters_) {
    filter->OnChannelClosing();
    filter->OnFilterRemoved();
  }
}

void ChildProcessHostImpl::AddFilter(IPC::MessageFilter* filter) {
  filters_.push_back(filter);

  if (channel_) {
    filter->OnFilterAdded(channel_.get());
  }
}

void ChildProcessHostImpl::BindReceiver(mojo::GenericPendingReceiver receiver) {
  child_process_->BindReceiver(std::move(receiver));
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
void ChildProcessHostImpl::ReinitializeLogging(
    uint32_t logging_dest,
    base::ScopedFD log_file_descriptor) {
  auto logging_settings = mojom::LoggingSettings::New();
  logging_settings->logging_dest = logging_dest;
  logging_settings->log_file_descriptor =
      mojo::PlatformHandle(std::move(log_file_descriptor));
  child_process()->ReinitializeLogging(std::move(logging_settings));
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

base::Process& ChildProcessHostImpl::GetPeerProcess() {
  if (!peer_process_.IsValid()) {
    const base::Process& process = delegate_->GetProcess();
    if (process.IsValid()) {
      peer_process_ = base::Process::OpenWithExtraPrivileges(process.Pid());
      if (!peer_process_.IsValid()) {
        peer_process_ = process.Duplicate();
      }
      DCHECK(peer_process_.IsValid());
    }
  }

  return peer_process_;
}

// TODO(crbug.com/1328879): Remove this method when fixing the bug.
#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
void ChildProcessHostImpl::RunServiceDeprecated(
    const std::string& service_name,
    mojo::ScopedMessagePipeHandle service_pipe) {
  child_process_->RunServiceDeprecated(service_name, std::move(service_pipe));
}
#endif

void ChildProcessHostImpl::ForceShutdown() {
  child_process_->ProcessShutdown();
}

absl::optional<mojo::OutgoingInvitation>&
ChildProcessHostImpl::GetMojoInvitation() {
  return mojo_invitation_;
}

void ChildProcessHostImpl::CreateChannelMojo() {
  // If in legacy mode, |channel_| is already initialized by the constructor
  // not bound through the ChildProcess API.
  if (ipc_mode_ != IpcMode::kLegacy) {
    DCHECK(!channel_);
    DCHECK_EQ(ipc_mode_, IpcMode::kNormal);
    DCHECK(child_process_);

    mojo::ScopedMessagePipeHandle bootstrap =
        mojo_invitation_->AttachMessagePipe(kLegacyIpcBootstrapAttachmentName);
    channel_ = IPC::ChannelMojo::Create(
        std::move(bootstrap), IPC::Channel::MODE_SERVER, this,
        base::SingleThreadTaskRunner::GetCurrentDefault(),
        base::SingleThreadTaskRunner::GetCurrentDefault());
  }
  DCHECK(channel_);

  // Since we're initializing a legacy IPC Channel, we will use its connection
  // status to monitor child process lifetime instead of using the status of the
  // `receiver_` endpoint.
  if (receiver_.is_bound()) {
    receiver_.set_disconnect_handler(base::NullCallback());
  }

  bool initialized = InitChannel();
  DCHECK(initialized);
}

bool ChildProcessHostImpl::InitChannel() {
  if (!channel_->Connect()) {
    return false;
  }

  for (auto& filter : filters_) {
    filter->OnFilterAdded(channel_.get());
  }

  delegate_->OnChannelInitialized(channel_.get());

  // Make sure these messages get sent first.
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
  bool enabled = IPC::Logging::GetInstance()->Enabled();
  child_process_->SetIPCLoggingEnabled(enabled);
#endif

  opening_channel_ = true;

  return true;
}

void ChildProcessHostImpl::OnDisconnectedFromChildProcess() {
  if (channel_) {
    opening_channel_ = false;
    delegate_->OnChannelError();
    for (auto& filter : filters_) {
      filter->OnChannelError();
    }
  }

  // This will delete host_, which will also destroy this!
  delegate_->OnChildDisconnected();
}

bool ChildProcessHostImpl::IsChannelOpening() {
  return opening_channel_;
}

bool ChildProcessHostImpl::Send(IPC::Message* message) {
  if (!channel_) {
    delete message;
    return false;
  }
  return channel_->Send(message);
}

int ChildProcessHostImpl::GenerateChildProcessUniqueId() {
  // This function must be threadsafe.
  //
  // Historically, this function returned ids started with 1, so in several
  // places in the code a value of 0 (rather than kInvalidUniqueID) was used as
  // an invalid value. So we retain those semantics.
  int id = g_unique_id.GetNext() + 1;

  CHECK_NE(0, id);
  CHECK_NE(kInvalidUniqueID, id);

  return id;
}

uint64_t ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
    int child_process_id) {
  // In single process mode, all the children are hosted in the same process,
  // therefore the generated memory dump guids should not be conditioned by the
  // child process id. The clients need not be aware of SPM and the conversion
  // takes care of the SPM special case while translating child process ids to
  // tracing process ids.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kSingleProcess)) {
    return memory_instrumentation::mojom::kServiceTracingProcessId;
  }

  // The hash value is incremented so that the tracing id is never equal to
  // MemoryDumpManager::kInvalidTracingProcessId.
  return static_cast<uint64_t>(base::PersistentHash(
             base::as_bytes(base::make_span(&child_process_id, 1u)))) +
         1;
}

void ChildProcessHostImpl::Ping(PingCallback callback) {
  std::move(callback).Run();
}

void ChildProcessHostImpl::BindHostReceiver(
    mojo::GenericPendingReceiver receiver) {
  delegate_->BindHostReceiver(std::move(receiver));
}

bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
  IPC::Logging* logger = IPC::Logging::GetInstance();
  if (msg.type() == IPC_LOGGING_ID) {
    logger->OnReceivedLoggingMessage(msg);
    return true;
  }

  if (logger->Enabled()) {
    logger->OnPreDispatchMessage(msg);
  }
#endif

  bool handled = false;
  for (auto& filter : filters_) {
    if (filter->OnMessageReceived(msg)) {
      handled = true;
      break;
    }
  }

  if (!handled) {
    handled = delegate_->OnMessageReceived(msg);
  }

#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
  if (logger->Enabled()) {
    logger->OnPostDispatchMessage(msg);
  }
#endif
  return handled;
}

void ChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
  // Propagate the pseudonymization salt to all the child processes.
  //
  // TODO(dullweber, lukasza): Figure out if it is possible to reset the salt
  // at a regular interval (on the order of hours?).  The browser would need
  // to be responsible for 1) deciding when the refresh happens and 2) pushing
  // the updated salt to all the child processes.
  child_process_->SetPseudonymizationSalt(GetPseudonymizationSalt());

  // We ignore the `peer_pid` argument, which ultimately comes over IPC from the
  // remote process, in favor of the PID already known by the browser after
  // launching the process. This is partly because IPC Channel is being phased
  // out and some process types no longer use it, but also because there's
  // really no need to get this information from the child process when we
  // already have it.
  //
  // TODO(crbug.com/616980): Remove the peer_pid argument altogether from
  // IPC::Listener::OnChannelConnected.
  const base::Process& peer_process = GetPeerProcess();
  base::ProcessId pid =
      peer_process.IsValid() ? peer_process.Pid() : base::GetCurrentProcId();
  opening_channel_ = false;
  delegate_->OnChannelConnected(pid);
  for (auto& filter : filters_) {
    filter->OnChannelConnected(pid);
  }
}

void ChildProcessHostImpl::OnChannelError() {
  OnDisconnectedFromChildProcess();
}

void ChildProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) {
  delegate_->OnBadMessageReceived(message);
}

#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
void ChildProcessHostImpl::DumpProfilingData(base::OnceClosure callback) {
  child_process_->WriteClangProfilingProfile(std::move(callback));
}

void ChildProcessHostImpl::SetProfilingFile(base::File file) {
  child_process_->SetProfilingFile(std::move(file));
}
#endif

#if BUILDFLAG(IS_ANDROID)
// Notifies the child process of memory pressure level.
void ChildProcessHostImpl::NotifyMemoryPressureToChildProcess(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  child_process()->OnMemoryPressure(level);
}
#endif

}  // namespace content
