1 // Copyright 2012 The Chromium Authors
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/file_version_info.h"
17 #include "base/files/file_path.h"
18 #include "base/functional/bind.h"
19 #include "base/logging.h"
20 #include "base/path_service.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/threading/scoped_blocking_call.h"
24 #include "base/win/scoped_handle.h"
25 #include "base/win/windows_version.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/grit/branded_strings.h"
28 #include "components/version_info/version_info.h"
29 #include "content/public/browser/browser_task_traits.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/common/process_type.h"
32 #include "ui/base/l10n/l10n_util.h"
34 MemoryDetails::MemoryDetails() {
35 base::FilePath browser_process_path;
36 base::PathService::Get(base::FILE_EXE, &browser_process_path);
39 process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
40 process.process_name = browser_process_path.BaseName().AsUTF16Unsafe();
41 process_data_.push_back(process);
44 ProcessData* MemoryDetails::ChromeBrowser() {
45 return &process_data_[0];
48 void MemoryDetails::CollectProcessData(
49 const std::vector<ProcessMemoryInformation>& child_info) {
50 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
51 base::BlockingType::MAY_BLOCK);
54 process_data_[0].processes.clear();
56 base::win::ScopedHandle snapshot(
57 ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
58 PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
59 if (!snapshot.Get()) {
60 LOG(ERROR) << "CreateToolhelp32Snapshot failed: " << GetLastError();
63 if (!::Process32First(snapshot.Get(), &process_entry)) {
64 LOG(ERROR) << "Process32First failed: " << GetLastError();
68 base::ProcessId pid = process_entry.th32ProcessID;
69 base::win::ScopedHandle process_handle(::OpenProcess(
70 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
71 if (!process_handle.IsValid())
73 if (_wcsicmp(base::as_wcstr(process_data_[0].process_name),
74 process_entry.szExeFile) != 0) {
78 // Get Memory Information.
79 ProcessMemoryInformation info;
81 info.process_type = pid == GetCurrentProcessId()
82 ? content::PROCESS_TYPE_BROWSER
83 : content::PROCESS_TYPE_UNKNOWN;
85 // Get Version Information.
86 info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
87 // Check if this is one of the child processes whose data we collected
88 // on the IO thread, and if so copy over that data.
89 for (const ProcessMemoryInformation& child : child_info) {
90 if (child.pid == info.pid) {
91 info.titles = child.titles;
92 info.process_type = child.process_type;
97 // Add the process info to our list.
98 process_data_[0].processes.push_back(info);
99 } while (::Process32Next(snapshot.Get(), &process_entry));
101 // Finally return to the browser thread.
102 content::GetUIThreadTaskRunner({})->PostTask(
104 base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));