blob: d94000cab7b54bd72834787576fef46aea20d40a [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]24d69692011-10-21 18:26:519#include "base/bind.h"
[email protected]4f260d02010-12-23 18:35:4210#include "base/file_path.h"
[email protected]54fd1d32009-09-01 00:12:5811#include "base/file_version_info.h"
12#include "base/string_util.h"
[email protected]0211f57e2010-08-27 20:28:4213#include "base/utf_string_conversions.h"
[email protected]b90d7e802011-01-09 16:32:2014#include "base/win/scoped_handle.h"
[email protected]1e67c2b2011-03-04 01:17:3715#include "base/win/windows_version.h"
[email protected]1eeb5e02010-07-20 23:02:1116#include "chrome/common/chrome_version_info.h"
[email protected]54fd1d32009-09-01 00:12:5817#include "chrome/common/url_constants.h"
[email protected]a01efd22011-03-01 00:38:3218#include "content/browser/browser_child_process_host.h"
[email protected]a01efd22011-03-01 00:38:3219#include "content/browser/renderer_host/backing_store_manager.h"
20#include "content/browser/renderer_host/render_process_host.h"
21#include "content/browser/tab_contents/navigation_entry.h"
[email protected]c38831a12011-10-28 12:44:4922#include "content/public/browser/browser_thread.h"
[email protected]54fd1d32009-09-01 00:12:5823#include "grit/chromium_strings.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.
29enum {
30 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
39} BrowserProcess;
40
[email protected]6fad2632009-11-02 05:59:3741MemoryDetails::MemoryDetails() {
[email protected]54fd1d32009-09-01 00:12:5842 static const std::wstring google_browser_name =
[email protected]0f26d7b2011-01-05 19:10:4443 UTF16ToWide(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
[email protected]93aa89c72010-10-20 21:32:0444 struct {
45 const wchar_t* name;
46 const wchar_t* process_name;
47 } process_template[MAX_BROWSERS] = {
[email protected]54fd1d32009-09-01 00:12:5848 { google_browser_name.c_str(), L"chrome.exe", },
[email protected]aef8d5ae2010-03-17 22:40:5249 { google_browser_name.c_str(), L"nacl64.exe", },
[email protected]54fd1d32009-09-01 00:12:5850 { L"IE", L"iexplore.exe", },
51 { L"Firefox", L"firefox.exe", },
52 { L"Opera", L"opera.exe", },
53 { L"Safari", L"safari.exe", },
54 { L"IE (64bit)", L"iexplore.exe", },
55 { L"Konqueror", L"konqueror.exe", },
56 };
57
[email protected]93aa89c72010-10-20 21:32:0458 for (int index = 0; index < MAX_BROWSERS; ++index) {
[email protected]54fd1d32009-09-01 00:12:5859 ProcessData process;
[email protected]93aa89c72010-10-20 21:32:0460 process.name = process_template[index].name;
61 process.process_name = process_template[index].process_name;
[email protected]54fd1d32009-09-01 00:12:5862 process_data_.push_back(process);
63 }
64}
65
66ProcessData* MemoryDetails::ChromeBrowser() {
67 return &process_data_[CHROME_BROWSER];
68}
69
70void MemoryDetails::CollectProcessData(
[email protected]4df3ac62011-03-11 04:38:5271 const std::vector<ProcessMemoryInformation>& child_info) {
[email protected]f8b3ef82010-10-11 02:45:5272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]54fd1d32009-09-01 00:12:5873
74 // Clear old data.
[email protected]93aa89c72010-10-20 21:32:0475 for (unsigned int index = 0; index < process_data_.size(); index++)
[email protected]54fd1d32009-09-01 00:12:5876 process_data_[index].processes.clear();
77
[email protected]f481221192011-04-07 22:15:3478 base::win::OSInfo::WindowsArchitecture windows_architecture =
79 base::win::OSInfo::GetInstance()->architecture();
[email protected]54fd1d32009-09-01 00:12:5880
[email protected]b90d7e802011-01-09 16:32:2081 base::win::ScopedHandle snapshot(
82 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
[email protected]54fd1d32009-09-01 00:12:5883 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
84 if (!snapshot.Get()) {
85 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
86 return;
87 }
88 if (!::Process32First(snapshot, &process_entry)) {
89 LOG(ERROR) << "Process32First failed: " << GetLastError();
90 return;
91 }
92 do {
[email protected]a4dc33f2009-10-20 15:09:5593 base::ProcessId pid = process_entry.th32ProcessID;
[email protected]1e67c2b2011-03-04 01:17:3794 base::win::ScopedHandle process_handle(::OpenProcess(
[email protected]54fd1d32009-09-01 00:12:5895 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
[email protected]1e67c2b2011-03-04 01:17:3796 if (!process_handle.Get())
[email protected]54fd1d32009-09-01 00:12:5897 continue;
[email protected]af67f202011-03-04 19:12:2998 bool is_64bit_process =
[email protected]f481221192011-04-07 22:15:3499 ((windows_architecture == base::win::OSInfo::X64_ARCHITECTURE) ||
100 (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)) &&
101 (base::win::OSInfo::GetWOW64StatusForProcess(process_handle) ==
102 base::win::OSInfo::WOW64_DISABLED);
[email protected]93aa89c72010-10-20 21:32:04103 for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) {
[email protected]54fd1d32009-09-01 00:12:58104 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;
[email protected]1e67c2b2011-03-04 01:17:37118 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(process_handle));
[email protected]54fd1d32009-09-01 00:12:58119 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;
[email protected]30c91802010-12-18 00:40:17126 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 }
[email protected]1e67c2b2011-03-04 01:17:37137 } else if (GetModuleFileNameEx(process_handle, NULL, name,
138 MAX_PATH - 1)) {
[email protected]54fd1d32009-09-01 00:12:58139 std::wstring str_name(name);
140 scoped_ptr<FileVersionInfo> version_info(
[email protected]4f260d02010-12-23 18:35:42141 FileVersionInfo::CreateFileVersionInfo(FilePath(str_name)));
[email protected]54fd1d32009-09-01 00:12:58142 if (version_info != NULL) {
143 info.version = version_info->product_version();
144 info.product_name = version_info->product_name();
145 }
146 }
147
148 // Add the process info to our list.
[email protected]aef8d5ae2010-03-17 22:40:52149 if (index2 == CHROME_NACL_PROCESS) {
150 // Add NaCl processes to Chrome's list
151 process_data_[CHROME_BROWSER].processes.push_back(info);
152 } else {
153 process_data_[index2].processes.push_back(info);
154 }
[email protected]54fd1d32009-09-01 00:12:58155 break;
156 }
157 } while (::Process32Next(snapshot, &process_entry));
158
159 // Finally return to the browser thread.
[email protected]f8b3ef82010-10-11 02:45:52160 BrowserThread::PostTask(
161 BrowserThread::UI, FROM_HERE,
[email protected]24d69692011-10-21 18:26:51162 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
[email protected]54fd1d32009-09-01 00:12:58163}