blob: d49a852935380bd6f5950f3dd6e94223f1de4881 [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"
[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]d27893f62010-07-03 05:47:4213#include "chrome/browser/browser_child_process_host.h"
[email protected]017a7a112010-10-12 16:38:2714#include "chrome/browser/browser_thread.h"
[email protected]54fd1d32009-09-01 00:12:5815#include "chrome/browser/renderer_host/backing_store_manager.h"
16#include "chrome/browser/renderer_host/render_process_host.h"
17#include "chrome/browser/tab_contents/navigation_entry.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
[email protected]6fad2632009-11-02 05:59:3735MemoryDetails::MemoryDetails() {
[email protected]54fd1d32009-09-01 00:12:5836 static const std::wstring google_browser_name =
[email protected]0f26d7b2011-01-05 19:10:4437 UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
[email protected]93aa89c72010-10-20 21:32:0438 struct {
39 const wchar_t* name;
40 const wchar_t* process_name;
41 } process_template[MAX_BROWSERS] = {
[email protected]54fd1d32009-09-01 00:12:5842 { 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
[email protected]93aa89c72010-10-20 21:32:0452 for (int index = 0; index < MAX_BROWSERS; ++index) {
[email protected]54fd1d32009-09-01 00:12:5853 ProcessData process;
[email protected]93aa89c72010-10-20 21:32:0454 process.name = process_template[index].name;
55 process.process_name = process_template[index].process_name;
[email protected]54fd1d32009-09-01 00:12:5856 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]f8b3ef82010-10-11 02:45:5266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]54fd1d32009-09-01 00:12:5867
68 // Clear old data.
[email protected]93aa89c72010-10-20 21:32:0469 for (unsigned int index = 0; index < process_data_.size(); index++)
[email protected]54fd1d32009-09-01 00:12:5870 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 }
[email protected]93aa89c72010-10-20 21:32:04102 for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) {
[email protected]54fd1d32009-09-01 00:12:58103 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]0211f57e2010-08-27 20:28:42124 chrome::VersionInfo version_info;
[email protected]30c91802010-12-18 00:40:17125 if (version_info.is_valid())
126 info.version = ASCIIToWide(version_info.Version());
[email protected]54fd1d32009-09-01 00:12:58127 // Check if this is one of the child processes whose data we collected
128 // on the IO thread, and if so copy over that data.
129 for (size_t child = 0; child < child_info.size(); child++) {
130 if (child_info[child].pid != info.pid)
131 continue;
132 info.titles = child_info[child].titles;
133 info.type = child_info[child].type;
134 break;
135 }
136 } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) {
137 std::wstring str_name(name);
138 scoped_ptr<FileVersionInfo> version_info(
[email protected]4f260d02010-12-23 18:35:42139 FileVersionInfo::CreateFileVersionInfo(FilePath(str_name)));
[email protected]54fd1d32009-09-01 00:12:58140 if (version_info != NULL) {
141 info.version = version_info->product_version();
142 info.product_name = version_info->product_name();
143 }
144 }
145
146 // Add the process info to our list.
[email protected]aef8d5ae2010-03-17 22:40:52147 if (index2 == CHROME_NACL_PROCESS) {
148 // Add NaCl processes to Chrome's list
149 process_data_[CHROME_BROWSER].processes.push_back(info);
150 } else {
151 process_data_[index2].processes.push_back(info);
152 }
[email protected]54fd1d32009-09-01 00:12:58153 break;
154 }
155 } while (::Process32Next(snapshot, &process_entry));
156
157 // Finally return to the browser thread.
[email protected]f8b3ef82010-10-11 02:45:52158 BrowserThread::PostTask(
159 BrowserThread::UI, FROM_HERE,
[email protected]54fd1d32009-09-01 00:12:58160 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
161}