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 // Windows headers must come first.
12 #include "chrome/browser/memory_details.h"
16 #include "base/bind.h"
17 #include "base/file_version_info.h"
18 #include "base/files/file_path.h"
19 #include "base/path_service.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/scoped_blocking_call.h"
23 #include "base/win/scoped_handle.h"
24 #include "base/win/windows_version.h"
25 #include "chrome/common/url_constants.h"
26 #include "chrome/grit/chromium_strings.h"
27 #include "components/version_info/version_info.h"
28 #include "content/public/browser/browser_task_traits.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/common/process_type.h"
31 #include "ui/base/l10n/l10n_util.h"
33 MemoryDetails::MemoryDetails() {
34 base::FilePath browser_process_path;
35 base::PathService::Get(base::FILE_EXE, &browser_process_path);
38 process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
39 process.process_name = browser_process_path.BaseName().value();
40 process_data_.push_back(process);
43 ProcessData* MemoryDetails::ChromeBrowser() {
44 return &process_data_[0];
47 void MemoryDetails::CollectProcessData(
48 const std::vector<ProcessMemoryInformation>& child_info) {
49 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
50 base::BlockingType::MAY_BLOCK);
53 process_data_[0].processes.clear();
55 base::win::ScopedHandle snapshot(
56 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
57 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
58 if (!snapshot.Get()) {
59 LOG(ERROR) << "CreateToolhelp32Snapshot failed: " << GetLastError();
62 if (!::Process32First(snapshot.Get(), &process_entry)) {
63 LOG(ERROR) << "Process32First failed: " << GetLastError();
67 base::ProcessId pid = process_entry.th32ProcessID;
68 base::win::ScopedHandle process_handle(::OpenProcess(
69 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
70 if (!process_handle.IsValid())
72 if (_wcsicmp(process_data_[0].process_name.c_str(),
73 process_entry.szExeFile) != 0) {
77 // Get Memory Information.
78 ProcessMemoryInformation info;
80 info.process_type = pid == GetCurrentProcessId()
81 ? content::PROCESS_TYPE_BROWSER
82 : content::PROCESS_TYPE_UNKNOWN;
84 // Get Version Information.
85 info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
86 // Check if this is one of the child processes whose data we collected
87 // on the IO thread, and if so copy over that data.
88 for (const ProcessMemoryInformation& child : child_info) {
89 if (child.pid == info.pid) {
90 info.titles = child.titles;
91 info.process_type = child.process_type;
96 // Add the process info to our list.
97 process_data_[0].processes.push_back(info);
98 } while (::Process32Next(snapshot.Get(), &process_entry));
100 // Finally return to the browser thread.
101 content::GetUIThreadTaskRunner({})->PostTask(
103 base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));