blob: 23a1ed93159d63a83c775f9a1c5d20c9f7b09ecf [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
[email protected]f164cea2009-11-05 23:37:409#include <set>
10#include <string>
11
[email protected]24d69692011-10-21 18:26:5112#include "base/bind.h"
[email protected]f164cea2009-11-05 23:37:4013#include "base/file_version_info.h"
[email protected]57999812013-02-24 05:40:5214#include "base/files/file_path.h"
avi69fed022014-12-21 01:02:5215#include "base/mac/foundation_util.h"
dcheng6003e0b2016-04-09 18:42:3416#include "base/memory/scoped_ptr.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"
[email protected]34b99632011-01-01 01:01:0620#include "base/threading/thread.h"
[email protected]f164cea2009-11-05 23:37:4021#include "chrome/common/chrome_constants.h"
22#include "chrome/common/url_constants.h"
[email protected]af39f002014-08-22 10:18:1823#include "chrome/grit/chromium_strings.h"
sdefresne9fb67692015-08-03 18:48:2224#include "components/version_info/version_info.h"
asvitkine58409e4c2015-01-15 01:25:4525#include "content/public/browser/browser_child_process_host.h"
[email protected]c38831a12011-10-28 12:44:4926#include "content/public/browser/browser_thread.h"
[email protected]bd5d6cf2011-12-01 00:39:1227#include "content/public/common/process_type.h"
[email protected]c051a1b2011-01-21 23:30:1728#include "ui/base/l10n/l10n_util.h"
[email protected]f164cea2009-11-05 23:37:4029
[email protected]631bb742011-11-02 11:29:3930using content::BrowserThread;
31
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
50 // Check if this is one of the child processes whose data was already
51 // collected and exists in |child_data|.
52 for (const ProcessMemoryInformation& child : child_info) {
53 if (child.pid == info.pid) {
54 info.titles = child.titles;
55 info.process_type = child.process_type;
56 break;
57 }
58 }
59
60 scoped_ptr<base::ProcessMetrics> metrics;
61 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(
62 pid, content::BrowserChildProcessHost::GetPortProvider()));
asvitkine57e53d3152015-01-23 01:42:5063 metrics->GetCommittedAndWorkingSetKBytes(&info.committed, &info.working_set);
asvitkine6f5f3592015-01-21 20:50:3764
65 processes->push_back(info);
66}
67
asvitkine6f5f3592015-01-21 20:50:3768} // namespace
[email protected]f164cea2009-11-05 23:37:4069
asvitkine89406d1f2015-01-17 06:57:1070MemoryDetails::MemoryDetails() {
asvitkine58409e4c2015-01-15 01:25:4571 const base::FilePath browser_process_path =
72 base::GetProcessExecutablePath(base::GetCurrentProcessHandle());
asvitkine58409e4c2015-01-15 01:25:4573
ellyjonescd6e449d2016-04-13 19:31:1574 ProcessData process;
75 process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
76 process.process_name =
77 base::UTF8ToUTF16(browser_process_path.BaseName().value());
78 process_data_.push_back(process);
[email protected]f164cea2009-11-05 23:37:4079}
80
81ProcessData* MemoryDetails::ChromeBrowser() {
ellyjonescd6e449d2016-04-13 19:31:1582 return &process_data_[0];
[email protected]f164cea2009-11-05 23:37:4083}
84
85void MemoryDetails::CollectProcessData(
[email protected]4df3ac62011-03-11 04:38:5286 const std::vector<ProcessMemoryInformation>& child_info) {
ellyjonescd6e449d2016-04-13 19:31:1587 // TODO(ellyjones): Does this still need to be run in the blocking pool?
88 // It used to need to be because it ran /bin/ps, but it might not need to any
89 // more.
hashimotoa8ea28d2015-04-11 02:50:4890 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
[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,
116 NULL);
117 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.
[email protected]f8b3ef82010-10-11 02:45:52129 BrowserThread::PostTask(
130 BrowserThread::UI, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51131 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
[email protected]f164cea2009-11-05 23:37:40132}