summaryrefslogtreecommitdiffstats
path: root/toolkit/components/processtools/ProcInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/processtools/ProcInfo.h')
-rw-r--r--toolkit/components/processtools/ProcInfo.h279
1 files changed, 279 insertions, 0 deletions
diff --git a/toolkit/components/processtools/ProcInfo.h b/toolkit/components/processtools/ProcInfo.h
new file mode 100644
index 0000000000..d7e557b42e
--- /dev/null
+++ b/toolkit/components/processtools/ProcInfo.h
@@ -0,0 +1,279 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __mozilla_ProcInfo_h
+#define __mozilla_ProcInfo_h
+
+#include <base/process.h>
+#include <stdint.h>
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/ChromeUtilsBinding.h"
+#include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/HashTable.h"
+#include "mozilla/MozPromise.h"
+
+namespace mozilla {
+
+namespace ipc {
+class GeckoChildProcessHost;
+}
+
+/**
+ * Return the number of milliseconds of CPU time used since process start.
+ *
+ * @return NS_OK on success.
+ */
+nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult);
+
+/**
+ * Return the number of milliseconds of GPU time used since process start.
+ *
+ * @return NS_OK on success.
+ */
+nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
+
+// Process types. When updating this enum, please make sure to update
+// WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
+// mirror the changes.
+enum class ProcType {
+ // These must match the ones in RemoteType.h, and E10SUtils.sys.mjs
+ Web,
+ WebIsolated,
+ File,
+ Extension,
+ PrivilegedAbout,
+ PrivilegedMozilla,
+ WebCOOPCOEP,
+ WebServiceWorker,
+// the rest matches GeckoProcessTypes.h
+#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
+ process_bin_type, procinfo_typename, \
+ webidl_typename, allcaps_name) \
+ procinfo_typename,
+#define SKIP_PROCESS_TYPE_CONTENT
+#ifndef MOZ_ENABLE_FORKSERVER
+# define SKIP_PROCESS_TYPE_FORKSERVER
+#endif // MOZ_ENABLE_FORKSERVER
+#include "mozilla/GeckoProcessTypes.h"
+#undef SKIP_PROCESS_TYPE_CONTENT
+#ifndef MOZ_ENABLE_FORKSERVER
+# undef SKIP_PROCESS_TYPE_FORKSERVER
+#endif // MOZ_ENABLE_FORKSERVER
+#undef GECKO_PROCESS_TYPE
+ Preallocated,
+ // Unknown type of process
+ Unknown,
+ Max = Unknown,
+};
+
+using UtilityActorName = mozilla::dom::WebIDLUtilityActorName;
+
+// String that will be used e.g. to annotate crash reports
+nsCString GetUtilityActorName(const UtilityActorName aActorName);
+
+#ifdef XP_WIN
+int GetCpuFrequencyMHz();
+#endif
+
+/* Get the CPU frequency to use to convert cycle time values to actual time.
+ * @returns the TSC (Time Stamp Counter) frequency in MHz, or 0 if converting
+ * cycle time values should not be attempted. */
+int GetCycleTimeFrequencyMHz();
+
+struct ThreadInfo {
+ // Thread Id.
+ base::ProcessId tid = 0;
+ // Thread name, if any.
+ nsString name;
+ // CPU time in ns.
+ uint64_t cpuTime = 0;
+ // CPU time in cycles if available.
+ uint64_t cpuCycleCount = 0;
+};
+
+// Info on a DOM window.
+struct WindowInfo {
+ explicit WindowInfo()
+ : outerWindowId(0),
+ documentURI(nullptr),
+ documentTitle(u""_ns),
+ isProcessRoot(false),
+ isInProcess(false) {}
+ WindowInfo(uint64_t aOuterWindowId, nsIURI* aDocumentURI,
+ nsAString&& aDocumentTitle, bool aIsProcessRoot, bool aIsInProcess)
+ : outerWindowId(aOuterWindowId),
+ documentURI(aDocumentURI),
+ documentTitle(std::move(aDocumentTitle)),
+ isProcessRoot(aIsProcessRoot),
+ isInProcess(aIsInProcess) {}
+
+ // Internal window id.
+ const uint64_t outerWindowId;
+
+ // URI of the document.
+ const nsCOMPtr<nsIURI> documentURI;
+
+ // Title of the document.
+ const nsString documentTitle;
+
+ // True if this is the toplevel window of the process.
+ // Note that this may be an iframe from another process.
+ const bool isProcessRoot;
+
+ const bool isInProcess;
+};
+
+// Info on a Utility process actor
+struct UtilityInfo {
+ explicit UtilityInfo() : actorName(UtilityActorName::Unknown) {}
+ explicit UtilityInfo(UtilityActorName aActorName) : actorName(aActorName) {}
+ const UtilityActorName actorName;
+};
+
+struct ProcInfo {
+ // Process Id
+ base::ProcessId pid = 0;
+ // Child Id as defined by Firefox when a child process is created.
+ dom::ContentParentId childId;
+ // Process type
+ ProcType type;
+ // Origin, if any
+ nsCString origin;
+ // Memory size in bytes.
+ uint64_t memory = 0;
+ // CPU time in ns.
+ uint64_t cpuTime = 0;
+ uint64_t cpuCycleCount = 0;
+ // Threads owned by this process.
+ CopyableTArray<ThreadInfo> threads;
+ // DOM windows represented by this process.
+ CopyableTArray<WindowInfo> windows;
+ // Utility process actors, empty for non Utility process
+ CopyableTArray<UtilityInfo> utilityActors;
+};
+
+typedef MozPromise<mozilla::HashMap<base::ProcessId, ProcInfo>, nsresult, true>
+ ProcInfoPromise;
+
+/**
+ * Data we need to request process info (e.g. CPU usage, memory usage)
+ * from the operating system and populate the resulting `ProcInfo`.
+ *
+ * Note that this structure contains a mix of:
+ * - low-level handles that we need to request low-level process info
+ * (`aChildTask` on macOS, `aPid` on other platforms); and
+ * - high-level data that we already acquired while looking for
+ * `aPid`/`aChildTask` and that we will need further down the road.
+ */
+struct ProcInfoRequest {
+ ProcInfoRequest(base::ProcessId aPid, ProcType aProcessType,
+ const nsACString& aOrigin, nsTArray<WindowInfo>&& aWindowInfo,
+ nsTArray<UtilityInfo>&& aUtilityInfo, uint32_t aChildId = 0
+#ifdef XP_MACOSX
+ ,
+ mach_port_t aChildTask = 0
+#endif // XP_MACOSX
+ )
+ : pid(aPid),
+ processType(aProcessType),
+ origin(aOrigin),
+ windowInfo(std::move(aWindowInfo)),
+ utilityInfo(std::move(aUtilityInfo)),
+ childId(aChildId)
+#ifdef XP_MACOSX
+ ,
+ childTask(aChildTask)
+#endif // XP_MACOSX
+ {
+ }
+ const base::ProcessId pid;
+ const ProcType processType;
+ const nsCString origin;
+ const nsTArray<WindowInfo> windowInfo;
+ const nsTArray<UtilityInfo> utilityInfo;
+ // If the process is a child, its child id, otherwise `0`.
+ const int32_t childId;
+#ifdef XP_MACOSX
+ const mach_port_t childTask;
+#endif // XP_MACOSX
+};
+
+/**
+ * Batch a request for low-level information on Gecko processes.
+ *
+ * # Request
+ *
+ * Argument `aRequests` is a list of processes, along with high-level data
+ * we have already obtained on them and that we need to populate the
+ * resulting array of `ProcInfo`.
+ *
+ * # Result
+ *
+ * This call succeeds (possibly with missing data, see below) unless we
+ * cannot allocate memory.
+ *
+ * # Performance
+ *
+ * - This call is always executed on a background thread.
+ * - This call does NOT wake up children processes.
+ * - This function is sometimes observably slow to resolve, in particular
+ * under Windows.
+ *
+ * # Error-handling and race conditions
+ *
+ * Requesting low-level information on a process and its threads is inherently
+ * subject to race conditions. Typically, if a process or a thread is killed
+ * while we're preparing to fetch information, we can easily end up with
+ * system/lib calls that return failures.
+ *
+ * For this reason, this API assumes that errors when placing a system/lib call
+ * are likely and normal. When some information cannot be obtained, the API will
+ * simply skip over said information.
+ *
+ * Note that due to different choices by OSes, the exact information we skip may
+ * vary across platforms. For instance, under Unix, failing to access the
+ * threads of a process will cause us to skip all data on the process, while
+ * under Windows, process information will be returned without thread
+ * information.
+ */
+RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests);
+
+/**
+ * Synchronous version of GetProcInfo.
+ */
+ProcInfoPromise::ResolveOrRejectValue GetProcInfoSync(
+ nsTArray<ProcInfoRequest>&& aRequests);
+
+/**
+ * Utility function: copy data from a `ProcInfo` and into either a
+ * `ParentProcInfoDictionary` or a `ChildProcInfoDictionary`.
+ */
+template <typename T>
+nsresult CopySysProcInfoToDOM(const ProcInfo& source, T* dest) {
+ // Copy system info.
+ dest->mPid = source.pid;
+ dest->mMemory = source.memory;
+ dest->mCpuTime = source.cpuTime;
+ dest->mCpuCycleCount = source.cpuCycleCount;
+
+ // Copy thread info.
+ mozilla::dom::Sequence<mozilla::dom::ThreadInfoDictionary> threads;
+ for (const ThreadInfo& entry : source.threads) {
+ mozilla::dom::ThreadInfoDictionary* thread =
+ threads.AppendElement(fallible);
+ if (NS_WARN_IF(!thread)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ thread->mCpuTime = entry.cpuTime;
+ thread->mCpuCycleCount = entry.cpuCycleCount;
+ thread->mTid = entry.tid;
+ thread->mName.Assign(entry.name);
+ }
+ dest->mThreads = std::move(threads);
+ return NS_OK;
+}
+
+} // namespace mozilla
+#endif // ProcInfo_h