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.
5 #include "chrome/browser/ui/webui/task_manager/task_manager_handler.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/task_manager/task_manager.h"
16 #include "chrome/browser/ui/host_desktop.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/browser/web_ui.h"
20 #include "ui/base/webui/web_ui_util.h"
21 #include "ui/gfx/image/image_skia.h"
22 #include "webkit/common/webpreferences.h"
27 const char* column_id;
28 // Whether the column has the real value separately or not, instead of the
29 // formatted value to display.
30 const bool has_real_value;
31 // Whether the column has single datum or multiple data in each group.
32 const bool has_multiple_data;
35 const ColumnType kColumnsList[] = {
36 {"type", false, false},
37 {"processId", true, false},
38 {"cpuUsage", true, false},
39 {"physicalMemory", true, false},
40 {"sharedMemory", true, false},
41 {"privateMemory", true, false},
42 {"webCoreImageCacheSize", true, false},
43 {"webCoreImageCacheSize", true, false},
44 {"webCoreScriptsCacheSize", true, false},
45 {"webCoreCSSCacheSize", true, false},
46 {"sqliteMemoryUsed", true, false},
47 {"v8MemoryAllocatedSize", true, false},
48 {"icon", false, true},
49 {"title", false, true},
50 {"profileName", false, true},
51 {"networkUsage", true, true},
53 {"videoMemory", true, false},
54 {"goatsTeleported", true, true},
55 {"canInspect", false, true},
56 {"canActivate", false, true}
61 TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
67 TaskManagerHandler::~TaskManagerHandler() {
68 DisableTaskManager(NULL);
71 // TaskManagerHandler, public: -----------------------------------------------
73 void TaskManagerHandler::OnModelChanged() {
74 OnGroupChanged(0, model_->GroupCount());
77 void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
78 OnGroupChanged(0, model_->GroupCount());
81 void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
84 void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
87 void TaskManagerHandler::RegisterMessages() {
88 web_ui()->RegisterMessageCallback("killProcesses",
89 base::Bind(&TaskManagerHandler::HandleKillProcesses,
90 base::Unretained(this)));
91 web_ui()->RegisterMessageCallback("inspect",
92 base::Bind(&TaskManagerHandler::HandleInspect,
93 base::Unretained(this)));
94 web_ui()->RegisterMessageCallback("activatePage",
95 base::Bind(&TaskManagerHandler::HandleActivatePage,
96 base::Unretained(this)));
97 web_ui()->RegisterMessageCallback("openAboutMemory",
98 base::Bind(&TaskManagerHandler::OpenAboutMemory,
99 base::Unretained(this)));
100 web_ui()->RegisterMessageCallback("enableTaskManager",
101 base::Bind(&TaskManagerHandler::EnableTaskManager,
102 base::Unretained(this)));
103 web_ui()->RegisterMessageCallback("disableTaskManager",
104 base::Bind(&TaskManagerHandler::DisableTaskManager,
105 base::Unretained(this)));
106 web_ui()->RegisterMessageCallback("setUpdateColumn",
107 base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
108 base::Unretained(this)));
111 static int parseIndex(const Value* value) {
113 string16 string16_index;
115 if (value->GetAsString(&string16_index)) {
116 bool converted = base::StringToInt(string16_index, &index);
118 } else if (value->GetAsDouble(&double_index)) {
119 index = static_cast<int>(double_index);
121 value->GetAsInteger(&index);
126 void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
127 for (ListValue::const_iterator i = unique_ids->begin();
128 i != unique_ids->end(); ++i) {
129 int unique_id = parseIndex(*i);
130 int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
131 if (resource_index == -1)
134 task_manager_->KillProcess(resource_index);
138 void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
139 for (ListValue::const_iterator i = unique_ids->begin();
140 i != unique_ids->end(); ++i) {
141 int unique_id = parseIndex(*i);
142 int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
143 if (resource_index == -1)
146 task_manager_->ActivateProcess(resource_index);
151 void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
152 for (ListValue::const_iterator i = unique_ids->begin();
153 i != unique_ids->end(); ++i) {
154 int unique_id = parseIndex(*i);
155 int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
156 if (resource_index == -1)
159 if (model_->CanInspect(resource_index))
160 model_->Inspect(resource_index);
165 void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
170 model_->StopUpdating();
171 model_->RemoveObserver(this);
174 void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
180 OnGroupChanged(0, model_->GroupCount());
182 model_->AddObserver(this);
183 model_->StartUpdating();
186 void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
187 content::RenderViewHost* rvh =
188 web_ui()->GetWebContents()->GetRenderViewHost();
190 WebPreferences webkit_prefs = rvh->GetWebkitPreferences();
191 webkit_prefs.allow_scripts_to_close_windows = true;
192 rvh->UpdateWebkitPreferences(webkit_prefs);
197 task_manager_->OpenAboutMemory(chrome::GetActiveDesktop());
200 void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
201 DCHECK_EQ(2U, args->GetSize());
204 std::string column_id;
205 ret &= args->GetString(0, &column_id);
207 ret &= args->GetBoolean(1, &is_enabled);
211 enabled_columns_.insert(column_id);
213 enabled_columns_.erase(column_id);
216 // TaskManagerHandler, private: -----------------------------------------------
218 bool TaskManagerHandler::is_alive() {
219 return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
222 void TaskManagerHandler::OnGroupChanged(const int group_start,
223 const int group_length) {
224 base::FundamentalValue start_value(group_start);
225 base::FundamentalValue length_value(group_length);
226 base::ListValue tasks_value;
228 for (int i = 0; i < group_length; ++i) {
229 tasks_value.Append(CreateTaskGroupValue(group_start + i));
232 if (is_enabled_ && is_alive()) {
233 web_ui()->CallJavascriptFunction("taskChanged",
234 start_value, length_value, tasks_value);
238 void TaskManagerHandler::OnGroupAdded(const int group_start,
239 const int group_length) {
242 void TaskManagerHandler::OnGroupRemoved(const int group_start,
243 const int group_length) {
246 void TaskManagerHandler::OnReadyPeriodicalUpdate() {
249 base::DictionaryValue* TaskManagerHandler::CreateTaskGroupValue(
251 DictionaryValue* val = new DictionaryValue();
253 if (group_index >= model_->GroupCount())
256 int index = model_->GetResourceIndexForGroup(group_index, 0);
257 int length = model_->GetGroupRangeForResource(index).second;
259 // Forces to set following column regardless of |enable_columns|.
260 val->SetInteger("index", index);
261 CreateGroupColumnList("processId", index, 1, val);
262 CreateGroupColumnList("type", index, length, val);
263 CreateGroupColumnList("uniqueId", index, length, val);
265 for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
266 const std::string column_id = kColumnsList[i].column_id;
268 if (enabled_columns_.find(column_id) == enabled_columns_.end())
271 int column_length = kColumnsList[i].has_multiple_data ? length : 1;
272 CreateGroupColumnList(column_id, index, column_length, val);
274 if (kColumnsList[i].has_real_value)
275 CreateGroupColumnList(column_id + "Value", index, column_length, val);
281 void TaskManagerHandler::CreateGroupColumnList(const std::string& column_name,
284 DictionaryValue* val) {
285 ListValue* list = new ListValue();
286 for (int i = index; i < (index + length); ++i) {
287 list->Append(CreateColumnValue(column_name, i));
289 val->Set(column_name, list);
292 base::Value* TaskManagerHandler::CreateColumnValue(
293 const std::string& column_name,
295 if (column_name == "uniqueId")
296 return Value::CreateIntegerValue(model_->GetResourceUniqueId(i));
297 if (column_name == "type") {
298 return Value::CreateStringValue(
299 TaskManager::Resource::GetResourceTypeAsString(
300 model_->GetResourceType(i)));
302 if (column_name == "processId")
303 return Value::CreateStringValue(model_->GetResourceProcessId(i));
304 if (column_name == "processIdValue")
305 return Value::CreateIntegerValue(model_->GetProcessId(i));
306 if (column_name == "cpuUsage")
307 return Value::CreateStringValue(model_->GetResourceCPUUsage(i));
308 if (column_name == "cpuUsageValue")
309 return Value::CreateDoubleValue(model_->GetCPUUsage(i));
310 if (column_name == "privateMemory")
311 return Value::CreateStringValue(model_->GetResourcePrivateMemory(i));
312 if (column_name == "privateMemoryValue") {
313 size_t private_memory;
314 model_->GetPrivateMemory(i, &private_memory);
315 return Value::CreateDoubleValue(private_memory);
317 if (column_name == "sharedMemory")
318 return Value::CreateStringValue(model_->GetResourceSharedMemory(i));
319 if (column_name == "sharedMemoryValue") {
320 size_t shared_memory;
321 model_->GetSharedMemory(i, &shared_memory);
322 return Value::CreateDoubleValue(shared_memory);
324 if (column_name == "physicalMemory")
325 return Value::CreateStringValue(model_->GetResourcePhysicalMemory(i));
326 if (column_name == "physicalMemoryValue") {
327 size_t physical_memory;
328 model_->GetPhysicalMemory(i, &physical_memory);
329 return Value::CreateDoubleValue(physical_memory);
331 if (column_name == "icon") {
332 ui::ScaleFactor icon_scale_factor = web_ui()->GetDeviceScaleFactor();
333 const gfx::ImageSkia& image = model_->GetResourceIcon(i);
334 const gfx::ImageSkiaRep image_rep =
335 image.GetRepresentation(icon_scale_factor);
336 return Value::CreateStringValue(
337 webui::GetBitmapDataUrl(image_rep.sk_bitmap()));
339 if (column_name == "title")
340 return Value::CreateStringValue(model_->GetResourceTitle(i));
341 if (column_name == "profileName")
342 return Value::CreateStringValue(model_->GetResourceProfileName(i));
343 if (column_name == "networkUsage")
344 return Value::CreateStringValue(model_->GetResourceNetworkUsage(i));
345 if (column_name == "networkUsageValue")
346 return Value::CreateDoubleValue(model_->GetNetworkUsage(i));
347 if (column_name == "webCoreImageCacheSize") {
348 return Value::CreateStringValue(
349 model_->GetResourceWebCoreImageCacheSize(i));
351 if (column_name == "webCoreImageCacheSizeValue") {
352 WebKit::WebCache::ResourceTypeStats resource_stats;
353 model_->GetWebCoreCacheStats(i, &resource_stats);
354 return Value::CreateDoubleValue(resource_stats.images.size);
356 if (column_name == "webCoreScriptsCacheSize") {
357 return Value::CreateStringValue(
358 model_->GetResourceWebCoreScriptsCacheSize(i));
360 if (column_name == "webCoreScriptsCacheSizeValue") {
361 WebKit::WebCache::ResourceTypeStats resource_stats;
362 model_->GetWebCoreCacheStats(i, &resource_stats);
363 return Value::CreateDoubleValue(resource_stats.scripts.size);
365 if (column_name == "webCoreCSSCacheSize")
366 return Value::CreateStringValue(model_->GetResourceWebCoreCSSCacheSize(i));
367 if (column_name == "webCoreCSSCacheSizeValue") {
368 WebKit::WebCache::ResourceTypeStats resource_stats;
369 model_->GetWebCoreCacheStats(i, &resource_stats);
370 return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
372 if (column_name == "fps")
373 return Value::CreateStringValue(model_->GetResourceFPS(i));
374 if (column_name == "fpsValue") {
376 model_->GetFPS(i, &fps);
377 return Value::CreateDoubleValue(fps);
379 if (column_name == "videoMemory")
380 return Value::CreateStringValue(model_->GetResourceVideoMemory(i));
381 if (column_name == "videoMemoryValue") {
385 if (model_->GetVideoMemory(i, &video_memory, &has_duplicates))
386 value = static_cast<double>(video_memory);
389 return Value::CreateDoubleValue(value);
391 if (column_name == "sqliteMemoryUsed")
392 return Value::CreateStringValue(model_->GetResourceSqliteMemoryUsed(i));
393 if (column_name == "sqliteMemoryUsedValue") {
394 size_t sqlite_memory;
395 model_->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
396 return Value::CreateDoubleValue(sqlite_memory);
398 if (column_name == "goatsTeleported")
399 return Value::CreateStringValue(model_->GetResourceGoatsTeleported(i));
400 if (column_name == "goatsTeleportedValue")
401 return Value::CreateIntegerValue(model_->GetGoatsTeleported(i));
402 if (column_name == "v8MemoryAllocatedSize") {
403 return Value::CreateStringValue(
404 model_->GetResourceV8MemoryAllocatedSize(i));
406 if (column_name == "v8MemoryAllocatedSizeValue") {
408 model_->GetV8Memory(i, &v8_memory);
409 return Value::CreateDoubleValue(v8_memory);
411 if (column_name == "canInspect")
412 return Value::CreateBooleanValue(model_->CanInspect(i));
413 if (column_name == "canActivate")
414 return Value::CreateBooleanValue(model_->CanActivate(i));