[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / memory_details_linux.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 #include <sys/types.h>
9 #include <unistd.h>
10
11 #include <map>
12 #include <memory>
13 #include <set>
14
15 #include "base/files/file_util.h"
16 #include "base/functional/bind.h"
17 #include "base/process/process_iterator.h"
18 #include "base/process/process_metrics.h"
19 #include "base/strings/string_number_conversions.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 "build/build_config.h"
24 #include "build/chromeos_buildflags.h"
25 #include "chrome/common/chrome_constants.h"
26 #include "chrome/grit/branded_strings.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 using base::ProcessEntry;
33 namespace {
34
35 struct Process {
36   pid_t pid;
37   pid_t parent;
38 };
39
40 typedef std::map<pid_t, Process> ProcessMap;
41
42 // Get information on all the processes running on the system.
43 ProcessMap GetProcesses() {
44   ProcessMap map;
45
46   base::ProcessIterator process_iter(nullptr);
47   while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
48     Process process;
49     process.pid = process_entry->pid();
50     process.parent = process_entry->parent_pid();
51     map.insert(std::make_pair(process.pid, process));
52   }
53   return map;
54 }
55
56 // For each of a list of pids, collect memory information about that process.
57 ProcessData GetProcessDataMemoryInformation(
58     const std::vector<pid_t>& pids) {
59   ProcessData process_data;
60   for (pid_t pid : pids) {
61     ProcessMemoryInformation pmi;
62
63     pmi.pid = pid;
64     pmi.num_processes = 1;
65
66     if (pmi.pid == base::GetCurrentProcId())
67       pmi.process_type = content::PROCESS_TYPE_BROWSER;
68     else
69       pmi.process_type = content::PROCESS_TYPE_UNKNOWN;
70
71     std::unique_ptr<base::ProcessMetrics> metrics(
72         base::ProcessMetrics::CreateProcessMetrics(pid));
73     pmi.num_open_fds = metrics->GetOpenFdCount();
74     pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
75
76     process_data.processes.push_back(pmi);
77   }
78   return process_data;
79 }
80
81 // Find all children of the given process with pid |root|.
82 std::vector<pid_t> GetAllChildren(const ProcessMap& processes, pid_t root) {
83   std::vector<pid_t> children;
84   children.push_back(root);
85
86   std::set<pid_t> wavefront, next_wavefront;
87   wavefront.insert(root);
88
89   while (wavefront.size()) {
90     for (const auto& entry : processes) {
91       const Process& process = entry.second;
92       if (wavefront.count(process.parent)) {
93         children.push_back(process.pid);
94         next_wavefront.insert(process.pid);
95       }
96     }
97
98     wavefront.clear();
99     wavefront.swap(next_wavefront);
100   }
101   return children;
102 }
103
104 }  // namespace
105
106 MemoryDetails::MemoryDetails() {
107 }
108
109 ProcessData* MemoryDetails::ChromeBrowser() {
110   return &process_data_[0];
111 }
112
113 void MemoryDetails::CollectProcessData(
114     const std::vector<ProcessMemoryInformation>& child_info) {
115   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
116                                                 base::BlockingType::MAY_BLOCK);
117
118   ProcessMap process_map = GetProcesses();
119   std::set<pid_t> browsers_found;
120
121   ProcessData current_browser =
122       GetProcessDataMemoryInformation(GetAllChildren(process_map, getpid()));
123   current_browser.name = l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
124   current_browser.process_name = u"chrome";
125
126   for (auto i = current_browser.processes.begin();
127        i != current_browser.processes.end(); ++i) {
128     // Check if this is one of the child processes whose data we collected
129     // on the IO thread, and if so copy over that data.
130     for (size_t child = 0; child < child_info.size(); child++) {
131       if (child_info[child].pid != i->pid)
132         continue;
133       i->titles = child_info[child].titles;
134       i->process_type = child_info[child].process_type;
135       break;
136     }
137   }
138
139   process_data_.push_back(current_browser);
140
141 #if BUILDFLAG(IS_CHROMEOS_ASH)
142   base::GetSwapInfo(&swap_info_);
143 #endif
144
145   // Finally return to the browser thread.
146   content::GetUIThreadTaskRunner({})->PostTask(
147       FROM_HERE,
148       base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));
149 }