// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/process/process.h"

#include <lib/zx/process.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#include "base/clang_profiling_buildflags.h"
#include "base/fuchsia/default_job.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/base_tracing.h"

#if BUILDFLAG(CLANG_PROFILING)
#include "base/test/clang_profiling.h"
#endif

namespace base {

namespace {

zx::process FindProcessInJobTree(const zx::job& job, ProcessId pid) {
  zx::process process;
  zx_status_t status = job.get_child(pid, ZX_RIGHT_SAME_RIGHTS, &process);

  if (status == ZX_OK)
    return process;

  if (status == ZX_ERR_NOT_FOUND) {
    std::vector<zx_koid_t> job_koids(32);
    while (true) {
      // Fetch the KOIDs of the job children of |job|.
      size_t actual = 0u;
      size_t available = 0u;
      status = job.get_info(ZX_INFO_JOB_CHILDREN, job_koids.data(),
                            job_koids.size() * sizeof(zx_koid_t), &actual,
                            &available);

      if (status != ZX_OK) {
        ZX_DLOG(ERROR, status) << "zx_object_get_info(JOB_CHILDREN)";
        return zx::process();
      }

      // If |job_koids| was too small then resize it and try again.
      if (available > actual) {
        job_koids.resize(available);
        continue;
      }

      // Break out of the loop and iterate over |job_koids|, to find the PID.
      job_koids.resize(actual);
      break;
    }

    for (zx_koid_t job_koid : job_koids) {
      zx::job child_job;
      if (job.get_child(job_koid, ZX_RIGHT_SAME_RIGHTS, &child_job) != ZX_OK)
        continue;
      process = FindProcessInJobTree(child_job, pid);
      if (process)
        return process;
    }

    return zx::process();
  }

  ZX_DLOG(ERROR, status) << "zx_object_get_child";
  return zx::process();
}

}  // namespace

Process::Process(ProcessHandle handle)
    : process_(handle), is_current_process_(false) {
  CHECK_NE(handle, zx_process_self());
}

Process::~Process() {
  Close();
}

Process::Process(Process&& other)
    : process_(std::move(other.process_)),
      is_current_process_(other.is_current_process_) {
  other.is_current_process_ = false;
}

Process& Process::operator=(Process&& other) {
  process_ = std::move(other.process_);
  is_current_process_ = other.is_current_process_;
  other.is_current_process_ = false;
  return *this;
}

// static
Process Process::Current() {
  Process process;
  process.is_current_process_ = true;
  return process;
}

// static
Process Process::Open(ProcessId pid) {
  if (pid == GetCurrentProcId())
    return Current();

  return Process(FindProcessInJobTree(*GetDefaultJob(), pid).release());
}

// static
Process Process::OpenWithExtraPrivileges(ProcessId pid) {
  // No privileges to set.
  return Open(pid);
}

// static
bool Process::CanBackgroundProcesses() {
  return false;
}

// static
void Process::TerminateCurrentProcessImmediately(int exit_code) {
#if BUILDFLAG(CLANG_PROFILING)
  WriteClangProfilingProfile();
#endif
  _exit(exit_code);
}

bool Process::IsValid() const {
  return process_.is_valid() || is_current();
}

ProcessHandle Process::Handle() const {
  return is_current_process_ ? zx_process_self() : process_.get();
}

Process Process::Duplicate() const {
  if (is_current())
    return Current();

  if (!IsValid())
    return Process();

  zx::process out;
  zx_status_t result = process_.duplicate(ZX_RIGHT_SAME_RIGHTS, &out);
  if (result != ZX_OK) {
    ZX_DLOG(ERROR, result) << "zx_handle_duplicate";
    return Process();
  }

  return Process(out.release());
}

ProcessHandle Process::Release() {
  if (is_current()) {
    // Caller expects to own the reference, so duplicate the self handle.
    zx::process handle;
    zx_status_t result =
        zx::process::self()->duplicate(ZX_RIGHT_SAME_RIGHTS, &handle);
    if (result != ZX_OK) {
      return kNullProcessHandle;
    }
    is_current_process_ = false;
    return handle.release();
  }
  return process_.release();
}

ProcessId Process::Pid() const {
  DCHECK(IsValid());
  return GetProcId(Handle());
}

Time Process::CreationTime() const {
  zx_info_process_t proc_info;
  zx_status_t status =
      zx_object_get_info(Handle(), ZX_INFO_PROCESS, &proc_info,
                         sizeof(proc_info), nullptr, nullptr);
  if (status != ZX_OK) {
    ZX_DLOG(ERROR, status) << "zx_process_get_info";
    return Time();
  }
  if ((proc_info.flags & ZX_INFO_PROCESS_FLAG_STARTED) == 0) {
    DLOG(WARNING) << "zx_process_get_info: Not started.";
    return Time();
  }
  // Process creation times are expressed in ticks since system boot, so
  // perform a best-effort translation from that to UTC "wall-clock" time.
  return Time::Now() +
         (TimeTicks::FromZxTime(proc_info.start_time) - TimeTicks::Now());
}

bool Process::is_current() const {
  return is_current_process_;
}

void Process::Close() {
  is_current_process_ = false;
  process_.reset();
}

bool Process::Terminate(int exit_code, bool wait) const {
  // exit_code isn't supportable. https://crbug.com/753490.
  zx_status_t status = zx_task_kill(Handle());
  if (status == ZX_OK && wait) {
    zx_signals_t signals;
    status = zx_object_wait_one(Handle(), ZX_TASK_TERMINATED,
                                zx_deadline_after(ZX_SEC(60)), &signals);
    if (status != ZX_OK) {
      ZX_DLOG(ERROR, status) << "zx_object_wait_one(terminate)";
    } else {
      CHECK(signals & ZX_TASK_TERMINATED);
    }
  } else if (status != ZX_OK) {
    ZX_DLOG(ERROR, status) << "zx_task_kill";
  }

  return status >= 0;
}

bool Process::WaitForExit(int* exit_code) const {
  return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
}

bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
  if (is_current_process_)
    return false;

