blob: 84497bac71f3005f79a9c555ec2ecc3cbdaf85ba [file] [log] [blame]
[email protected]54fd1d32009-09-01 00:12:581// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// 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#include <psapi.h>
7
8#include "app/l10n_util.h"
9#include "base/file_version_info.h"
10#include "base/string_util.h"
[email protected]bcff05a2010-04-14 01:46:4311#include "chrome/app/chrome_version_info.h"
[email protected]dcddcdb02010-02-23 09:10:1312#include "chrome/browser/child_process_host.h"
[email protected]54fd1d32009-09-01 00:12:5813#include "chrome/browser/chrome_thread.h"
14#include "chrome/browser/renderer_host/backing_store_manager.h"
15#include "chrome/browser/renderer_host/render_process_host.h"
16#include "chrome/browser/tab_contents/navigation_entry.h"
17#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]54fd1d32009-09-01 00:12:5818#include "chrome/common/url_constants.h"
19#include "grit/chromium_strings.h"
20
21// Known browsers which we collect details for.
22enum {
23 CHROME_BROWSER = 0,
[email protected]aef8d5ae2010-03-17 22:40:5224 CHROME_NACL_PROCESS,
[email protected]54fd1d32009-09-01 00:12:5825 IE_BROWSER,
26 FIREFOX_BROWSER,
27 OPERA_BROWSER,
28 SAFARI_BROWSER,
29 IE_64BIT_BROWSER,
30 KONQUEROR_BROWSER,
31 MAX_BROWSERS
32} BrowserProcess;
33
34// Template of static data we use for finding browser process information.
35// These entries must match the ordering for MemoryDetails::BrowserProcess.
36static ProcessData g_process_template[MAX_BROWSERS];
37
[email protected]6fad2632009-11-02 05:59:3738MemoryDetails::MemoryDetails() {
[email protected]54fd1d32009-09-01 00:12:5839 static const std::wstring google_browser_name =
40 l10n_util::GetString(IDS_PRODUCT_NAME);
41 ProcessData g_process_template[MAX_BROWSERS] = {
42 { google_browser_name.c_str(), L"chrome.exe", },
[email protected]aef8d5ae2010-03-17 22:40:5243 { google_browser_name.c_str(), L"nacl64.exe", },
[email protected]54fd1d32009-09-01 00:12:5844 { L"IE", L"iexplore.exe", },
45 { L"Firefox", L"firefox.exe", },
46 { L"Opera", L"opera.exe", },
47 { L"Safari", L"safari.exe", },
48 { L"IE (64bit)", L"iexplore.exe", },
49 { L"Konqueror", L"konqueror.exe", },
50 };
51
52 for (int index = 0; index < arraysize(g_process_template); ++index) {
53 ProcessData process;
54 process.name = g_process_template[index].name;
55 process.process_name = g_process_template[index].process_name;
56 process_data_.push_back(process);
57 }
58}
59
60ProcessData* MemoryDetails::ChromeBrowser() {
61 return &process_data_[CHROME_BROWSER];
62}
63
64void MemoryDetails::CollectProcessData(
65 std::vector<ProcessMemoryInformation> child_info) {
[email protected]d85cf072009-10-27 03:59:3166 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
[email protected]54fd1d32009-09-01 00:12:5867
68 // Clear old data.
69 for (int index = 0; index < arraysize(g_process_template); index++)
70 process_data_[index].processes.clear();
71
72 SYSTEM_INFO system_info;
73 GetNativeSystemInfo(&system_info);
74 bool is_64bit_os =
75 system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
76
77 ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
78 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
79 if (!snapshot.Get()) {
80 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
81 return;
82 }
83 if (!::Process32First(snapshot, &process_entry)) {
84 LOG(ERROR) << "Process32First failed: " << GetLastError();
85 return;
86 }
87 do {
[email protected]a4dc33f2009-10-20 15:09:5588 base::ProcessId pid = process_entry.th32ProcessID;
[email protected]54fd1d32009-09-01 00:12:5889 ScopedHandle handle(::OpenProcess(
90 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
91 if (!handle.Get())
92 continue;
93 bool is_64bit_process = false;
94 // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS.
95 // We need to check if the real OS is 64bit.
96 if (is_64bit_os) {
97 BOOL is_wow64 = FALSE;
98 // IsWow64Process() is supported by Windows XP SP2 or later.
99 IsWow64Process(handle, &is_wow64);
100 is_64bit_process = !is_wow64;
101 }
102 for (int index2 = 0; index2 < arraysize(g_process_template); index2++) {
103 if (_wcsicmp(process_data_[index2].process_name.c_str(),
[email protected]b6128aa2010-04-29 17:44:42104 process_entry.szExeFile) != 0)
[email protected]54fd1d32009-09-01 00:12:58105 continue;
106 if (index2 == IE_BROWSER && is_64bit_process)
107 continue; // Should use IE_64BIT_BROWSER
108 // Get Memory Information.
109 ProcessMemoryInformation info;
110 info.pid = pid;
111 if (info.pid == GetCurrentProcessId())
112 info.type = ChildProcessInfo::BROWSER_PROCESS;
113 else
114 info.type = ChildProcessInfo::UNKNOWN_PROCESS;
115
116 scoped_ptr<base::ProcessMetrics> metrics;
117 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
118 metrics->GetCommittedKBytes(&info.committed);
119 metrics->GetWorkingSetKBytes(&info.working_set);
120
121 // Get Version Information.
122 TCHAR name[MAX_PATH];
[email protected]aef8d5ae2010-03-17 22:40:52123 if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
[email protected]54fd1d32009-09-01 00:12:58124 scoped_ptr<FileVersionInfo> version_info(
[email protected]bcff05a2010-04-14 01:46:43125 chrome_app::GetChromeVersionInfo());
[email protected]54fd1d32009-09-01 00:12:58126 if (version_info != NULL)
127 info.version = version_info->file_version();
128 // Check if this is one of the child processes whose data we collected
129 // on the IO thread, and if so copy over that data.
130 for (size_t child = 0; child < child_info.size(); child++) {
131 if (child_info[child].pid != info.pid)
132 continue;
133 info.titles = child_info[child].titles;
134 info.type = child_info[child].type;
135 break;
136 }
137 } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) {
138 std::wstring str_name(name);
139 scoped_ptr<FileVersionInfo> version_info(
140 FileVersionInfo::CreateFileVersionInfo(str_name));
141 if (version_info != NULL) {
142 info.version = version_info->product_version();
143 info.product_name = version_info->product_name();
144 }
145 }
146
147 // Add the process info to our list.
[email protected]aef8d5ae2010-03-17 22:40:52148 if (index2 == CHROME_NACL_PROCESS) {
149 // Add NaCl processes to Chrome's list
150 process_data_[CHROME_BROWSER].processes.push_back(info);
151 } else {
152 process_data_[index2].processes.push_back(info);
153 }
[email protected]54fd1d32009-09-01 00:12:58154 break;
155 }
156 } while (::Process32Next(snapshot, &process_entry));
157
158 // Finally return to the browser thread.
[email protected]6fad2632009-11-02 05:59:37159 ChromeThread::PostTask(
160 ChromeThread::UI, FROM_HERE,
[email protected]54fd1d32009-09-01 00:12:58161 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
162}