Reland "[memory] Move process memory info to base"

This is a reland of commit 6a0ed21330f202eae185ea827ae19f51f0537d82

Reason for revert:
Speculatively reverting due to Linux MSan bot failures on
RenderFrameHostManagerTest.RenderViewInitAfterNewProxyAndProcessKill

Fix 1: initialize ProcessMemoryInfo fields on linux.
Fix 2: use /proc/pid/statm as fallback for pre linux 4.5

Original change's description:
> [memory] Move process memory info to base
>
> This will be re-used in a follow-up in SystemMetricsSampler.
> This should also replaced copied code in blink::MemoryUsageMonitor.
>
> This changes Linux's FillOSMemoryDump from GetResidentAndSharedPagesFromStatmFile() (proc/pid/statm) to ReadProcFileToTrimmedStringPairs() (proc/pid/status)
>
> This drops supports for pre MAC_OS_X_VERSION_10_11 missing
> phys_footprint: https://issues.chromium.org/issues/40669926
>
> Change-Id: I2002e69abbe852e82d0d1cb37017e77602538d6b
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6039432
> Reviewed-by: Primiano Tucci <primiano@chromium.org>
> Reviewed-by: Gabriel Charette <gab@chromium.org>
> Owners-Override: Gabriel Charette <gab@chromium.org>
> Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1390345}

Change-Id: I8b98ca2ba24a0cabd9f49b5e1e85e54932dfbf32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6062359
Owners-Override: Gabriel Charette <gab@chromium.org>
Reviewed-by: Primiano Tucci <primiano@chromium.org>
Reviewed-by: Gabriel Charette <gab@chromium.org>
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1391983}
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h
index c5d994f..86b448af 100644
--- a/base/process/process_metrics.h
+++ b/base/process/process_metrics.h
@@ -64,7 +64,7 @@
 // Convert a POSIX timeval to microseconds.
 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
 
-enum class ProcessCPUUsageError {
+enum class ProcessUsageError {
   // The OS returned an error while measuring the CPU usage. The possible causes
   // vary by platform.
   kSystemError,
@@ -74,6 +74,32 @@
   kProcessNotFound,
 };
 
+using ProcessCPUUsageError = ProcessUsageError;
+
+struct ProcessMemoryInfo {
+  uint64_t resident_set_bytes = 0;
+
+#if BUILDFLAG(IS_APPLE)
+  uint64_t physical_footprint_bytes = 0;
+  uint64_t internal_bytes = 0;
+  uint64_t compressed_bytes = 0;
+#endif  // BUILDFLAG(IS_APPLE)
+
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
+    BUILDFLAG(IS_FUCHSIA)
+  uint64_t rss_anon_bytes = 0;
+  uint64_t vm_swap_bytes = 0;
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+        // BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(IS_WIN)
+  uint64_t private_bytes = 0;
+#endif  // BUILDFLAG(IS_WIN)
+
+  // On iOS,
+  //   TBD: https://crbug.com/714961
+};
+
 // Provides performance metrics for a specified process (CPU usage and IO
 // counters). Use CreateCurrentProcessMetrics() to get an instance for the
 // current process, or CreateProcessMetrics() to get an instance for an
@@ -113,11 +139,16 @@
   // convenience wrapper for CreateProcessMetrics().
   static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics();
 
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
-  // Resident Set Size is a Linux/Android specific memory concept. Do not
-  // attempt to extend this to other platforms.
-  BASE_EXPORT size_t GetResidentSetSize() const;
-#endif
+  // Provides synchronous access to memory metrics for a process. This interface
+  // has platform-specific restrictions:
+  //  * On Android, due to sandboxing restrictions, processes can only access
+  //    memory metrics for themselves.
+  //  * On Linux, due to sandboxing restrictions, only the privileged browser
+  //    process has access to memory metrics for sandboxed child processes.
+  //  * On Fuchsia, due to the API expecting a ProcessId rather than a
+  //    ProcessHandle, processes can only access memory metrics for themselves
+  //    or for children of base::GetDefaultJob().
+  base::expected<ProcessMemoryInfo, ProcessUsageError> GetMemoryInfo() const;
 
   // Returns the percentage of time spent executing, across all threads of the
   // process, in the interval since the last time the method was called, using
@@ -193,9 +224,6 @@
 #endif  // BUILDFLAG(IS_POSIX)
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
-  // Bytes of swap as reported by /proc/[pid]/status.
-  uint64_t GetVmSwapBytes() const;
-
   // Minor and major page fault count as reported by /proc/[pid]/stat.
   // Returns true for success.
   bool GetPageFaultCounts(PageFaultCounts* counts) const;
diff --git a/base/process/process_metrics_apple.cc b/base/process/process_metrics_apple.cc
index 12e772d..8bf40141 100644
--- a/base/process/process_metrics_apple.cc
+++ b/base/process/process_metrics_apple.cc
@@ -86,6 +86,34 @@
   return kr == KERN_SUCCESS;
 }
 
