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"
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/url_constants.h"
19 #include "chrome/grit/chromium_strings.h"
20 #include "components/version_info/version_info.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.
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
);
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
) {
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(
76 const std::vector
<ProcessMemoryInformation
>& child_info
) {
77 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
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();
93 if (!::Process32First(snapshot
.Get(), &process_entry
)) {
94 LOG(ERROR
) << "Process32First failed: " << GetLastError();
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())
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)
114 if (index2
== IE_BROWSER
&& is_64bit_process
)
115 continue; // Should use IE_64BIT_BROWSER
116 // Get Memory Information.
117 ProcessMemoryInformation info
;
119 if (info
.pid
== GetCurrentProcessId())
120 info
.process_type
= content::PROCESS_TYPE_BROWSER
;
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 info
.version
= base::ASCIIToUTF16(version_info::GetVersionNumber());
134 // Check if this is one of the child processes whose data we collected
135 // on the IO thread, and if so copy over that data.
136 for (size_t child
= 0; child
< child_info
.size(); child
++) {
137 if (child_info
[child
].pid
!= info
.pid
)
139 info
.titles
= child_info
[child
].titles
;
140 info
.process_type
= child_info
[child
].process_type
;
143 } else if (GetModuleFileNameEx(process_handle
.Get(), NULL
, name
,
145 std::wstring
str_name(name
);
146 scoped_ptr
<FileVersionInfo
> version_info(
147 FileVersionInfo::CreateFileVersionInfo(base::FilePath(str_name
)));
148 if (version_info
!= NULL
) {
149 info
.version
= version_info
->product_version();
150 info
.product_name
= version_info
->product_name();
154 // Add the process info to our list.
155 if (index2
== CHROME_NACL_PROCESS
) {
156 // Add NaCl processes to Chrome's list
157 process_data_
[CHROME_BROWSER
].processes
.push_back(info
);
159 process_data_
[index2
].processes
.push_back(info
);
163 } while (::Process32Next(snapshot
.Get(), &process_entry
));
165 // Finally return to the browser thread.
166 BrowserThread::PostTask(
167 BrowserThread::UI
, FROM_HERE
,
168 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread
, this));