blob: b9d67ca2671c2747cf7b788eaf7f0295100c0aa5 [file] [log] [blame]
[email protected]b0b67cf2012-01-18 21:59:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[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
[email protected]24d69692011-10-21 18:26:5113#include "base/bind.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"
avi69fed022014-12-21 01:02:5216#include "base/mac/foundation_util.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"
Eric Seckler8652dcd52018-09-20 10:42:2820#include "base/task/post_task.h"
Etienne Pierre-doray0fbce432018-08-27 20:27:5121#include "base/threading/scoped_blocking_call.h"
[email protected]34b99632011-01-01 01:01:0622#include "base/threading/thread.h"
[email protected]f164cea2009-11-05 23:37:4023#include "chrome/common/chrome_constants.h"
24#include "chrome/common/url_constants.h"
[email protected]af39f002014-08-22 10:18:1825#include "chrome/grit/chromium_strings.h"
sdefresne9fb67692015-08-03 18:48:2226#include "components/version_info/version_info.h"
asvitkine58409e4c2015-01-15 01:25:4527#include "content/public/browser/browser_child_process_host.h"
Eric Seckler8652dcd52018-09-20 10:42:2828#include "content/public/browser/browser_task_traits.h"
[email protected]c38831a12011-10-28 12:44:4929#include "content/public/browser/browser_thread.h"
[email protected]bd5d6cf2011-12-01 00:39:1230#include "content/public/common/process_type.h"
[email protected]c051a1b2011-01-21 23:30:1731#include "ui/base/l10n/l10n_util.h"
[email protected]f164cea2009-11-05 23:37:4032
[email protected]631bb742011-11-02 11:29:3933using content::BrowserThread;
34
asvitkine6f5f3592015-01-21 20:50:3735namespace {
36
37// A helper for |CollectProcessData()|, collecting data on the Chrome/Chromium
38// process with PID |pid|. The collected data is added to |processes|.
39void CollectProcessDataForChromeProcess(
40 const std::vector<ProcessMemoryInformation>& child_info,
41 base::ProcessId pid,
42 ProcessMemoryInformationList* processes) {
43 ProcessMemoryInformation info;
44 info.pid = pid;
45 if (info.pid == base::GetCurrentProcId())
46 info.process_type = content::PROCESS_TYPE_BROWSER;
47 else
48 info.process_type = content::PROCESS_TYPE_UNKNOWN;
49
sdefresne9fb67692015-08-03 18:48:2250 info.product_name = base::ASCIIToUTF16(version_info::GetProductName());
51 info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
asvitkine6f5f3592015-01-21 20:50:3752
Robert Sesek3aff3362019-01-23 20:16:1653 // A PortProvider is not necessary to acquire information about the number
54 // of open file descriptors.
55 std::unique_ptr<base::ProcessMetrics> metrics(
56 base::ProcessMetrics::CreateProcessMetrics(pid, nullptr));
57 info.num_open_fds = metrics->GetOpenFdCount();
58 info.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
59
asvitkine6f5f3592015-01-21 20:50:3760 // Check if this is one of the child processes whose data was already
61 // collected and exists in |child_data|.
62 for (const ProcessMemoryInformation& child : child_info) {
63 if (child.pid == info.pid) {
64 info.titles = child.titles;
65 info.process_type = child.process_type;
66 break;
67 }
68 }
69
asvitkine6f5f3592015-01-21 20:50:3770 processes->push_back(info);
71}
72
asvitkine6f5f3592015-01-21 20:50:3773} // namespace
[email protected]f164cea2009-11-05 23:37:4074
asvitkine89406d1f2015-01-17 06:57:1075MemoryDetails::MemoryDetails() {
asvitkine58409e4c2015-01-15 01:25:4576 const base::FilePath browser_process_path =
77 base::GetProcessExecutablePath(base::GetCurrentProcessHandle());
asvitkine58409e4c2015-01-15 01:25:4578
ellyjonescd6e449d2016-04-13 19:31:1579 ProcessData process;
80 process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
81 process.process_name =
82 base::UTF8ToUTF16(browser_process_path.BaseName().value());
83 process_data_.push_back(process);
[email protected]f164cea2009-11-05 23:37:4084}
85
86ProcessData* MemoryDetails::ChromeBrowser() {
ellyjonescd6e449d2016-04-13 19:31:1587 return &process_data_[0];
[email protected]f164cea2009-11-05 23:37:4088}
89
90void MemoryDetails::CollectProcessData(
[email protected]4df3ac62011-03-11 04:38:5291 const std::vector<ProcessMemoryInformation>& child_info) {
Etienne Pierre-doray0fbce432018-08-27 20:27:5192 base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
[email protected]f164cea2009-11-05 23:37:4093
94 // Clear old data.
ellyjonescd6e449d2016-04-13 19:31:1595 process_data_[0].processes.clear();
[email protected]f164cea2009-11-05 23:37:4096
97 // First, we use |NamedProcessIterator| to get the PIDs of the processes we're
98 // interested in; we save our results to avoid extra calls to
99 // |NamedProcessIterator| (for performance reasons) and to avoid additional
100 // inconsistencies caused by racing. Then we run |/bin/ps| *once* to get
101 // information on those PIDs. Then we used our saved information to iterate
102 // over browsers, then over PIDs.
103
104 // Get PIDs of main browser processes.
[email protected]f164cea2009-11-05 23:37:40105 std::vector<base::ProcessId> all_pids;
ellyjonescd6e449d2016-04-13 19:31:15106 {
[email protected]4f260d02010-12-23 18:35:42107 base::NamedProcessIterator process_it(
ellyjonescd6e449d2016-04-13 19:31:15108 base::UTF16ToUTF8(process_data_[0].process_name), NULL);
[email protected]f164cea2009-11-05 23:37:40109
[email protected]a5a00b1d2010-04-08 15:52:45110 while (const base::ProcessEntry* entry = process_it.NextProcessEntry()) {
[email protected]b6128aa2010-04-29 17:44:42111 all_pids.push_back(entry->pid());
[email protected]f164cea2009-11-05 23:37:40112 }
113 }
114
kerrnel0c619642015-09-21 18:39:54115 // Get PIDs of the helper.
ellyjonescd6e449d2016-04-13 19:31:15116 {
117 base::NamedProcessIterator helper_it(chrome::kHelperProcessExecutableName,
118 NULL);
119 while (const base::ProcessEntry* entry = helper_it.NextProcessEntry()) {
120 all_pids.push_back(entry->pid());
121 }
[email protected]f164cea2009-11-05 23:37:40122 }
123
ellyjonescd6e449d2016-04-13 19:31:15124 ProcessMemoryInformationList* chrome_processes = &process_data_[0].processes;
asvitkine6f5f3592015-01-21 20:50:37125
[email protected]f164cea2009-11-05 23:37:40126 // Collect data about Chrome/Chromium.
ellyjonescd6e449d2016-04-13 19:31:15127 for (const base::ProcessId& pid : all_pids)
asvitkine6f5f3592015-01-21 20:50:37128 CollectProcessDataForChromeProcess(child_info, pid, chrome_processes);
[email protected]f164cea2009-11-05 23:37:40129
130 // Finally return to the browser thread.
Eric Seckler8652dcd52018-09-20 10:42:28131 base::PostTaskWithTraits(
132 FROM_HERE, {BrowserThread::UI},
[email protected]24d69692011-10-21 18:26:51133 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
[email protected]f164cea2009-11-05 23:37:40134}