  TRACE_EVENT0("base", "Process::WaitForExitWithTimeout");

  if (!timeout.is_zero()) {
    // Assert that this thread is allowed to wait below. This intentionally
    // doesn't use ScopedBlockingCallWithBaseSyncPrimitives because the process
    // being waited upon tends to itself be using the CPU and considering this
    // thread non-busy causes more issue than it fixes: http://crbug.com/905788
    internal::AssertBaseSyncPrimitivesAllowed();
  }

  zx::time deadline = timeout == TimeDelta::Max()
                          ? zx::time::infinite()
                          : zx::time((TimeTicks::Now() + timeout).ToZxTime());
  zx_signals_t signals_observed = 0;
  zx_status_t status =
      process_.wait_one(ZX_TASK_TERMINATED, deadline, &signals_observed);
  if (status != ZX_OK) {
    ZX_DLOG_IF(ERROR, status != ZX_ERR_TIMED_OUT, status)
        << "zx_object_wait_one";
    return false;
  }

  zx_info_process_t proc_info;
  status = process_.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info),
                             nullptr, nullptr);
  if (status != ZX_OK) {
    ZX_DLOG(ERROR, status) << "zx_object_get_info";
    if (exit_code)
      *exit_code = -1;
    return false;
  }

  if (exit_code)
    *exit_code = static_cast<int>(proc_info.return_code);

  return true;
}

void Process::Exited(int exit_code) const {}

bool Process::IsProcessBackgrounded() const {
  // See SetProcessBackgrounded().
  DCHECK(IsValid());
  return false;
}

bool Process::SetProcessBackgrounded(bool value) {
  // No process priorities on Fuchsia.
  // TODO(fxbug.dev/30735): Update this later if priorities are implemented.
  return false;
}

int Process::GetPriority() const {
  DCHECK(IsValid());
  // No process priorities on Fuchsia.
  return 0;
}

}  // namespace base
