Upstream oodles of Chrome for Android code into Chromium.
[chromium-blink-merge.git] / chrome / browser / memory_details_win.cc
blob8cb2056b652d12a2599e4383cd7ddcd87c4094d6
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/memory_details.h"
7 #include <psapi.h>
8 #include <TlHelp32.h>
10 #include "base/bind.h"
11 #include "base/file_version_info.h"
12 #include "base/files/file_path.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/win/scoped_handle.h"
17 #include "base/win/windows_version.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/grit/chromium_strings.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/process_type.h"
23 #include "ui/base/l10n/l10n_util.h"
25 using content::BrowserThread;
27 // Known browsers which we collect details for.
28 enum {
29 CHROME_BROWSER = 0,
30 CHROME_NACL_PROCESS,
31 IE_BROWSER,
32 FIREFOX_BROWSER,
33 OPERA_BROWSER,
34 SAFARI_BROWSER,
35 IE_64BIT_BROWSER,
36 KONQUEROR_BROWSER,
37 MAX_BROWSERS
38 } BrowserProcess;
40 MemoryDetails::MemoryDetails() {
41 base::FilePath browser_process_path;
42 PathService::Get(base::FILE_EXE, &browser_process_path);
43 const base::string16 browser_process_name =
44 browser_process_path.BaseName().value();
45 const base::string16 google_browser_name =
46 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
48 struct {
49 const wchar_t* name;
50 const wchar_t* process_name;
51 } process_template[MAX_BROWSERS] = {
52 { google_browser_name.c_str(), browser_process_name.c_str(), },
53 { google_browser_name.c_str(), L"nacl64.exe", },
54 { L"IE", L"iexplore.exe", },
55 { L"Firefox", L"firefox.exe", },
56 { L"Opera", L"opera.exe", },
57 { L"Safari", L"safari.exe", },
58 { L"IE (64bit)", L"iexplore.exe", },
59 { L"Konqueror", L"konqueror.exe", },
62 for (int index = 0; index < MAX_BROWSERS; ++index) {
63 ProcessData process;
64 process.name = process_template[index].name;
65 process.process_name = process_template[index].process_name;
66 process_data_.push_back(process);
70 ProcessData* MemoryDetails::ChromeBrowser() {
71 return &process_data_[CHROME_BROWSER];
74 void MemoryDetails::CollectProcessData(
75 CollectionMode mode,
76 const std::vector<ProcessMemoryInformation>& child_info) {
77 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
79 // Clear old data.
80 for (unsigned int index = 0; index < process_data_.size(); index++)
81 process_data_[index].processes.clear();
83 base::win::OSInfo::WindowsArchitecture windows_architecture =
84 base::win::OSInfo::GetInstance()->architecture();
86 base::win::ScopedHandle snapshot(
87 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
88 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
89 if (!snapshot.Get()) {
90 LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
91 return;
93 if (!::Process32First(snapshot.Get(), &process_entry)) {
94 LOG(ERROR) << "Process32First failed: " << GetLastError();
95 return;
97 do {
98 base::ProcessId pid = process_entry.th32ProcessID;
99 base::win::ScopedHandle process_handle(::OpenProcess(
100 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
101 if (!process_handle.IsValid())
102 continue;
103 bool is_64bit_process =
104 ((windows_architecture == base::win::OSInfo::X64_ARCHITECTURE) ||
105 (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)) &&
106 (base::win::OSInfo::GetWOW64StatusForProcess(process_handle.Get()) ==
107 base::win::OSInfo::WOW64_DISABLED);
108 const size_t browser_list_size =
109 (mode == FROM_CHROME_ONLY ? 1 : process_data_.size());
110 for (size_t index2 = 0; index2 < browser_list_size; ++index2) {
111 if (_wcsicmp(process_data_[index2].process_name.c_str(),
112 process_entry.szExeFile) != 0)
113 continue;
114 if (index2 == IE_BROWSER && is_64bit_process)
115 continue; // Should use IE_64BIT_BROWSER
116 // Get Memory Information.
117 ProcessMemoryInformation info;
118 info.pid = pid;
119 if (info.pid == GetCurrentProcessId())
120 info.process_type = content::PROCESS_TYPE_BROWSER;
121 else
122 info.process_type = content::PROCESS_TYPE_UNKNOWN;
124 scoped_ptr<base::ProcessMetrics> metrics;
125 metrics.reset(base::ProcessMetrics::CreateProcessMetrics(
126 process_handle.Get()));
127 metrics->GetCommittedKBytes(&info.committed);
128 metrics->GetWorkingSetKBytes(&info.working_set);
130 // Get Version Information.
131 TCHAR name[MAX_PATH];
132 if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
133 chrome::VersionInfo version_info;
134 info.version = base::ASCIIToUTF16(version_info.Version());
135 // Check if this is one of the child processes whose data we collected
136 // on the IO thread, and if so copy over that data.
137 for (size_t child = 0; child < child_info.size(); child++) {
138 if (child_info[child].pid != info.pid)
139 continue;
140 info.titles = child_info[child].titles;
141 info.process_type = child_info[child].process_type;
142 break;
144 } else if (GetModuleFileNameEx(process_handle.Get(), NULL, name,
145 MAX_PATH - 1)) {
146 std::wstring str_name(name);
147 scoped_ptr<FileVersionInfo> version_info(
148 FileVersionInfo::CreateFileVersionInfo(base::FilePath(str_name)));
149 if (version_info != NULL) {
150 info.version = version_info->product_version();
151 info.product_name = version_info->product_name();
155 // Add the process info to our list.
156 if (index2 == CHROME_NACL_PROCESS) {
157 // Add NaCl processes to Chrome's list
158 process_data_[CHROME_BROWSER].processes.push_back(info);
159 } else {
160 process_data_[index2].processes.push_back(info);
162 break;
164 } while (::Process32Next(snapshot.Get(), &process_entry));
166 // Finally return to the browser thread.
167 BrowserThread::PostTask(
168 BrowserThread::UI, FROM_HERE,
169 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));