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
  142
  143

base / process / current_process.h [blame]

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