blob: 697f6089d3e48d0b31721a495d90f5ca341112b3 [file] [log] [blame]
[email protected]b90d7e802011-01-09 16:32:201// Copyright (c) 2011 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>
8
[email protected]4f260d02010-12-23 18:35:429#include "base/file_path.h"
[email protected]54fd1d32009-09-01 00:12:5810#include "base/file_version_info.h"
11#include "base/string_util.h"
[email protected]0211f57e2010-08-27 20:28:4212#include "base/utf_string_conversions.h"
[email protected]b90d7e802011-01-09 16:32:2013#include "base/win/scoped_handle.h"
[email protected]d27893f62010-07-03 05:47:4214#include "chrome/browser/browser_child_process_host.h"
[email protected]017a7a112010-10-12 16:38:2715#include "chrome/browser/browser_thread.h"
[email protected]54fd1d32009-09-01 00:12:5816#include "chrome/browser/renderer_host/backing_store_manager.h"
17#include "chrome/browser/renderer_host/render_process_host.h"
18#include "chrome/browser/tab_contents/navigation_entry.h"
[email protected]1eeb5e02010-07-20 23:02:1119#include "chrome/common/chrome_version_info.h"
[email protected]54fd1d32009-09-01 00:12:5820#include "chrome/common/url_constants.h"
21#include "grit/chromium_strings.h"
[email protected]c051a1b2011-01-21 23:30:1722#include "ui/base/l10n/l10n_util.h"
[email protected]54fd1d32009-09-01 00:12:5823
24// Known browsers which we collect details for.
25enum {
26 CHROME_BROWSER = 0,
[email protected]aef8d5ae2010-03-17 22:40:5227 CHROME_NACL_PROCESS,
[email protected]54fd1d32009-09-01 00:12:5828 IE_BROWSER,
29 FIREFOX_BROWSER,
30 OPERA_BROWSER,
31 SAFARI_BROWSER,
32 IE_64BIT_BROWSER,
33 KONQUEROR_BROWSER,
34 MAX_BROWSERS
35} BrowserProcess;
36
[email protected]6fad2632009-11-02 05:59:3737MemoryDetails::MemoryDetails() {
[email protected]54fd1d32009-09-01 00:12:5838 static const std::wstring google_browser_name =
[email protected]0f26d7b2011-01-05 19:10:4439 UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
[email protected]93aa89c72010-10-20 21:32:0440 struct {
41 const wchar_t* name;
42 const wchar_t* process_name;
43 } process_template[MAX_BROWSERS] = {
[email protected]54fd1d32009-09-01 00:12:5844 { google_browser_name.c_str(), L"chrome.exe", },
[email protected]aef8d5ae2010-03-17 22:40:5245 { google_browser_name.c_str(), L"nacl64.exe", },
[email protected]54fd1d32009-09-01 00:12:5846 { L"IE", L"iexplore.exe", },
47 { L"Firefox", L"firefox.exe", },
48 { L"Opera", L"opera.exe", },
49 { L"Safari", L"safari.exe", },
50 { L"IE (64bit)", L"iexplore.exe", },
51 { L"Konqueror", L"konqueror.exe", },
52 };
53
[email protected]93aa89c72010-10-20 21:32:0454 for (int index = 0; index < MAX_BROWSERS; ++index) {
[email protected]54fd1d32009-09-01 00:12:5855 ProcessData process;
[email protected]93aa89c72010-10-20 21:32:0456 process.name = process_template[index].name;
57 process.process_name = process_template[index].process_name;
[email protected]54fd1d32009-09-01 00:12:5858 process_data_.push_back(process);
59 }
60}
61
62ProcessData* MemoryDetails::ChromeBrowser() {
63 return &process_data_[CHROME_BROWSER];
64}
65
66void MemoryDetails::CollectProcessData(
67 std::vector<ProcessMemoryInformation> child_info) {
[email protected]f8b3ef82010-10-11 02:45:5268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]54fd1d32009-09-01 00:12:5869
70 // Clear old data.
[email protected]93aa89c72010-10-20 21:32:0471 for (unsigned int index = 0; index < process_data_.size(); index++)
[email protected]54fd1d32009-09-01 00:12:5872 process_data_[index].processes.clear();
73
74 SYSTEM_INFO system_info;
75 GetNativeSystemInfo(&system_info);
76 bool is_64bit_os =
77 system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
78
[email protected]b90d7e802011-01-09 16:32:2079 base::win::ScopedHandle snapshot(
80 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
[email protected]54fd1d32009-09-01 00:12:5881 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
82 if (!snapshot.Get()) {
83 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
84 return;
85 }
86 if (!::Process32First(snapshot, &process_entry)) {
87 LOG(ERROR) << "Process32First failed: " << GetLastError();
88 return;
89 }
90 do {
[email protected]a4dc33f2009-10-20 15:09:5591 base::ProcessId pid = process_entry.th32ProcessID;
[email protected]b90d7e802011-01-09 16:32:2092 base::win::ScopedHandle handle(::OpenProcess(
[email protected]54fd1d32009-09-01 00:12:5893 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
94 if (!handle.Get())
95 continue;
96 bool is_64bit_process = false;
97 // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS.
98 // We need to check if the real OS is 64bit.
99 if (is_64bit_os) {
100 BOOL is_wow64 = FALSE;
101 // IsWow64Process() is supported by Windows XP SP2 or later.
102 IsWow64Process(handle, &is_wow64);
103 is_64bit_process = !is_wow64;
104 }
[email protected]93aa89c72010-10-20 21:32:04105 for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) {
[email protected]54fd1d32009-09-01 00:12:58106 if (_wcsicmp(process_data_[index2].process_name.c_str(),
[email protected]b6128aa2010-04-29 17:44:42107 process_entry.szExeFile) != 0)
[email protected]54fd1d32009-09-01 00:12:58108 continue;
109 if (index2 == IE_BROWSER && is_64bit_process)
110 continue; // Should use IE_64BIT_BROWSER
111 // Get Memory Information.
112 ProcessMemoryInformation info;
113 info.pid = pid;
114 if (info.pid == GetCurrentProcessId())
115 info.type = ChildProcessInfo::BROWSER_PROCESS;
116 else
117 info.type = ChildProcessInfo::UNKNOWN_PROCESS;
118
119 scoped_ptr<base::ProcessMetrics> metrics;
120 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
121 metrics->GetCommittedKBytes(&info.committed);
122 metrics->GetWorkingSetKBytes(&info.working_set);
123
124 // Get Version Information.
125 TCHAR name[MAX_PATH];
[email protected]aef8d5ae2010-03-17 22:40:52126 if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
[email protected]0211f57e2010-08-27 20:28:42127 chrome::VersionInfo version_info;
[email protected]30c91802010-12-18 00:40:17128 if (version_info.is_valid())
129 info.version = ASCIIToWide(version_info.Version());
[email protected]54fd1d32009-09-01 00:12:58130 // Check if this is one of the child processes whose data we collected
131 // on the IO thread, and if so copy over that data.
132 for (size_t child = 0; child < child_info.size(); child++) {
133 if (child_info[child].pid != info.pid)
134 continue;
135 info.titles = child_info[child].titles;
136 info.type = child_info[child].type;
137 break;
138 }
139 } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) {
140 std::wstring str_name(name);
141 scoped_ptr<FileVersionInfo> version_info(
[email protected]4f260d02010-12-23 18:35:42142 FileVersionInfo::CreateFileVersionInfo(FilePath(str_name)));
[email protected]54fd1d32009-09-01 00:12:58143 if (version_info != NULL) {
144 info.version = version_info->product_version();
145 info.product_name = version_info->product_name();
146 }
147 }
148
149 // Add the process info to our list.
[email protected]aef8d5ae2010-03-17 22:40:52150 if (index2 == CHROME_NACL_PROCESS) {
151 // Add NaCl processes to Chrome's list
152 process_data_[CHROME_BROWSER].processes.push_back(info);
153 } else {
154 process_data_[index2].processes.push_back(info);
155 }
[email protected]54fd1d32009-09-01 00:12:58156 break;
157 }
158 } while (::Process32Next(snapshot, &process_entry));
159
160 // Finally return to the browser thread.
[email protected]f8b3ef82010-10-11 02:45:52161 BrowserThread::PostTask(
162 BrowserThread::UI, FROM_HERE,
[email protected]54fd1d32009-09-01 00:12:58163 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
164}