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

#ifndef BASE_PROCESS_CURRENT_PROCESS_H_
#define BASE_PROCESS_CURRENT_PROCESS_H_

#include <atomic>
#include <string>

#include "base/base_export.h"
#include "base/no_destructor.h"
#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/base_tracing.h"
#include "build/buildflag.h"

namespace tracing {
class TraceEventDataSource;
class CustomEventRecorder;
void SetProcessTrackDescriptor(int64_t process_start_timestamp);
}  // namespace tracing

namespace mojo::core {
class Channel;
}

namespace base {
namespace test {
class CurrentProcessForTest;
}  // namespace test

using CurrentProcessType =
    perfetto::protos::pbzero::ChromeProcessDescriptor::ProcessType;

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// Use coalesced service process for recording histograms.
enum class ShortProcessType {
  kUnspecified = 0,
  kBrowser = 1,
  kRenderer = 2,
  kUtility = 3,
  kZygote = 4,
  kSandboxHelper = 5,
  kGpu = 6,
  kPpapiPlugin = 7,
  kPpapiBroker = 8,
  kServiceNetwork = 9,
  kServiceStorage = 10,
  kService = 11,
  kRendererExtension = 12,
  kMaxValue = kRendererExtension,
};

// CurrentProcess class provides access to set of current process properties
// which are accessible only from the process itself (e.g. ProcessType,
// ProcessName).
// See base::CurrentThread for access to properties of the running
// thread and base::Process::Current for the properties which are known both
// from within and without the process (e.g. pid).
class BASE_EXPORT CurrentProcess {
 public:
  static CurrentProcess& GetInstance();

  CurrentProcess(const CurrentProcess&) = delete;
  CurrentProcess& operator=(const CurrentProcess&) = delete;
  ~CurrentProcess();

  bool operator==(const CurrentProcess& other) const;

  class TypeKey {
   private:
    TypeKey() = default;
    friend class ::base::test::CurrentProcessForTest;
    friend class ::tracing::TraceEventDataSource;
    friend class ::tracing::CustomEventRecorder;
    friend void ::tracing::SetProcessTrackDescriptor(
        int64_t process_start_timestamp);
    friend class ::mojo::core::Channel;
  };
  // Returns an enum corresponding to the type of the current process (e.g.
  // browser / renderer / utility / etc). It can be used in metrics or tracing
  // code — for example, to split a number of low-level events with
  // process-type-agnostic implementation (e.g. number of posted tasks) by
  // process type for diagnostic purposes.
  // To avoid layering violations (i.e. //base or other low-level code modifying
  // its behaviour based on the //chrome or //content-level concepts like a
  // "browser" or "renderer" process), the access to this function is controlled
  // by an explicit list.
  CurrentProcessType GetType(TypeKey key) {
    return static_cast<CurrentProcessType>(
        process_type_.load(std::memory_order_relaxed));
  }

  ShortProcessType GetShortType(TypeKey key);

  class NameKey {
   private:
    NameKey() = default;
    friend class ::base::test::CurrentProcessForTest;
    friend class ::tracing::TraceEventDataSource;
    friend void ::tracing::SetProcessTrackDescriptor(
        int64_t process_start_timestamp);
  };
  std::string GetName(NameKey key) {
    AutoLock lock(lock_);
    return process_name_;
  }

  // Sets the name and type of the process for the metrics and tracing. This
  // function should be called as early as possible in the process's lifetime
  // before starting any threads, typically in *Main() function. Provide
  // process_name as an argument if it can't be trivially derived from the
  // process type.
  void SetProcessType(CurrentProcessType process_type);
  void SetProcessNameAndType(const std::string& process_name,
                             CurrentProcessType process_type);

  bool IsProcessNameEmpty() const {
    AutoLock lock(lock_);
    return process_name_.empty();
  }

 private:
  friend class base::NoDestructor<CurrentProcess>;

  CurrentProcess() = default;

  mutable Lock lock_;
  std::string process_name_;
  // The process_type_ is set at the startup before processes start running.
  // However, since it runs in multi-threaded environment and if has to be
  // changed later, we would want well-defined behaviour even if one thread
  // writes while another reads. There are some processes (e.g. Service process)
  // where we don't have a guarantee that it will be called early enough in the
  // process's lifetime, thus we use std::atomic here.
  std::atomic<CurrentProcessType> process_type_;
};

}  // namespace base

#endif  // BASE_PROCESS_CURRENT_PROCESS_H_