+// Don't simply use sizeof(task_vm_info) / sizeof(natural_t):
+// In the 10.15 SDK, this structure is 87 32-bit words long, and in
+// mach_types.defs:
+//
+//   type task_info_t    = array[*:87] of integer_t;
+//
+// However in the 10.14 SDK, this structure is 42 32-bit words, and in
+// mach_types.defs:
+//
+//   type task_info_t    = array[*:52] of integer_t;
+//
+// As a result, the 10.15 SDK's task_vm_info won't fit inside the 10.14 SDK's
+// task_info_t, so the *rest of the system* (on 10.14 and earlier) can't handle
+// calls that request the full 10.15 structure. We have to request a prefix of
+// it that 10.14 and earlier can handle by limiting the length we request. The
+// rest of the fields just get ignored, but we don't use them anyway.
+
+constexpr mach_msg_type_number_t ChromeTaskVMInfoCount =
+    TASK_VM_INFO_REV2_COUNT;
+
+// The count field is in units of natural_t, which is the machine's word size
+// (64 bits on all modern machines), but the task_info_t array is in units of
+// integer_t, which is 32 bits.
+constexpr mach_msg_type_number_t MAX_MIG_SIZE_FOR_1014 =
+    52 / (sizeof(natural_t) / sizeof(integer_t));
+static_assert(ChromeTaskVMInfoCount <= MAX_MIG_SIZE_FOR_1014,
+              "task_vm_info must be small enough for 10.14 MIG interfaces");
+
 }  // namespace
 
 // Implementations of ProcessMetrics class shared by Mac and iOS.
@@ -102,6 +130,28 @@
   return task;
 }
 
+base::expected<ProcessMemoryInfo, ProcessUsageError>
+ProcessMetrics::GetMemoryInfo() const {
+  mach_port_t task = TaskForHandle(process_);
+  if (task == MACH_PORT_NULL) {
+    return base::unexpected(ProcessUsageError::kProcessNotFound);
+  }
+  task_vm_info info;
+  mach_msg_type_number_t count = ChromeTaskVMInfoCount;
+  kern_return_t result = task_info(
+      task, TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &count);
+  if (result != KERN_SUCCESS) {
+    return base::unexpected(ProcessUsageError::kSystemError);
+  }
+
+  ProcessMemoryInfo memory_info;
+  memory_info.internal_bytes = info.internal;
+  memory_info.compressed_bytes = info.compressed;
+  memory_info.resident_set_bytes = info.resident_size;
+  memory_info.physical_footprint_bytes = info.phys_footprint;
+  return memory_info;
+}
+
 base::expected<TimeDelta, ProcessCPUUsageError>
 ProcessMetrics::GetCumulativeCPUUsage() {
   mach_port_t task = TaskForHandle(process_);
diff --git a/base/process/process_metrics_fuchsia.cc b/base/process/process_metrics_fuchsia.cc
index b1f94c4..f67b66b5 100644
--- a/base/process/process_metrics_fuchsia.cc
+++ b/base/process/process_metrics_fuchsia.cc
@@ -48,6 +48,24 @@
   return base::ok(TimeDelta::FromZxDuration(stats.cpu_time));
 }
 
+base::expected<ProcessMemoryInfo, ProcessUsageError>
+ProcessMetrics::GetMemoryInfo() const {
+  zx_info_task_stats_t info;
+  zx_status_t status = zx::unowned_process(process_)->get_info(
+      ZX_INFO_TASK_STATS, &info, sizeof(info), nullptr, nullptr);
+  if (status != ZX_OK) {
+    return base::unexpected(ProcessUsageError::kSystemError);
+  }
+
+  ProcessMemoryInfo memory_info;
+  memory_info.resident_set_bytes =
+      info.mem_private_bytes + info.mem_shared_bytes;
+  memory_info.rss_anon_bytes = info.mem_private_bytes;
+  // Fuchsia has no swap.
+  memory_info.vm_swap_bytes = 0;
+  return memory_info;
+}
+
 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
   // TODO(crbug.com/42050627).
   return false;
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index b0abc364..5ef8c17 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -29,6 +29,7 @@
 #include "base/files/dir_reader_posix.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/memory/page_size.h"
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
 #include "base/numerics/clamped_math.h"
@@ -88,6 +89,15 @@
   return base::ok(cpu_time);
 }
 
+size_t GetKbFieldAsSizeT(std::string_view value_str) {
+  std::vector<std::string_view> split_value_str =
+      SplitStringPiece(value_str, " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+  CHECK(split_value_str.size() == 2 && split_value_str[1] == "kB");
+  size_t value;
+  CHECK(StringToSizeT(split_value_str[0], &value));
+  return value;
+}
+
 }  // namespace
 
 // static
@@ -96,11 +106,6 @@
   return WrapUnique(new ProcessMetrics(process));
 }
 
