[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / memory_details_mac.cc
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.
4
5 #include "chrome/browser/memory_details.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <set>
11 #include <string>
12
13 #include "base/apple/foundation_util.h"
14 #include "base/file_version_info.h"
15 #include "base/files/file_path.h"
16 #include "base/functional/bind.h"
17 #include "base/process/process_iterator.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/threading/scoped_blocking_call.h"
21 #include "base/threading/thread.h"
22 #include "chrome/common/chrome_constants.h"
23 #include "chrome/common/url_constants.h"
24 #include "chrome/grit/branded_strings.h"
25 #include "components/version_info/version_info.h"
26 #include "content/public/browser/browser_child_process_host.h"
27 #include "content/public/browser/browser_task_traits.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/common/process_type.h"
30 #include "ui/base/l10n/l10n_util.h"
31
32 namespace {
33
34 // A helper for |CollectProcessData()|, collecting data on the Chrome/Chromium
35 // process with PID |pid|. The collected data is added to |processes|.
36 void CollectProcessDataForChromeProcess(
37     const std::vector<ProcessMemoryInformation>& child_info,
38     base::ProcessId pid,
39     ProcessMemoryInformationList* processes) {
40   ProcessMemoryInformation info;
41   info.pid = pid;
42   if (info.pid == base::GetCurrentProcId())
43     info.process_type = content::PROCESS_TYPE_BROWSER;
44   else
45     info.process_type = content::PROCESS_TYPE_UNKNOWN;
46
47   info.product_name = base::ASCIIToUTF16(version_info::GetProductName());
48   info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
49
50   // A PortProvider is not necessary to acquire information about the number
51   // of open file descriptors.
52   std::unique_ptr<base::ProcessMetrics> metrics(
53       base::ProcessMetrics::CreateProcessMetrics(pid, nullptr));
54   info.num_open_fds = metrics->GetOpenFdCount();
55   info.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
56
57   // Check if this is one of the child processes whose data was already
58   // collected and exists in |child_data|.
59   for (const ProcessMemoryInformation& child : child_info) {
60     if (child.pid == info.pid) {
61       info.titles = child.titles;
62       info.process_type = child.process_type;
63       break;
64     }
65   }
66
67   processes->push_back(info);
68 }
69
70 }  // namespace
71
72 MemoryDetails::MemoryDetails() {
73   const base::FilePath browser_process_path =
74       base::GetProcessExecutablePath(base::GetCurrentProcessHandle());
75
76   ProcessData process;
77   process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
78   process.process_name =
79       base::UTF8ToUTF16(browser_process_path.BaseName().value());
80   process_data_.push_back(process);
81 }
82
83 ProcessData* MemoryDetails::ChromeBrowser() {
84   return &process_data_[0];
85 }
86
87 void MemoryDetails::CollectProcessData(
88     const std::vector<ProcessMemoryInformation>& child_info) {
89   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
90                                                 base::BlockingType::MAY_BLOCK);
91
92   // Clear old data.
93   process_data_[0].processes.clear();
94
95   // First, we use |NamedProcessIterator| to get the PIDs of the processes we're
96   // interested in; we save our results to avoid extra calls to
97   // |NamedProcessIterator| (for performance reasons) and to avoid additional
98   // inconsistencies caused by racing. Then we run |/bin/ps| *once* to get
99   // information on those PIDs. Then we used our saved information to iterate
100   // over browsers, then over PIDs.
101
102   // Get PIDs of main browser processes.
103   std::vector<base::ProcessId> all_pids;
104   {
105     base::NamedProcessIterator process_it(
106         base::UTF16ToUTF8(process_data_[0].process_name), NULL);
107
108     while (const base::ProcessEntry* entry = process_it.NextProcessEntry()) {
109       all_pids.push_back(entry->pid());
110     }
111   }
112
113   // Get PIDs of the helper.
114   {
115     base::NamedProcessIterator helper_it(chrome::kHelperProcessExecutableName,
116                                          NULL, /*use_prefix_match=*/true);
117     while (const base::ProcessEntry* entry = helper_it.NextProcessEntry()) {
118       all_pids.push_back(entry->pid());
119     }
120   }
121
122   ProcessMemoryInformationList* chrome_processes = &process_data_[0].processes;
123
124   // Collect data about Chrome/Chromium.
125   for (const base::ProcessId& pid : all_pids)
126     CollectProcessDataForChromeProcess(child_info, pid, chrome_processes);
127
128   // Finally return to the browser thread.
129   content::GetUIThreadTaskRunner({})->PostTask(
130       FROM_HERE,
131       base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));
132 }