blob: e0957bc589b81329ff616929e763bdf745b1980c [file] [log] [blame]
[email protected]4306df72012-04-20 18:58:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]54fd1d32009-09-01 00:12:582// 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"
[email protected]b90d7e802011-01-09 16:32:206
[email protected]54fd1d32009-09-01 00:12:587#include <psapi.h>
avi6846aef2015-12-26 01:09:388#include <stddef.h>
[email protected]d09a4ce1c2013-07-24 17:37:029#include <TlHelp32.h>
[email protected]54fd1d32009-09-01 00:12:5810
[email protected]24d69692011-10-21 18:26:5111#include "base/bind.h"
[email protected]54fd1d32009-09-01 00:12:5812#include "base/file_version_info.h"
[email protected]57999812013-02-24 05:40:5213#include "base/files/file_path.h"
asvitkine58409e4c2015-01-15 01:25:4514#include "base/path_service.h"
[email protected]f9b294362013-06-10 20:22:3115#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1816#include "base/strings/utf_string_conversions.h"
[email protected]b90d7e802011-01-09 16:32:2017#include "base/win/scoped_handle.h"
[email protected]1e67c2b2011-03-04 01:17:3718#include "base/win/windows_version.h"
[email protected]54fd1d32009-09-01 00:12:5819#include "chrome/common/url_constants.h"
[email protected]af39f002014-08-22 10:18:1820#include "chrome/grit/chromium_strings.h"
sdefresne9fb67692015-08-03 18:48:2221#include "components/version_info/version_info.h"
[email protected]c38831a12011-10-28 12:44:4922#include "content/public/browser/browser_thread.h"
[email protected]bd5d6cf2011-12-01 00:39:1223#include "content/public/common/process_type.h"
[email protected]c051a1b2011-01-21 23:30:1724#include "ui/base/l10n/l10n_util.h"
[email protected]54fd1d32009-09-01 00:12:5825
[email protected]631bb742011-11-02 11:29:3926using content::BrowserThread;
27
[email protected]54fd1d32009-09-01 00:12:5828// Known browsers which we collect details for.
mgiuca88867d32015-07-08 04:08:2429enum BrowserProcess {
[email protected]54fd1d32009-09-01 00:12:5830 CHROME_BROWSER = 0,
[email protected]aef8d5ae2010-03-17 22:40:5231 CHROME_NACL_PROCESS,
[email protected]54fd1d32009-09-01 00:12:5832 IE_BROWSER,
33 FIREFOX_BROWSER,
34 OPERA_BROWSER,
35 SAFARI_BROWSER,
36 IE_64BIT_BROWSER,
37 KONQUEROR_BROWSER,
38 MAX_BROWSERS
mgiuca88867d32015-07-08 04:08:2439};
[email protected]54fd1d32009-09-01 00:12:5840
asvitkine89406d1f2015-01-17 06:57:1041MemoryDetails::MemoryDetails() {
asvitkine58409e4c2015-01-15 01:25:4542 base::FilePath browser_process_path;
43 PathService::Get(base::FILE_EXE, &browser_process_path);
44 const base::string16 browser_process_name =
45 browser_process_path.BaseName().value();
46 const base::string16 google_browser_name =
[email protected]299e3d002014-06-03 08:46:4947 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
asvitkine58409e4c2015-01-15 01:25:4548
[email protected]93aa89c72010-10-20 21:32:0449 struct {
50 const wchar_t* name;
51 const wchar_t* process_name;
52 } process_template[MAX_BROWSERS] = {
asvitkine58409e4c2015-01-15 01:25:4553 { google_browser_name.c_str(), browser_process_name.c_str(), },
[email protected]aef8d5ae2010-03-17 22:40:5254 { google_browser_name.c_str(), L"nacl64.exe", },
[email protected]54fd1d32009-09-01 00:12:5855 { L"IE", L"iexplore.exe", },
56 { L"Firefox", L"firefox.exe", },
57 { L"Opera", L"opera.exe", },
58 { L"Safari", L"safari.exe", },
59 { L"IE (64bit)", L"iexplore.exe", },
60 { L"Konqueror", L"konqueror.exe", },
61 };
62
[email protected]93aa89c72010-10-20 21:32:0463 for (int index = 0; index < MAX_BROWSERS; ++index) {
[email protected]54fd1d32009-09-01 00:12:5864 ProcessData process;
[email protected]93aa89c72010-10-20 21:32:0465 process.name = process_template[index].name;
66 process.process_name = process_template[index].process_name;
[email protected]54fd1d32009-09-01 00:12:5867 process_data_.push_back(process);
68 }
69}
70
71ProcessData* MemoryDetails::ChromeBrowser() {
72 return &process_data_[CHROME_BROWSER];
73}
74
75void MemoryDetails::CollectProcessData(
asvitkine6f5f3592015-01-21 20:50:3776 CollectionMode mode,
[email protected]4df3ac62011-03-11 04:38:5277 const std::vector<ProcessMemoryInformation>& child_info) {
hashimotoa8ea28d2015-04-11 02:50:4878 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
[email protected]54fd1d32009-09-01 00:12:5879
80 // Clear old data.
[email protected]93aa89c72010-10-20 21:32:0481 for (unsigned int index = 0; index < process_data_.size(); index++)
[email protected]54fd1d32009-09-01 00:12:5882 process_data_[index].processes.clear();
83
[email protected]f481221192011-04-07 22:15:3484 base::win::OSInfo::WindowsArchitecture windows_architecture =
85 base::win::OSInfo::GetInstance()->architecture();
[email protected]54fd1d32009-09-01 00:12:5886
[email protected]b90d7e802011-01-09 16:32:2087 base::win::ScopedHandle snapshot(
88 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
[email protected]54fd1d32009-09-01 00:12:5889 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
90 if (!snapshot.Get()) {
91 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
92 return;
93 }
rvargasd7743ba2014-09-25 01:35:2894 if (!::Process32First(snapshot.Get(), &process_entry)) {
[email protected]54fd1d32009-09-01 00:12:5895 LOG(ERROR) << "Process32First failed: " << GetLastError();
96 return;
97 }
98 do {
[email protected]a4dc33f2009-10-20 15:09:5599 base::ProcessId pid = process_entry.th32ProcessID;
[email protected]1e67c2b2011-03-04 01:17:37100 base::win::ScopedHandle process_handle(::OpenProcess(
[email protected]54fd1d32009-09-01 00:12:58101 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
rvargasd7743ba2014-09-25 01:35:28102 if (!process_handle.IsValid())
[email protected]54fd1d32009-09-01 00:12:58103 continue;
[email protected]af67f202011-03-04 19:12:29104 bool is_64bit_process =
[email protected]f481221192011-04-07 22:15:34105 ((windows_architecture == base::win::OSInfo::X64_ARCHITECTURE) ||
106 (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)) &&
rvargasd7743ba2014-09-25 01:35:28107 (base::win::OSInfo::GetWOW64StatusForProcess(process_handle.Get()) ==
[email protected]f481221192011-04-07 22:15:34108 base::win::OSInfo::WOW64_DISABLED);
asvitkine6f5f3592015-01-21 20:50:37109 const size_t browser_list_size =
110 (mode == FROM_CHROME_ONLY ? 1 : process_data_.size());
111 for (size_t index2 = 0; index2 < browser_list_size; ++index2) {
[email protected]54fd1d32009-09-01 00:12:58112 if (_wcsicmp(process_data_[index2].process_name.c_str(),
[email protected]b6128aa2010-04-29 17:44:42113 process_entry.szExeFile) != 0)
[email protected]54fd1d32009-09-01 00:12:58114 continue;
115 if (index2 == IE_BROWSER && is_64bit_process)
116 continue; // Should use IE_64BIT_BROWSER
117 // Get Memory Information.
118 ProcessMemoryInformation info;
119 info.pid = pid;
120 if (info.pid == GetCurrentProcessId())
[email protected]f3b357692013-03-22 05:16:13121 info.process_type = content::PROCESS_TYPE_BROWSER;
[email protected]54fd1d32009-09-01 00:12:58122 else
[email protected]f3b357692013-03-22 05:16:13123 info.process_type = content::PROCESS_TYPE_UNKNOWN;
[email protected]54fd1d32009-09-01 00:12:58124
125 scoped_ptr<base::ProcessMetrics> metrics;
rvargasd7743ba2014-09-25 01:35:28126 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(
127 process_handle.Get()));
[email protected]54fd1d32009-09-01 00:12:58128 metrics->GetCommittedKBytes(&info.committed);
129 metrics->GetWorkingSetKBytes(&info.working_set);
130
131 // Get Version Information.
132 TCHAR name[MAX_PATH];
[email protected]aef8d5ae2010-03-17 22:40:52133 if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
sdefresne9fb67692015-08-03 18:48:22134 info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
[email protected]54fd1d32009-09-01 00:12:58135 // Check if this is one of the child processes whose data we collected
136 // on the IO thread, and if so copy over that data.
137 for (size_t child = 0; child < child_info.size(); child++) {
138 if (child_info[child].pid != info.pid)
139 continue;
140 info.titles = child_info[child].titles;
[email protected]f3b357692013-03-22 05:16:13141 info.process_type = child_info[child].process_type;
[email protected]54fd1d32009-09-01 00:12:58142 break;
143 }
rvargasd7743ba2014-09-25 01:35:28144 } else if (GetModuleFileNameEx(process_handle.Get(), NULL, name,
[email protected]1e67c2b2011-03-04 01:17:37145 MAX_PATH - 1)) {
[email protected]54fd1d32009-09-01 00:12:58146 std::wstring str_name(name);
147 scoped_ptr<FileVersionInfo> version_info(
[email protected]650b2d52013-02-10 03:41:45148 FileVersionInfo::CreateFileVersionInfo(base::FilePath(str_name)));
[email protected]54fd1d32009-09-01 00:12:58149 if (version_info != NULL) {
150 info.version = version_info->product_version();
151 info.product_name = version_info->product_name();
152 }
153 }
154
155 // Add the process info to our list.
[email protected]aef8d5ae2010-03-17 22:40:52156 if (index2 == CHROME_NACL_PROCESS) {
157 // Add NaCl processes to Chrome's list
158 process_data_[CHROME_BROWSER].processes.push_back(info);
159 } else {
160 process_data_[index2].processes.push_back(info);
161 }
[email protected]54fd1d32009-09-01 00:12:58162 break;
163 }
rvargasd7743ba2014-09-25 01:35:28164 } while (::Process32Next(snapshot.Get(), &process_entry));
[email protected]54fd1d32009-09-01 00:12:58165
166 // Finally return to the browser thread.
[email protected]f8b3ef82010-10-11 02:45:52167 BrowserThread::PostTask(
168 BrowserThread::UI, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51169 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
[email protected]54fd1d32009-09-01 00:12:58170}