Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(514)

Side by Side Diff: chrome/browser/chromeos/status/memory_menu_button.cc

Issue 10056001: chromeos: Remove old status-area related code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 // Note: this file is used by Aura on all linux platforms, even though it
6 // is currently in a chromeos specific location.
7
8 #include "chrome/browser/chromeos/status/memory_menu_button.h"
9
10 #include "base/file_util.h"
11 #include "base/process_util.h" // GetSystemMemoryInfo
12 #include "base/stringprintf.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/chromeos/view_ids.h"
16 #include "chrome/browser/memory_purger.h"
17 #include "chrome/common/render_messages.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_types.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "grit/generated_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/views/controls/menu/menu_runner.h"
24 #include "ui/views/widget/widget.h"
25
26 #if defined(USE_TCMALLOC)
27 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
28 #endif
29
30 #if defined(USE_TCMALLOC)
31 const char kProfileDumpFilePrefix[] = "/tmp/chrome_tcmalloc";
32 #endif
33
34 namespace {
35
36 // views::MenuItemView item ids
37 enum {
38 MEM_TOTAL_ITEM,
39 MEM_FREE_ITEM,
40 MEM_BUFFERS_ITEM,
41 MEM_CACHE_ITEM,
42 SHMEM_ITEM,
43 PURGE_MEMORY_ITEM,
44 #if defined(USE_TCMALLOC)
45 TOGGLE_PROFILING_ITEM,
46 DUMP_PROFILING_ITEM,
47 #endif
48 };
49
50 } // namespace
51
52 // Delay between updates, in seconds.
53 const int kUpdateIntervalSeconds = 5;
54
55 MemoryMenuButton::MemoryMenuButton(StatusAreaButton::Delegate* delegate)
56 : StatusAreaButton(delegate, this),
57 meminfo_(new base::SystemMemoryInfoKB()),
58 renderer_kills_(0) {
59 set_id(VIEW_ID_STATUS_BUTTON_MEMORY);
60 // Track renderer kills, as the kernel OOM killer will start to kill our
61 // renderers as we run out of memory.
62 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
63 content::NotificationService::AllSources());
64 UpdateTextAndSetNextTimer();
65 }
66
67 MemoryMenuButton::~MemoryMenuButton() {
68 }
69
70 void MemoryMenuButton::UpdateTextAndSetNextTimer() {
71 UpdateText();
72
73 timer_.Start(FROM_HERE,
74 base::TimeDelta::FromSeconds(kUpdateIntervalSeconds), this,
75 &MemoryMenuButton::UpdateTextAndSetNextTimer);
76 }
77
78 void MemoryMenuButton::UpdateText() {
79 base::GetSystemMemoryInfo(meminfo_.get());
80 // "Anonymous" memory, meaning not mapped to a file (which has a name),
81 // represents memory that has been dynamically allocated to a process.
82 // It thus approximates heap memory usage across all processes.
83 int anon_kb = meminfo_->active_anon + meminfo_->inactive_anon;
84 std::string label = base::StringPrintf("%d MB (%d)",
85 anon_kb / 1024,
86 renderer_kills_);
87 SetText(ASCIIToUTF16(label));
88 std::string tooltip = base::StringPrintf("%d MB allocated (anonymous)\n"
89 "%d renderer kill(s)",
90 anon_kb / 1024,
91 renderer_kills_);
92 SetTooltipText(ASCIIToUTF16(tooltip));
93 SchedulePaint();
94 }
95
96 // MemoryMenuButton, views::MenuDelegate implementation:
97 string16 MemoryMenuButton::GetLabel(int id) const {
98 std::string label;
99 switch (id) {
100 case MEM_TOTAL_ITEM:
101 label = base::StringPrintf("%d MB total", meminfo_->total / 1024);
102 break;
103 case MEM_FREE_ITEM:
104 label = base::StringPrintf("%d MB free", meminfo_->free / 1024);
105 break;
106 case MEM_BUFFERS_ITEM:
107 label = base::StringPrintf("%d MB buffers", meminfo_->buffers / 1024);
108 break;
109 case MEM_CACHE_ITEM:
110 label = base::StringPrintf("%d MB cache", meminfo_->cached / 1024);
111 break;
112 case SHMEM_ITEM:
113 label = base::StringPrintf("%d MB shmem", meminfo_->shmem / 1024);
114 break;
115 case PURGE_MEMORY_ITEM:
116 return ASCIIToUTF16("Purge memory");
117 #if defined(USE_TCMALLOC)
118 case TOGGLE_PROFILING_ITEM:
119 if (!IsHeapProfilerRunning())
120 return ASCIIToUTF16("Start profiling");
121 else
122 return ASCIIToUTF16("Stop profiling");
123 case DUMP_PROFILING_ITEM:
124 return ASCIIToUTF16("Dump profile");
125 #endif
126 default:
127 return string16();
128 }
129 return UTF8ToUTF16(label);
130 }
131
132 bool MemoryMenuButton::IsCommandEnabled(int id) const {
133 switch (id) {
134 case PURGE_MEMORY_ITEM:
135 return true;
136 #if defined(USE_TCMALLOC)
137 case TOGGLE_PROFILING_ITEM:
138 case DUMP_PROFILING_ITEM:
139 return true;
140 #endif
141 default:
142 return false;
143 }
144 }
145
146 namespace {
147 #if defined(USE_TCMALLOC)
148 FilePath::StringType GetProfileDumpFilePath(base::ProcessId pid) {
149 int int_pid = static_cast<int>(pid);
150 FilePath::StringType filepath = StringPrintf(
151 FILE_PATH_LITERAL("%s.%d.heap"),
152 FILE_PATH_LITERAL(kProfileDumpFilePrefix), int_pid);
153 return filepath;
154 }
155 #endif
156 }
157
158 void MemoryMenuButton::SendCommandToRenderers(int id) {
159 #if defined(USE_TCMALLOC)
160 // Use the "is running" value for this process to determine whether to
161 // start or stop profiling on the renderer processes.
162 bool started = IsHeapProfilerRunning();
163 for (content::RenderProcessHost::iterator it =
164 content::RenderProcessHost::AllHostsIterator();
165 !it.IsAtEnd(); it.Advance()) {
166 switch (id) {
167 case TOGGLE_PROFILING_ITEM:
168 it.GetCurrentValue()->Send(new ChromeViewMsg_SetTcmallocHeapProfiling(
169 started, std::string(kProfileDumpFilePrefix)));
170 break;
171 case DUMP_PROFILING_ITEM:
172 it.GetCurrentValue()->Send(new ChromeViewMsg_WriteTcmallocHeapProfile(
173 GetProfileDumpFilePath(
174 base::GetProcId(it.GetCurrentValue()->GetHandle()))));
175 break;
176 default:
177 NOTREACHED();
178 }
179 }
180 #endif
181 }
182
183 void MemoryMenuButton::ExecuteCommand(int id) {
184 switch (id) {
185 case PURGE_MEMORY_ITEM:
186 MemoryPurger::PurgeAll();
187 break;
188 #if defined(USE_TCMALLOC)
189 case TOGGLE_PROFILING_ITEM: {
190 if (!IsHeapProfilerRunning())
191 HeapProfilerStart(kProfileDumpFilePrefix);
192 else
193 HeapProfilerStop();
194 SendCommandToRenderers(id);
195 break;
196 }
197 case DUMP_PROFILING_ITEM: {
198 char* profile = GetHeapProfile();
199 if (profile) {
200 FilePath::StringType filepath =
201 GetProfileDumpFilePath(base::GetProcId(base::GetCurrentProcId()));
202 VLOG(0) << "Writing browser heap profile dump to: " << filepath;
203 base::ThreadRestrictions::ScopedAllowIO allow_io;
204 file_util::WriteFile(FilePath(filepath), profile, strlen(profile));
205 delete profile;
206 }
207 SendCommandToRenderers(id);
208 break;
209 }
210 #endif
211 default:
212 NOTREACHED();
213 break;
214 }
215 }
216
217 int MemoryMenuButton::horizontal_padding() {
218 return 3;
219 }
220
221 // MemoryMenuButton, views::MenuButtonListener implementation:
222
223 void MemoryMenuButton::OnMenuButtonClicked(views::View* source,
224 const gfx::Point& point) {
225 // View passed in must be a views::MenuButton, i.e. the MemoryMenuButton.
226 DCHECK_EQ(source, this);
227
228 menu_runner_.reset(new views::MenuRunner(CreateMenu()));
229 gfx::Point screen_location;
230 views::View::ConvertPointToScreen(source, &screen_location);
231 gfx::Rect bounds(screen_location, source->size());
232 if (menu_runner_->RunMenuAt(
233 source->GetWidget()->GetTopLevelWidget(), this, bounds,
234 views::MenuItemView::TOPRIGHT, views::MenuRunner::HAS_MNEMONICS) ==
235 views::MenuRunner::MENU_DELETED)
236 return;
237 }
238
239 views::MenuItemView* MemoryMenuButton::CreateMenu() {
240 // Just rebuild the menu each time to ensure the labels are up-to-date.
241 views::MenuItemView* menu = new views::MenuItemView(this);
242 // Text for these items will be set by GetLabel().
243 menu->AppendDelegateMenuItem(MEM_TOTAL_ITEM);
244 menu->AppendDelegateMenuItem(MEM_FREE_ITEM);
245 menu->AppendDelegateMenuItem(MEM_BUFFERS_ITEM);
246 menu->AppendDelegateMenuItem(MEM_CACHE_ITEM);
247 menu->AppendDelegateMenuItem(SHMEM_ITEM);
248 menu->AppendSeparator();
249 menu->AppendDelegateMenuItem(PURGE_MEMORY_ITEM);
250 #if defined(USE_TCMALLOC)
251 menu->AppendSeparator();
252 menu->AppendDelegateMenuItem(TOGGLE_PROFILING_ITEM);
253 if (IsHeapProfilerRunning())
254 menu->AppendDelegateMenuItem(DUMP_PROFILING_ITEM);
255 #endif
256 return menu;
257 }
258
259 /////////////////////////////////////////////////////////////////////////////
260 // content::NotificationObserver overrides.
261
262 void MemoryMenuButton::Observe(int type,
263 const content::NotificationSource& source,
264 const content::NotificationDetails& details) {
265 switch (type) {
266 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
267 content::RenderProcessHost::RendererClosedDetails* process_details =
268 content::Details<content::RenderProcessHost::RendererClosedDetails>(
269 details).ptr();
270 if (process_details->status ==
271 base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
272 renderer_kills_++;
273 // A kill is a very interesting event, so repaint immediately.
274 UpdateText();
275 }
276 break;
277 }
278 default:
279 NOTREACHED() << L"Received unexpected notification";
280 break;
281 }
282 }
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/status/memory_menu_button.h ('k') | chrome/browser/chromeos/status/network_menu.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698