blob: 979cb6c3a2315bb1e735f880883b982c5fe65592 [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2012 The Chromium Authors
[email protected]f164cea2009-11-05 23:37:402// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/memory_details.h"
6
avi6846aef2015-12-26 01:09:387#include <stddef.h>
8
dcheng4af48582016-04-19 00:29:359#include <memory>
[email protected]f164cea2009-11-05 23:37:4010#include <set>
11#include <string>
12
Avi Drissmaneac566b02023-08-18 02:56:2113#include "base/apple/foundation_util.h"
[email protected]f164cea2009-11-05 23:37:4014#include "base/file_version_info.h"
[email protected]57999812013-02-24 05:40:5215#include "base/files/file_path.h"
Avi Drissman9269d4ed2023-01-07 01:38:0616#include "base/functional/bind.h"
[email protected]d09a4ce1c2013-07-24 17:37:0217#include "base/process/process_iterator.h"
[email protected]f9b294362013-06-10 20:22:3118#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1819#include "base/strings/utf_string_conversions.h"
Etienne Pierre-doray0fbce432018-08-27 20:27:5120#include "base/threading/scoped_blocking_call.h"
[email protected]34b99632011-01-01 01:01:0621#include "base/threading/thread.h"
[email protected]f164cea2009-11-05 23:37:4022#include "chrome/common/chrome_constants.h"
23#include "chrome/common/url_constants.h"
Henrique Ferreirod78ab262023-09-13 11:21:4324#include "chrome/grit/branded_strings.h"
sdefresne9fb67692015-08-03 18:48:2225#include "components/version_info/version_info.h"
asvitkine58409e4c2015-01-15 01:25:4526#include "content/public/browser/browser_child_process_host.h"
Eric Seckler8652dcd52018-09-20 10:42:2827#include "content/public/browser/browser_task_traits.h"
[email protected]c38831a12011-10-28 12:44:4928#include "content/public/browser/browser_thread.h"
[email protected]bd5d6cf2011-12-01 00:39:1229#include "content/public/common/process_type.h"
[email protected]c051a1b2011-01-21 23:30:1730#include "ui/base/l10n/l10n_util.h"
[email protected]f164cea2009-11-05 23:37:4031
asvitkine6f5f3592015-01-21 20:50:3732namespace {
33
34// A helper for |CollectProcessData()|, collecting data on the Chrome/Chromium
35// process with PID |pid|. The collected data is added to |processes|.
36void CollectProcessDataForChromeProcess(
37 const std::vector<ProcessMemoryInformation>& child_info,
38 base::ProcessId pid,
39 ProcessMemoryInformationList* processes) {
40 ProcessMemoryInformation info;
41 info.pid = pid;
42 if (info.pid == base::GetCurrentProcId())
43 info.process_type = content::PROCESS_TYPE_BROWSER;
44 else
45 info.process_type = content::PROCESS_TYPE_UNKNOWN;
46
sdefresne9fb67692015-08-03 18:48:2247 info.product_name = base::ASCIIToUTF16(version_info::GetProductName());
48 info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
asvitkine6f5f3592015-01-21 20:50:3749
Robert Sesek3aff3362019-01-23 20:16:1650 // A PortProvider is not necessary to acquire information about the number
51 // of open file descriptors.
52 std::unique_ptr<base::ProcessMetrics> metrics(
53 base::ProcessMetrics::CreateProcessMetrics(pid, nullptr));
54 info.num_open_fds = metrics->GetOpenFdCount();
55 info.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
56
asvitkine6f5f3592015-01-21 20:50:3757 // Check if this is one of the child processes whose data was already
58 // collected and exists in |child_data|.
59 for (const ProcessMemoryInformation& child : child_info) {
60 if (child.pid == info.pid) {
61 info.titles = child.titles;
62 info.process_type = child.process_type;
63 break;
64 }
65 }
66
asvitkine6f5f3592015-01-21 20:50:3767 processes->push_back(info);
68}
69
asvitkine6f5f3592015-01-21 20:50:3770} // namespace
[email protected]f164cea2009-11-05 23:37:4071
asvitkine89406d1f2015-01-17 06:57:1072MemoryDetails::MemoryDetails() {
asvitkine58409e4c2015-01-15 01:25:4573 const base::FilePath browser_process_path =
74 base::GetProcessExecutablePath(base::GetCurrentProcessHandle());
asvitkine58409e4c2015-01-15 01:25:4575
ellyjonescd6e449d2016-04-13 19:31:1576 ProcessData process;
77 process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
78 process.process_name =
79 base::UTF8ToUTF16(browser_process_path.BaseName().value());
80 process_data_.push_back(process);
[email protected]f164cea2009-11-05 23:37:4081}
82
83ProcessData* MemoryDetails::ChromeBrowser() {
ellyjonescd6e449d2016-04-13 19:31:1584 return &process_data_[0];
[email protected]f164cea2009-11-05 23:37:4085}
86
87void MemoryDetails::CollectProcessData(
[email protected]4df3ac62011-03-11 04:38:5288 const std::vector<ProcessMemoryInformation>& child_info) {
Etienne Bergeron436d42212019-02-26 17:15:1289 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
90 base::BlockingType::MAY_BLOCK);
[email protected]f164cea2009-11-05 23:37:4091
92 // Clear old data.
ellyjonescd6e449d2016-04-13 19:31:1593 process_data_[0].processes.clear();
[email protected]f164cea2009-11-05 23:37:4094
95 // First, we use |NamedProcessIterator| to get the PIDs of the processes we're
96 // interested in; we save our results to avoid extra calls to
97 // |NamedProcessIterator| (for performance reasons) and to avoid additional
98 // inconsistencies caused by racing. Then we run |/bin/ps| *once* to get
99 // information on those PIDs. Then we used our saved information to iterate
100 // over browsers, then over PIDs.
101
102 // Get PIDs of main browser processes.
[email protected]f164cea2009-11-05 23:37:40103 std::vector<base::ProcessId> all_pids;
ellyjonescd6e449d2016-04-13 19:31:15104 {
[email protected]4f260d02010-12-23 18:35:42105 base::NamedProcessIterator process_it(
ellyjonescd6e449d2016-04-13 19:31:15106 base::UTF16ToUTF8(process_data_[0].process_name), NULL);
[email protected]f164cea2009-11-05 23:37:40107
[email protected]a5a00b1d2010-04-08 15:52:45108 while (const base::ProcessEntry* entry = process_it.NextProcessEntry()) {
[email protected]b6128aa2010-04-29 17:44:42109 all_pids.push_back(entry->pid());
[email protected]f164cea2009-11-05 23:37:40110 }
111 }
112
kerrnel0c619642015-09-21 18:39:54113 // Get PIDs of the helper.
ellyjonescd6e449d2016-04-13 19:31:15114 {
115 base::NamedProcessIterator helper_it(chrome::kHelperProcessExecutableName,
Leonard Grey77c540e2022-10-28 20:04:15116 NULL, /*use_prefix_match=*/true);
ellyjonescd6e449d2016-04-13 19:31:15117 while (const base::ProcessEntry* entry = helper_it.NextProcessEntry()) {
118 all_pids.push_back(entry->pid());
119 }
[email protected]f164cea2009-11-05 23:37:40120 }
121
ellyjonescd6e449d2016-04-13 19:31:15122 ProcessMemoryInformationList* chrome_processes = &process_data_[0].processes;
asvitkine6f5f3592015-01-21 20:50:37123
[email protected]f164cea2009-11-05 23:37:40124 // Collect data about Chrome/Chromium.
ellyjonescd6e449d2016-04-13 19:31:15125 for (const base::ProcessId& pid : all_pids)
asvitkine6f5f3592015-01-21 20:50:37126 CollectProcessDataForChromeProcess(child_info, pid, chrome_processes);
[email protected]f164cea2009-11-05 23:37:40127
128 // Finally return to the browser thread.
Gabriel Charettee7cdc5cd2020-05-27 23:35:05129 content::GetUIThreadTaskRunner({})->PostTask(
130 FROM_HERE,
kylechar99ef9042019-02-25 18:09:43131 base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));
[email protected]f164cea2009-11-05 23:37:40132}