// 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 #include #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( 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() = 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 process_type_; }; } // namespace base #endif // BASE_PROCESS_CURRENT_PROCESS_H_