-size_t ProcessMetrics::GetResidentSetSize() const {
-  return internal::ReadProcStatsAndGetFieldAsSizeT(process_, internal::VM_RSS) *
-         checked_cast<size_t>(getpagesize());
-}
-
 base::expected<TimeDelta, ProcessCPUUsageError>
 ProcessMetrics::GetCumulativeCPUUsage() {
   std::string buffer;
@@ -140,9 +145,48 @@
 }
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
-uint64_t ProcessMetrics::GetVmSwapBytes() const {
-  return internal::ReadProcStatusAndGetKbFieldAsSizeT(process_, "VmSwap") *
-         1024;
+base::expected<ProcessMemoryInfo, ProcessUsageError>
+ProcessMetrics::GetMemoryInfo() const {
+  StringPairs pairs;
+  if (!internal::ReadProcFileToTrimmedStringPairs(process_, "status", &pairs)) {
+    return base::unexpected(ProcessUsageError::kSystemError);
+  }
+  ProcessMemoryInfo dump;
+  for (const auto& pair : pairs) {
+    const std::string& key = pair.first;
+    const std::string& value_str = pair.second;
+    if (key == "VmSwap") {
+      dump.vm_swap_bytes =
+          static_cast<uint64_t>(GetKbFieldAsSizeT(value_str)) * 1024;
+    } else if (key == "VmRSS") {
+      dump.resident_set_bytes =
+          static_cast<uint64_t>(GetKbFieldAsSizeT(value_str)) * 1024;
+    } else if (key == "RssAnon") {
+      dump.rss_anon_bytes =
+          static_cast<uint64_t>(GetKbFieldAsSizeT(value_str)) * 1024;
+    } else {
+      continue;
+    }
+  }
+  if (dump.rss_anon_bytes != 0) {
+    return dump;
+  }
+  // RssAnon was introduced in Linux 4.5, use /proc/pid/statm as fallback.
+  std::string statm_data;
+  FilePath statm_file = internal::GetProcPidDir(process_).Append("statm");
+  if (!internal::ReadProcFile(statm_file, &statm_data)) {
+    return base::unexpected(ProcessUsageError::kSystemError);
+  }
+  std::vector<std::string_view> values = SplitStringPieceUsingSubstr(
+      statm_data, " ", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+  CHECK_GE(values.size(), 3U);
+  uint64_t resident_pages = 0;
+  uint64_t shared_pages = 0;
+  CHECK(StringToUint64(values[1], &resident_pages));
+  CHECK(StringToUint64(values[2], &shared_pages));
+  static const size_t page_size = GetPageSize();
+  dump.rss_anon_bytes = (resident_pages - shared_pages) * page_size;
+  return dump;
 }
 
 bool ProcessMetrics::GetPageFaultCounts(PageFaultCounts* counts) const {
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index 2b636279..eb45247 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -736,6 +736,32 @@
 
 #endif  // ENABLE_CPU_TESTS
 
+TEST_F(SystemMetricsTest, TestValidMemoryInfo) {
+  std::unique_ptr<ProcessMetrics> metrics =
+      ProcessMetrics::CreateCurrentProcessMetrics();
+
+  auto memory_info = metrics->GetMemoryInfo();
+  EXPECT_TRUE(memory_info.has_value());
+  EXPECT_GT(memory_info->resident_set_bytes, 0U);
+
+#if BUILDFLAG(IS_APPLE)
+  EXPECT_GT(memory_info->physical_footprint_bytes, 0U);
+  EXPECT_GT(memory_info->internal_bytes, 0U);
+  EXPECT_GE(memory_info->compressed_bytes, 0U);
+#endif  // BUILDFLAG(IS_APPLE)
+
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
+    BUILDFLAG(IS_FUCHSIA)
+  EXPECT_GT(memory_info->rss_anon_bytes, 0U);
+  EXPECT_GE(memory_info->vm_swap_bytes, 0U);
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+        // BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(IS_WIN)
+  EXPECT_GT(memory_info->private_bytes, 0U);
+#endif  // BUILDFLAG(IS_WIN)
+}
+
 #if BUILDFLAG(IS_CHROMEOS)
 TEST_F(SystemMetricsTest, ParseZramMmStat) {
   SwapInfo swapinfo;
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc
index 8514c76c..40e30a6 100644
--- a/base/process/process_metrics_win.cc
+++ b/base/process/process_metrics_win.cc
@@ -160,6 +160,23 @@
   return WrapUnique(new ProcessMetrics(process));
 }
 
+base::expected<ProcessMemoryInfo, ProcessUsageError>
+ProcessMetrics::GetMemoryInfo() const {
+  if (!process_.is_valid()) {
+    return base::unexpected(ProcessUsageError::kProcessNotFound);
+  }
+  PROCESS_MEMORY_COUNTERS_EX pmc;
+  if (!::GetProcessMemoryInfo(process_.get(),
+                              reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc),
+                              sizeof(pmc))) {
+    return base::unexpected(ProcessUsageError::kSystemError);
+  }
+  ProcessMemoryInfo counters;
+  counters.private_bytes = pmc.PrivateUsage;
+  counters.resident_set_bytes = pmc.WorkingSetSize;
+  return counters;
+}
+
 base::expected<TimeDelta, ProcessCPUUsageError>
 ProcessMetrics::GetCumulativeCPUUsage() {
 #if defined(ARCH_CPU_ARM64)
diff --git a/chrome/browser/ash/arc/memory_pressure/container_app_killer.cc b/chrome/browser/ash/arc/memory_pressure/container_app_killer.cc
index d4bc2f4f..8dfa393 100644
--- a/chrome/browser/ash/arc/memory_pressure/container_app_killer.cc
+++ b/chrome/browser/ash/arc/memory_pressure/container_app_killer.cc
@@ -155,9 +155,10 @@
 
 uint64_t ContainerAppKiller::GetMemoryFootprintKB(base::ProcessId pid) {
   auto process_metrics = base::ProcessMetrics::CreateProcessMetrics(pid);
-  return (process_metrics->GetVmSwapBytes() +
-          process_metrics->GetResidentSetSize()) /
-         1024;
+  auto info = process_metrics->GetMemoryInfo();
+  return info.has_value()
+             ? (info->vm_swap_bytes + info->resident_set_bytes) / 1024
+             : 0;
 }
 
 bool ContainerAppKiller::KillArcProcess(base::ProcessId nspid) {
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
index 39060df7e..9987daac 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -866,8 +866,8 @@
     // To match with the memory maps, need to convert it to absolute path,
     // which may hit ScopedBlockingCall.
     base::ScopedAllowBlockingForTesting allow_blocking;
-    auto maps =
-        memory_instrumentation::OSMetrics::GetProcessMemoryMaps(process.Pid());
+    auto maps = memory_instrumentation::OSMetrics::GetProcessMemoryMaps(
+        process.Handle());
     bool found = false;
     for (const memory_instrumentation::mojom::VmRegionPtr& region : maps) {
       if (region->module_debugid.empty())
diff --git a/chrome/browser/resource_coordinator/utils.cc b/chrome/browser/resource_coordinator/utils.cc
index 1c89633..b432099e7a 100644
--- a/chrome/browser/resource_coordinator/utils.cc
+++ b/chrome/browser/resource_coordinator/utils.cc
@@ -30,8 +30,8 @@
   auto dump = memory_instrumentation::mojom::RawOSMemDump::New();
   dump->platform_private_footprint =
       memory_instrumentation::mojom::PlatformPrivateFootprint::New();
-  bool success = memory_instrumentation::OSMetrics::FillOSMemoryDump(
-      base::GetProcId(handle), dump.get());
+  bool success =
+      memory_instrumentation::OSMetrics::FillOSMemoryDump(handle, dump.get());
 
   // Failed to get private memory for the process, e.g. the process has died.
   if (!success)
diff --git a/chrome/browser/task_manager/sampling/task_group_sampler.cc b/chrome/browser/task_manager/sampling/task_group_sampler.cc
index fb04077..5366e24c 100644
--- a/chrome/browser/task_manager/sampling/task_group_sampler.cc
+++ b/chrome/browser/task_manager/sampling/task_group_sampler.cc
@@ -138,7 +138,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(worker_pool_sequenced_checker_);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  return process_metrics_->GetVmSwapBytes();
+  auto info = process_metrics_->GetMemoryInfo();
+  if (!info.has_value()) {
+    return 0;
+  }
+  return info->vm_swap_bytes;
 #else
   return 0;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/services/heap_profiling/json_exporter_unittest.cc b/components/services/heap_profiling/json_exporter_unittest.cc
index cbe3f02..7e27d43 100644
--- a/components/services/heap_profiling/json_exporter_unittest.cc
+++ b/components/services/heap_profiling/json_exporter_unittest.cc
@@ -293,7 +293,7 @@
 TEST(ProfilingJsonExporterTest, MAYBE_MemoryMaps) {
   ExportParams params;
   params.maps = memory_instrumentation::OSMetrics::GetProcessMemoryMaps(
-      base::Process::Current().Pid());
+      base::Process::Current().Handle());
   ASSERT_GT(params.maps.size(), 2u);
 
   std::string json = ExportMemoryMapsAndV2StackTraceToJSON(&params);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 183ddbb..93fb4523 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -5088,14 +5088,12 @@
   dump->platform_private_footprint =
       memory_instrumentation::mojom::PlatformPrivateFootprint::New();
 #if BUILDFLAG(IS_APPLE)
-  bool success =
-      memory_instrumentation::OSMetrics::FillOSMemoryDumpFromTaskPort(
-          ChildProcessTaskPortProvider::GetInstance()->TaskForHandle(
-              GetProcess().Handle()),
-          dump.get());
+  bool success = memory_instrumentation::OSMetrics::FillOSMemoryDump(
+      GetProcess().Handle(), ChildProcessTaskPortProvider::GetInstance(),
+      dump.get());
 #else
   bool success = memory_instrumentation::OSMetrics::FillOSMemoryDump(
-      GetProcess().Pid(), dump.get());
+      GetProcess().Handle(), dump.get());
 #endif
 
   // Failed to get private memory for the process, e.g. the process has died.
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
index 291774e..6386862 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
@@ -8,6 +8,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/not_fatal_until.h"
+#include "base/process/process.h"
 #include "base/synchronization/lock.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/trace_event/memory_dump_request_args.h"
@@ -169,12 +170,13 @@
   bool global_success = true;
   base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr> results;
   for (const base::ProcessId& pid : args.pids) {
+    auto handle = base::Process::Open(pid).Handle();
     mojom::RawOSMemDumpPtr result = mojom::RawOSMemDump::New();
     result->platform_private_footprint = mojom::PlatformPrivateFootprint::New();
-    bool success = OSMetrics::FillOSMemoryDump(pid, result.get());
+    bool success = OSMetrics::FillOSMemoryDump(handle, result.get());
     if (args.mmap_option != mojom::MemoryMapOption::NONE) {
       success = success && OSMetrics::FillProcessMemoryMaps(
-                               pid, args.mmap_option, result.get());
+                               handle, args.mmap_option, result.get());
     }
     if (success) {
       results[pid] = std::move(result);
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
index ae67a8b..0e7ab66 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
@@ -9,7 +9,7 @@
 namespace memory_instrumentation {
 
 // static
-bool OSMetrics::FillProcessMemoryMaps(base::ProcessId pid,
+bool OSMetrics::FillProcessMemoryMaps(base::ProcessHandle handle,
                                       mojom::MemoryMapOption mmap_option,
                                       mojom::RawOSMemDump* dump) {
   DCHECK_NE(mmap_option, mojom::MemoryMapOption::NONE);
@@ -19,9 +19,9 @@
 #if BUILDFLAG(IS_MAC)
   // On macOS, fetching all memory maps is very slow. See
   // https://crbug.com/826913 and https://crbug.com/1035401.
-  results = GetProcessModules(pid);
+  results = GetProcessModules(handle);
 #else
-  results = GetProcessMemoryMaps(pid);
+  results = GetProcessMemoryMaps(handle);
 
 #endif
 
@@ -33,4 +33,15 @@
   return true;
 }
 
+#if !BUILDFLAG(IS_APPLE)
+base::expected<base::ProcessMemoryInfo, base::ProcessUsageError>
+OSMetrics::GetMemoryInfo(base::ProcessHandle handle) {
+  auto process_metrics =
+      (handle == base::kNullProcessHandle)
+          ? base::ProcessMetrics::CreateCurrentProcessMetrics()
+          : base::ProcessMetrics::CreateProcessMetrics(handle);
+  return process_metrics->GetMemoryInfo();
+}
+#endif  // !BUILDFLAG(IS_APPLE)
+
 }  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
index f04f99d..b690f95 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
@@ -9,6 +9,7 @@
 #include "base/component_export.h"
 #include "base/gtest_prod_util.h"
 #include "base/process/process_handle.h"
+#include "base/process/process_metrics.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "build/build_config.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
@@ -39,19 +40,22 @@
 class COMPONENT_EXPORT(
     RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) OSMetrics {
  public:
-  // Fills |dump| with memory information about |pid|. See class comments for
-  // restrictions on |pid|. |dump.platform_private_footprint| must be allocated
-  // before calling this function. If |pid| is null, the pid of the current
-  // process is used
-  static bool FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump);
+  // Fills |dump| with memory information about |handle|. See class comments for
+  // restrictions on |handle|. |dump.platform_private_footprint| must be
+  // allocated before calling this function. If |handle| is null, the handle of
+  // the current process is used
+  static bool FillOSMemoryDump(base::ProcessHandle handle,
+                               mojom::RawOSMemDump* dump);
 #if BUILDFLAG(IS_APPLE)
-  static bool FillOSMemoryDumpFromTaskPort(mach_port_t task_port,
-                                           mojom::RawOSMemDump* dump);
+  static bool FillOSMemoryDump(base::ProcessHandle handle,
+                               base::PortProvider* port_provider,
+                               mojom::RawOSMemDump* dump);
 #endif
-  static bool FillProcessMemoryMaps(base::ProcessId,
+  static bool FillProcessMemoryMaps(base::ProcessHandle,
                                     mojom::MemoryMapOption,
                                     mojom::RawOSMemDump*);
-  static std::vector<mojom::VmRegionPtr> GetProcessMemoryMaps(base::ProcessId);
+  static std::vector<mojom::VmRegionPtr> GetProcessMemoryMaps(
+      base::ProcessHandle);
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
   static void SetProcSmapsForTesting(FILE*);
@@ -67,9 +71,14 @@
                            MemoryMaps);
 
 #if BUILDFLAG(IS_MAC)
-  static std::vector<mojom::VmRegionPtr> GetProcessModules(base::ProcessId);
+  static std::vector<mojom::VmRegionPtr> GetProcessModules(base::ProcessHandle);
 #endif
 
+#if !BUILDFLAG(IS_APPLE)
+  static base::expected<base::ProcessMemoryInfo, base::ProcessUsageError>
+  GetMemoryInfo(base::ProcessHandle handle);
+#endif  // !BUILDFLAG(IS_APPLE)
+
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
   // Provides information on the dump state of resident pages. These values are
   // written to logs. New enum values can be added, but existing enums must
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
index 36f4fa1..b7dedda 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
@@ -18,32 +18,23 @@
 namespace memory_instrumentation {
 
 // static
-bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
+bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
                                  mojom::RawOSMemDump* dump) {
-  base::Process process = pid == base::kNullProcessId
-                              ? base::Process::Current()
-                              : base::Process::Open(pid);
-  zx::unowned<zx::process> zx_process(process.Handle());
-  zx_info_task_stats_t info;
-  zx_status_t status = zx_process->get_info(ZX_INFO_TASK_STATS, &info,
-                                            sizeof(info), nullptr, nullptr);
-  if (status != ZX_OK) {
+  auto info = GetMemoryInfo(handle);
+  if (!info.has_value()) {
     return false;
   }
 
-  size_t rss_bytes = info.mem_private_bytes + info.mem_shared_bytes;
-  size_t rss_anon_bytes = info.mem_private_bytes;
-
-  dump->resident_set_kb = rss_bytes / 1024;
-  dump->platform_private_footprint->rss_anon_bytes = rss_anon_bytes;
-  // Fuchsia has no swap.
-  dump->platform_private_footprint->vm_swap_bytes = 0;
+  dump->platform_private_footprint->rss_anon_bytes = info->rss_anon_bytes;
+  dump->platform_private_footprint->vm_swap_bytes = info->vm_swap_bytes;
+  dump->resident_set_kb =
+      base::saturated_cast<uint32_t>(info->resident_set_bytes / 1024);
   return true;
 }
 
 // static
 std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessMemoryMaps(
-    base::ProcessId) {
+    base::ProcessHandle) {
   // TODO(crbug.com/40720107): Implement this.
   NOTIMPLEMENTED();
   return std::vector<mojom::VmRegionPtr>();
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
index 03edcc7..588c7f53 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
@@ -54,20 +54,6 @@
       pid == base::kNullProcessId ? "self" : base::NumberToString(pid));
 }
 
-bool GetResidentAndSharedPagesFromStatmFile(int fd,
-                                            uint64_t* resident_pages,
-                                            uint64_t* shared_pages) {
-  lseek(fd, 0, SEEK_SET);
-  char line[kMaxLineSize];
-  int res = read(fd, line, kMaxLineSize - 1);
-  if (res <= 0)
-    return false;
-  line[res] = '\0';
-  int num_scanned =
-      sscanf(line, "%*s %" SCNu64 " %" SCNu64, resident_pages, shared_pages);
-  return num_scanned == 2;
-}
-
 bool ResetPeakRSSIfPossible(base::ProcessId pid) {
   static bool is_peak_rss_resettable = true;
   if (!is_peak_rss_resettable)
@@ -80,14 +66,6 @@
   return is_peak_rss_resettable;
 }
 
-std::unique_ptr<base::ProcessMetrics> CreateProcessMetrics(
-    base::ProcessId pid) {
-  if (pid == base::kNullProcessId) {
-    return base::ProcessMetrics::CreateCurrentProcessMetrics();
-  }
-  return base::ProcessMetrics::CreateProcessMetrics(pid);
-}
-
 struct ModuleData {
   std::string path;
   std::string build_id;
@@ -290,36 +268,19 @@
 }
 
 // static
-bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
+bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
                                  mojom::RawOSMemDump* dump) {
-  // TODO(chiniforooshan): There is no need to read both /statm and /status
-  // files. Refactor to get everything from /status using ProcessMetric.
-  auto statm_file = GetProcPidDir(pid).Append("statm");
-  auto autoclose = base::ScopedFD(open(statm_file.value().c_str(), O_RDONLY));
-  int statm_fd = autoclose.get();
-
-  if (statm_fd == -1)
+  auto info = GetMemoryInfo(handle);
+  if (!info.has_value()) {
     return false;
+  }
 
-  uint64_t resident_pages;
-  uint64_t shared_pages;
-  bool success = GetResidentAndSharedPagesFromStatmFile(
-      statm_fd, &resident_pages, &shared_pages);
-
-  if (!success)
-    return false;
-
-  auto process_metrics = CreateProcessMetrics(pid);
-
-  static const size_t page_size = base::GetPageSize();
-  uint64_t rss_anon_bytes = (resident_pages - shared_pages) * page_size;
-  uint64_t vm_swap_bytes = process_metrics->GetVmSwapBytes();
-
-  dump->platform_private_footprint->rss_anon_bytes = rss_anon_bytes;
-  dump->platform_private_footprint->vm_swap_bytes = vm_swap_bytes;
-  dump->resident_set_kb = process_metrics->GetResidentSetSize() / 1024;
-  dump->peak_resident_set_kb = GetPeakResidentSetSize(pid);
-  dump->is_peak_rss_resettable = ResetPeakRSSIfPossible(pid);
+  dump->platform_private_footprint->rss_anon_bytes = info->rss_anon_bytes;
+  dump->platform_private_footprint->vm_swap_bytes = info->vm_swap_bytes;
+  dump->resident_set_kb =
+      base::saturated_cast<uint32_t>(info->resident_set_bytes / 1024);
+  dump->peak_resident_set_kb = GetPeakResidentSetSize(handle);
+  dump->is_peak_rss_resettable = ResetPeakRSSIfPossible(handle);
 
 #if BUILDFLAG(IS_ANDROID)
 #if BUILDFLAG(SUPPORTS_CODE_ORDERING)
@@ -351,7 +312,8 @@
 }
 
 // static
-std::vector<VmRegionPtr> OSMetrics::GetProcessMemoryMaps(base::ProcessId pid) {
+std::vector<VmRegionPtr> OSMetrics::GetProcessMemoryMaps(
+    base::ProcessHandle handle) {
   std::vector<VmRegionPtr> maps;
   uint32_t res = 0;
   if (g_proc_smaps_for_testing) {
@@ -359,7 +321,8 @@
   } else {
     std::string file_name =
         "/proc/" +
-        (pid == base::kNullProcessId ? "self" : base::NumberToString(pid)) +
+        (handle == base::kNullProcessHandle ? "self"
+                                            : base::NumberToString(handle)) +
         "/smaps";
     base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r"));
     res = ReadLinuxProcSmapsFile(smaps_file.get(), &maps);
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc
index c6c1833..a45ebda 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc
@@ -33,34 +33,6 @@
 
 namespace {
 
-// Don't simply use sizeof(task_vm_info) / sizeof(natural_t):
-// In the 10.15 SDK, this structure is 87 32-bit words long, and in
-// mach_types.defs:
-//
-//   type task_info_t    = array[*:87] of integer_t;
-//
-// However in the 10.14 SDK, this structure is 42 32-bit words, and in
-// mach_types.defs:
-//
-//   type task_info_t    = array[*:52] of integer_t;
-//
-// As a result, the 10.15 SDK's task_vm_info won't fit inside the 10.14 SDK's
-// task_info_t, so the *rest of the system* (on 10.14 and earlier) can't handle
-// calls that request the full 10.15 structure. We have to request a prefix of
-// it that 10.14 and earlier can handle by limiting the length we request. The
-// rest of the fields just get ignored, but we don't use them anyway.
-
-constexpr mach_msg_type_number_t ChromeTaskVMInfoCount =
-    TASK_VM_INFO_REV2_COUNT;
-
-// The count field is in units of natural_t, which is the machine's word size
-// (64 bits on all modern machines), but the task_info_t array is in units of
-// integer_t, which is 32 bits.
-constexpr mach_msg_type_number_t MAX_MIG_SIZE_FOR_1014 =
-    52 / (sizeof(natural_t) / sizeof(integer_t));
-static_assert(ChromeTaskVMInfoCount <= MAX_MIG_SIZE_FOR_1014,
-              "task_vm_info must be small enough for 10.14 MIG interfaces");
-
 using VMRegion = mojom::VmRegion;
 
 bool IsAddressInSharedRegion(uint64_t address) {
@@ -254,41 +226,38 @@
 }  // namespace
 
 // static
-bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
+bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
                                  mojom::RawOSMemDump* dump) {
-  if (pid != base::kNullProcessId && pid != base::GetCurrentProcId()) {
+  auto current_handle = base::GetCurrentProcessHandle();
+  if (handle != base::kNullProcessId && handle != current_handle) {
     return false;
   }
-  return FillOSMemoryDumpFromTaskPort(mach_task_self(), dump);
+  return FillOSMemoryDump(current_handle, nullptr, dump);
 }
 
 // static
-bool OSMetrics::FillOSMemoryDumpFromTaskPort(mach_port_t task_port,
-                                             mojom::RawOSMemDump* dump) {
-  task_vm_info info;
-  mach_msg_type_number_t count = ChromeTaskVMInfoCount;
-  kern_return_t result = task_info(
-      task_port, TASK_VM_INFO, reinterpret_cast<task_info_t>(&info), &count);
-  if (result != KERN_SUCCESS)
+bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
+                                 base::PortProvider* port_provider,
+                                 mojom::RawOSMemDump* dump) {
+  auto process_metrics =
+      base::ProcessMetrics::CreateProcessMetrics(handle, port_provider);
+  auto info = process_metrics->GetMemoryInfo();
+  if (!info.has_value()) {
     return false;
-
-  dump->platform_private_footprint->internal_bytes = info.internal;
-  dump->platform_private_footprint->compressed_bytes = info.compressed;
-  dump->resident_set_kb = info.resident_size / 1024;
-  dump->peak_resident_set_kb = info.resident_size_peak / 1024;
-
-  // The |phys_footprint| field was introduced in 10.11.
-  if (count == ChromeTaskVMInfoCount) {
-    dump->platform_private_footprint->phys_footprint_bytes =
-        info.phys_footprint;
   }
 
+  dump->platform_private_footprint->phys_footprint_bytes =
+      info->physical_footprint_bytes;
+  dump->platform_private_footprint->internal_bytes = info->internal_bytes;
+  dump->platform_private_footprint->compressed_bytes = info->compressed_bytes;
+  dump->resident_set_kb =
+      base::saturated_cast<uint32_t>(info->resident_set_bytes / 1024);
   return true;
 }
 
 // static
 std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessMemoryMaps(
-    base::ProcessId pid) {
+    base::ProcessHandle handle) {
   std::vector<mojom::VmRegionPtr> maps;
 
   std::vector<VMRegion> dyld_regions;
@@ -340,7 +309,7 @@
 
 #if !BUILDFLAG(IS_IOS)
 std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessModules(
-    base::ProcessId pid) {
+    base::ProcessHandle handle) {
   std::vector<mojom::VmRegionPtr> maps;
 
   std::vector<VMRegion> dyld_regions;
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
index 841a542..e825189 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
@@ -137,10 +137,10 @@
         // BUILDFLAG(IS_ANDROID)
 
 TEST(OSMetricsTest, GivesNonZeroResults) {
-  base::ProcessId pid = base::kNullProcessId;
+  base::ProcessHandle handle = base::kNullProcessHandle;
   mojom::RawOSMemDump dump;
   dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
-  EXPECT_TRUE(OSMetrics::FillOSMemoryDump(pid, &dump));
+  EXPECT_TRUE(OSMetrics::FillOSMemoryDump(handle, &dump));
   EXPECT_TRUE(dump.platform_private_footprint);
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
     BUILDFLAG(IS_FUCHSIA)
@@ -162,14 +162,14 @@
   base::ScopedFILE empty_file(OpenFile(base::FilePath("/dev/null"), "r"));
   ASSERT_TRUE(empty_file.get());
   OSMetrics::SetProcSmapsForTesting(empty_file.get());
-  auto no_maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
+  auto no_maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessHandle);
   ASSERT_TRUE(no_maps.empty());
 
   // Parse the 1st smaps file.
   base::ScopedFILE temp_file1;
   CreateTempFileWithContents(kTestSmaps1, &temp_file1);
   OSMetrics::SetProcSmapsForTesting(temp_file1.get());
-  auto maps_1 = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
+  auto maps_1 = OSMetrics::GetProcessMemoryMaps(base::kNullProcessHandle);
   ASSERT_EQ(2UL, maps_1.size());
 
   EXPECT_EQ(0x00400000UL, maps_1[0]->start_address);
@@ -200,7 +200,7 @@
   base::ScopedFILE temp_file2;
   CreateTempFileWithContents(kTestSmaps2, &temp_file2);
   OSMetrics::SetProcSmapsForTesting(temp_file2.get());
-  auto maps_2 = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
+  auto maps_2 = OSMetrics::GetProcessMemoryMaps(base::kNullProcessHandle);
   ASSERT_EQ(1UL, maps_2.size());
   EXPECT_EQ(0x7fe7ce79c000UL, maps_2[0]->start_address);
   EXPECT_EQ(0x7fe7ce7a8000UL - 0x7fe7ce79c000UL, maps_2[0]->size_in_bytes);
@@ -266,7 +266,7 @@
 void DummyFunction() {}
 
 TEST(OSMetricsTest, TestWinModuleReading) {
-  auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
+  auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessHandle);
 
   wchar_t module_name[MAX_PATH];
   DWORD result = GetModuleFileName(nullptr, module_name, MAX_PATH);
@@ -350,9 +350,9 @@
 
 // Test failing on Mac ASan 64: https://crbug.com/852690
 TEST(OSMetricsTest, DISABLED_TestMachOReading) {
-  auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessId);
+  auto maps = OSMetrics::GetProcessMemoryMaps(base::kNullProcessHandle);
   CheckMachORegions(maps);
-  maps = OSMetrics::GetProcessModules(base::kNullProcessId);
+  maps = OSMetrics::GetProcessModules(base::kNullProcessHandle);
   CheckMachORegions(maps);
 }
 #endif  // BUILDFLAG(IS_MAC)
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
index ddcf3cc..7b6b4ce 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
@@ -40,32 +40,22 @@
 }  // namespace
 
 // static
-bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
+bool OSMetrics::FillOSMemoryDump(base::ProcessHandle handle,
                                  mojom::RawOSMemDump* dump) {
-  base::Process process;
-  if (pid == base::kNullProcessId) {
-    process = base::Process::Current();
-  } else {
-    process = base::Process::Open(pid);
-  }
-  if (!process.IsValid()) {
+  auto info = GetMemoryInfo(handle);
+  if (!info.has_value()) {
     return false;
   }
-  PROCESS_MEMORY_COUNTERS_EX pmc;
-  if (::GetProcessMemoryInfo(process.Handle(),
-                             reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc),
-                             sizeof(pmc))) {
-    dump->platform_private_footprint->private_bytes = pmc.PrivateUsage;
-    dump->resident_set_kb =
-        base::saturated_cast<uint32_t>(pmc.WorkingSetSize / 1024);
-    return true;
-  }
-  return false;
+
+  dump->platform_private_footprint->private_bytes = info->private_bytes;
+  dump->resident_set_kb =
+      base::saturated_cast<uint32_t>(info->resident_set_bytes / 1024);
+  return true;
 }
 
 // static
 std::vector<mojom::VmRegionPtr> OSMetrics::GetProcessMemoryMaps(
-    base::ProcessId pid) {
+    base::ProcessHandle handle) {
   std::vector<mojom::VmRegionPtr> maps;
   std::vector<HMODULE> modules;
   if (!base::win::GetLoadedModulesSnapshot(::GetCurrentProcess(), &modules))