[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / memory_details_android.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 <memory>
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "base/functional/bind.h"
13 #include "base/process/process_iterator.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/scoped_blocking_call.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/grit/branded_strings.h"
18 #include "content/public/browser/browser_task_traits.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/process_type.h"
21 #include "ui/base/l10n/l10n_util.h"
22
23 using base::ProcessEntry;
24 using base::ProcessId;
25 namespace {
26
27 // A helper for |CollectProcessData()| to include the chrome sandboxed
28 // processes in android which are not running as a child of the browser
29 // process.
30 void AddNonChildChromeProcesses(
31     std::vector<ProcessMemoryInformation>* processes) {
32   base::ProcessIterator process_iter(NULL);
33   while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
34     const std::vector<std::string>& cmd_args = process_entry->cmd_line_args();
35     if (cmd_args.empty() ||
36         cmd_args[0].find(chrome::kHelperProcessExecutableName) ==
37             std::string::npos) {
38       continue;
39     }
40     ProcessMemoryInformation info;
41     info.pid = process_entry->pid();
42     processes->push_back(info);
43   }
44 }
45
46 // For each of the pids, collect memory information about that process
47 // and append a record to |out|.
48 void GetProcessDataMemoryInformation(
49     const std::set<ProcessId>& pids, ProcessData* out) {
50   for (std::set<ProcessId>::const_iterator i = pids.begin(); i != pids.end();
51        ++i) {
52     ProcessMemoryInformation pmi;
53
54     pmi.pid = *i;
55     pmi.num_processes = 1;
56
57     base::ProcessId current_pid = base::GetCurrentProcId();
58     if (pmi.pid == current_pid)
59       pmi.process_type = content::PROCESS_TYPE_BROWSER;
60     else
61       pmi.process_type = content::PROCESS_TYPE_UNKNOWN;
62
63     std::unique_ptr<base::ProcessMetrics> metrics(
64         base::ProcessMetrics::CreateProcessMetrics(*i));
65
66     // TODO(ssid): Reading "/proc/fd" only works for current process. For child
67     // processes, the values need to be computed by the process itself.
68     if (pmi.pid == current_pid) {
69       pmi.num_open_fds = metrics->GetOpenFdCount();
70       pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
71     }
72
73     out->processes.push_back(pmi);
74   }
75 }
76
77 // Find all children of the given process.
78 void GetAllChildren(const std::vector<ProcessEntry>& processes,
79                     const std::set<ProcessId>& roots,
80                     std::set<ProcessId>* out) {
81   *out = roots;
82
83   std::set<ProcessId> wavefront;
84   for (std::set<ProcessId>::const_iterator i = roots.begin(); i != roots.end();
85        ++i) {
86     wavefront.insert(*i);
87   }
88
89   while (wavefront.size()) {
90     std::set<ProcessId> next_wavefront;
91     for (std::vector<ProcessEntry>::const_iterator i = processes.begin();
92          i != processes.end(); ++i) {
93       if (wavefront.count(i->parent_pid())) {
94         out->insert(i->pid());
95         next_wavefront.insert(i->pid());
96       }
97     }
98
99     wavefront.clear();
100     wavefront.swap(next_wavefront);
101   }
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>& chrome_processes) {
115   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
116                                                 base::BlockingType::WILL_BLOCK);
117
118   std::vector<ProcessMemoryInformation> all_processes(chrome_processes);
119   AddNonChildChromeProcesses(&all_processes);
120
121   std::vector<ProcessEntry> processes;
122   base::ProcessIterator process_iter(NULL);
123   while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
124     processes.push_back(*process_entry);
125   }
126
127   std::set<ProcessId> roots;
128   roots.insert(base::GetCurrentProcId());
129   for (std::vector<ProcessMemoryInformation>::const_iterator
130        i = all_processes.begin(); i != all_processes.end(); ++i) {
131     roots.insert(i->pid);
132   }
133
134   std::set<ProcessId> current_browser_processes;
135   GetAllChildren(processes, roots, &current_browser_processes);
136
137   ProcessData current_browser;
138   GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
139   current_browser.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
140   current_browser.process_name =
141       base::ASCIIToUTF16(chrome::kBrowserProcessExecutableName);
142   process_data_.push_back(current_browser);
143
144   // Finally return to the browser thread.
145   content::GetUIThreadTaskRunner({})->PostTask(
146       FROM_HERE,
147       base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));
148 }