blob: 1e6d98597ccc8be3888602be4d970e9e5ce3584e [file] [log] [blame]
[email protected]1eeb5e02010-07-20 23:02:111// Copyright (c) 2010 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"
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]0211f57e2010-08-27 20:28:4211#include "base/utf_string_conversions.h"
[email protected]d27893f62010-07-03 05:47:4212#include "chrome/browser/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]1eeb5e02010-07-20 23:02:1118#include "chrome/common/chrome_version_info.h"
[email protected]54fd1d32009-09-01 00:12:5819#include "chrome/common/url_constants.h"
20#include "grit/chromium_strings.h"
21
22// Known browsers which we collect details for.
23enum {
24 CHROME_BROWSER = 0,
[email protected]aef8d5ae2010-03-17 22:40:5225 CHROME_NACL_PROCESS,
[email protected]54fd1d32009-09-01 00:12:5826 IE_BROWSER,
27 FIREFOX_BROWSER,
28 OPERA_BROWSER,
29 SAFARI_BROWSER,
30 IE_64BIT_BROWSER,
31 KONQUEROR_BROWSER,
32 MAX_BROWSERS
33} BrowserProcess;
34
35// Template of static data we use for finding browser process information.
36// These entries must match the ordering for MemoryDetails::BrowserProcess.
37static ProcessData g_process_template[MAX_BROWSERS];
38
[email protected]6fad2632009-11-02 05:59:3739MemoryDetails::MemoryDetails() {
[email protected]54fd1d32009-09-01 00:12:5840 static const std::wstring google_browser_name =
41 l10n_util::GetString(IDS_PRODUCT_NAME);
42 ProcessData g_process_template[MAX_BROWSERS] = {
43 { google_browser_name.c_str(), L"chrome.exe", },
[email protected]aef8d5ae2010-03-17 22:40:5244 { google_browser_name.c_str(), L"nacl64.exe", },
[email protected]54fd1d32009-09-01 00:12:5845 { L"IE", L"iexplore.exe", },
46 { L"Firefox", L"firefox.exe", },
47 { L"Opera", L"opera.exe", },
48 { L"Safari", L"safari.exe", },
49 { L"IE (64bit)", L"iexplore.exe", },
50 { L"Konqueror", L"konqueror.exe", },
51 };
52
53 for (int index = 0; index < arraysize(g_process_template); ++index) {
54 ProcessData process;
55 process.name = g_process_template[index].name;
56 process.process_name = g_process_template[index].process_name;
57 process_data_.push_back(process);
58 }
59}
60
61ProcessData* MemoryDetails::ChromeBrowser() {
62 return &process_data_[CHROME_BROWSER];
63}
64
65void MemoryDetails::CollectProcessData(
66 std::vector<ProcessMemoryInformation> child_info) {
[email protected]d85cf072009-10-27 03:59:3167 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
[email protected]54fd1d32009-09-01 00:12:5868
69 // Clear old data.
70 for (int index = 0; index < arraysize(g_process_template); index++)
71 process_data_[index].processes.clear();
72
73 SYSTEM_INFO system_info;
74 GetNativeSystemInfo(&system_info);
75 bool is_64bit_os =
76 system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
77
78 ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
79 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
80 if (!snapshot.Get()) {
81 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
82 return;
83 }
84 if (!::Process32First(snapshot, &process_entry)) {
85 LOG(ERROR) << "Process32First failed: " << GetLastError();
86 return;
87 }
88 do {
[email protected]a4dc33f2009-10-20 15:09:5589 base::ProcessId pid = process_entry.th32ProcessID;
[email protected]54fd1d32009-09-01 00:12:5890 ScopedHandle handle(::OpenProcess(
91 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
92 if (!handle.Get())
93 continue;
94 bool is_64bit_process = false;
95 // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS.
96 // We need to check if the real OS is 64bit.
97 if (is_64bit_os) {
98 BOOL is_wow64 = FALSE;
99 // IsWow64Process() is supported by Windows XP SP2 or later.
100 IsWow64Process(handle, &is_wow64);
101 is_64bit_process = !is_wow64;
102 }
103 for (int index2 = 0; index2 < arraysize(g_process_template); index2++) {
104 if (_wcsicmp(process_data_[index2].process_name.c_str(),
[email protected]b6128aa2010-04-29 17:44:42105 process_entry.szExeFile) != 0)
[email protected]54fd1d32009-09-01 00:12:58106 continue;
107 if (index2 == IE_BROWSER && is_64bit_process)
108 continue; // Should use IE_64BIT_BROWSER
109 // Get Memory Information.
110 ProcessMemoryInformation info;
111 info.pid = pid;
112 if (info.pid == GetCurrentProcessId())
113 info.type = ChildProcessInfo::BROWSER_PROCESS;
114 else
115 info.type = ChildProcessInfo::UNKNOWN_PROCESS;
116
117 scoped_ptr<base::ProcessMetrics> metrics;
118 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
119 metrics->GetCommittedKBytes(&info.committed);
120 metrics->GetWorkingSetKBytes(&info.working_set);
121
122 // Get Version Information.
123 TCHAR name[MAX_PATH];
[email protected]aef8d5ae2010-03-17 22:40:52124 if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
[email protected]0211f57e2010-08-27 20:28:42125 chrome::VersionInfo version_info;
126 if (version_info.is_valid())
127 info.version = ASCIIToWide(version_info.Version());
[email protected]54fd1d32009-09-01 00:12:58128 // 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}