blob: 8ba6cef10bfa27301c1169257a1af678da35d49a [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/task_manager/task_manager_handler.h"
#include <algorithm>
#include <functional>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/host_desktop.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/webui/web_ui_util.h"
#include "webkit/common/webpreferences.h"
namespace {
struct ColumnType {
const char* column_id;
// Whether the column has the real value separately or not, instead of the
// formatted value to display.
const bool has_real_value;
// Whether the column has single datum or multiple data in each group.
const bool has_multiple_data;
};
const ColumnType kColumnsList[] = {
{"type", false, false},
{"processId", true, false},
{"cpuUsage", true, false},
{"physicalMemory", true, false},
{"sharedMemory", true, false},
{"privateMemory", true, false},
{"webCoreImageCacheSize", true, false},
{"webCoreImageCacheSize", true, false},
{"webCoreScriptsCacheSize", true, false},
{"webCoreCSSCacheSize", true, false},
{"sqliteMemoryUsed", true, false},
{"v8MemoryAllocatedSize", true, false},
{"icon", false, true},
{"title", false, true},
{"profileName", false, true},
{"networkUsage", true, true},
{"fps", true, true},
{"videoMemory", true, false},
{"goatsTeleported", true, true},
{"canInspect", false, true},
{"canActivate", false, true}
};
} // namespace
TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
: task_manager_(tm),
model_(tm->model()),
is_enabled_(false) {
}
TaskManagerHandler::~TaskManagerHandler() {
DisableTaskManager(NULL);
}
// TaskManagerHandler, public: -----------------------------------------------
void TaskManagerHandler::OnModelChanged() {
OnGroupChanged(0, model_->GroupCount());
}
void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
OnGroupChanged(0, model_->GroupCount());
}
void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
}
void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
}
void TaskManagerHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback("killProcesses",
base::Bind(&TaskManagerHandler::HandleKillProcesses,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("inspect",
base::Bind(&TaskManagerHandler::HandleInspect,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("activatePage",
base::Bind(&TaskManagerHandler::HandleActivatePage,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("openAboutMemory",
base::Bind(&TaskManagerHandler::OpenAboutMemory,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("enableTaskManager",
base::Bind(&TaskManagerHandler::EnableTaskManager,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("disableTaskManager",
base::Bind(&TaskManagerHandler::DisableTaskManager,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("setUpdateColumn",
base::Bind(&TaskManagerHandler::HandleSetUpdateColumn,
base::Unretained(this)));
}
static int parseIndex(const Value* value) {
int index = -1;
string16 string16_index;
double double_index;
if (value->GetAsString(&string16_index)) {
bool converted = base::StringToInt(string16_index, &index);
DCHECK(converted);
} else if (value->GetAsDouble(&double_index)) {
index = static_cast<int>(double_index);
} else {
value->GetAsInteger(&index);
}
return index;
}
void TaskManagerHandler::HandleKillProcesses(const ListValue* unique_ids) {
for (ListValue::const_iterator i = unique_ids->begin();
i != unique_ids->end(); ++i) {
int unique_id = parseIndex(*i);
int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
if (resource_index == -1)
continue;
task_manager_->KillProcess(resource_index);
}
}
void TaskManagerHandler::HandleActivatePage(const ListValue* unique_ids) {
for (ListValue::const_iterator i = unique_ids->begin();
i != unique_ids->end(); ++i) {
int unique_id = parseIndex(*i);
int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
if (resource_index == -1)
continue;
task_manager_->ActivateProcess(resource_index);
break;
}
}
void TaskManagerHandler::HandleInspect(const ListValue* unique_ids) {
for (ListValue::const_iterator i = unique_ids->begin();
i != unique_ids->end(); ++i) {
int unique_id = parseIndex(*i);
int resource_index = model_->GetResourceIndexByUniqueId(unique_id);
if (resource_index == -1)
continue;
if (model_->CanInspect(resource_index))
model_->Inspect(resource_index);
break;
}
}
void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
if (!is_enabled_)
return;
is_enabled_ = false;
model_->StopUpdating();
model_->RemoveObserver(this);
}
void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
if (is_enabled_)
return;
is_enabled_ = true;
OnGroupChanged(0, model_->GroupCount());
model_->AddObserver(this);
model_->StartUpdating();
}
void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
content::RenderViewHost* rvh =
web_ui()->GetWebContents()->GetRenderViewHost();
if (rvh) {
WebPreferences webkit_prefs = rvh->GetWebkitPreferences();
webkit_prefs.allow_scripts_to_close_windows = true;
rvh->UpdateWebkitPreferences(webkit_prefs);
} else {
DCHECK(false);
}
task_manager_->OpenAboutMemory(chrome::GetActiveDesktop());
}
void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
DCHECK_EQ(2U, args->GetSize());
bool ret = true;
std::string column_id;
ret &= args->GetString(0, &column_id);
bool is_enabled;
ret &= args->GetBoolean(1, &is_enabled);
DCHECK(ret);
if (is_enabled)
enabled_columns_.insert(column_id);
else
enabled_columns_.erase(column_id);
}
// TaskManagerHandler, private: -----------------------------------------------
bool TaskManagerHandler::is_alive() {
return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
}
void TaskManagerHandler::OnGroupChanged(const int group_start,
const int group_length) {
base::FundamentalValue start_value(group_start);
base::FundamentalValue length_value(group_length);
base::ListValue tasks_value;
for (int i = 0; i < group_length; ++i) {
tasks_value.Append(CreateTaskGroupValue(group_start + i));
}
if (is_enabled_ && is_alive()) {
web_ui()->CallJavascriptFunction("taskChanged",
start_value, length_value, tasks_value);
}
}
void TaskManagerHandler::OnGroupAdded(const int group_start,
const int group_length) {
}
void TaskManagerHandler::OnGroupRemoved(const int group_start,
const int group_length) {
}
void TaskManagerHandler::OnReadyPeriodicalUpdate() {
}
base::DictionaryValue* TaskManagerHandler::CreateTaskGroupValue(
int group_index) {
DictionaryValue* val = new DictionaryValue();
if (group_index >= model_->GroupCount())
return val;
int index = model_->GetResourceIndexForGroup(group_index, 0);
int length = model_->GetGroupRangeForResource(index).second;
// Forces to set following column regardless of |enable_columns|.
val->SetInteger("index", index);
CreateGroupColumnList("processId", index, 1, val);
CreateGroupColumnList("type", index, length, val);
CreateGroupColumnList("uniqueId", index, length, val);
for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
const std::string column_id = kColumnsList[i].column_id;
if (enabled_columns_.find(column_id) == enabled_columns_.end())
continue;
int column_length = kColumnsList[i].has_multiple_data ? length : 1;
CreateGroupColumnList(column_id, index, column_length, val);
if (kColumnsList[i].has_real_value)
CreateGroupColumnList(column_id + "Value", index, column_length, val);
}
return val;
}
void TaskManagerHandler::CreateGroupColumnList(const std::string& column_name,
const int index,
const int length,
DictionaryValue* val) {
ListValue* list = new ListValue();
for (int i = index; i < (index + length); ++i) {
list->Append(CreateColumnValue(column_name, i));
}
val->Set(column_name, list);
}
base::Value* TaskManagerHandler::CreateColumnValue(
const std::string& column_name,
const int i) {
if (column_name == "uniqueId")
return Value::CreateIntegerValue(model_->GetResourceUniqueId(i));
if (column_name == "type") {
return Value::CreateStringValue(
TaskManager::Resource::GetResourceTypeAsString(
model_->GetResourceType(i)));
}
if (column_name == "processId")
return Value::CreateStringValue(model_->GetResourceProcessId(i));
if (column_name == "processIdValue")
return Value::CreateIntegerValue(model_->GetProcessId(i));
if (column_name == "cpuUsage")
return Value::CreateStringValue(model_->GetResourceCPUUsage(i));
if (column_name == "cpuUsageValue")
return Value::CreateDoubleValue(model_->GetCPUUsage(i));
if (column_name == "privateMemory")
return Value::CreateStringValue(model_->GetResourcePrivateMemory(i));
if (column_name == "privateMemoryValue") {
size_t private_memory;
model_->GetPrivateMemory(i, &private_memory);
return Value::CreateDoubleValue(private_memory);
}
if (column_name == "sharedMemory")
return Value::CreateStringValue(model_->GetResourceSharedMemory(i));
if (column_name == "sharedMemoryValue") {
size_t shared_memory;
model_->GetSharedMemory(i, &shared_memory);
return Value::CreateDoubleValue(shared_memory);
}
if (column_name == "physicalMemory")
return Value::CreateStringValue(model_->GetResourcePhysicalMemory(i));
if (column_name == "physicalMemoryValue") {
size_t physical_memory;
model_->GetPhysicalMemory(i, &physical_memory);
return Value::CreateDoubleValue(physical_memory);
}
if (column_name == "icon") {
ui::ScaleFactor icon_scale_factor = web_ui()->GetDeviceScaleFactor();
const gfx::ImageSkia& image = model_->GetResourceIcon(i);
const gfx::ImageSkiaRep image_rep =
image.GetRepresentation(icon_scale_factor);
return Value::CreateStringValue(
webui::GetBitmapDataUrl(image_rep.sk_bitmap()));
}
if (column_name == "title")
return Value::CreateStringValue(model_->GetResourceTitle(i));
if (column_name == "profileName")
return Value::CreateStringValue(model_->GetResourceProfileName(i));
if (column_name == "networkUsage")
return Value::CreateStringValue(model_->GetResourceNetworkUsage(i));
if (column_name == "networkUsageValue")
return Value::CreateDoubleValue(model_->GetNetworkUsage(i));
if (column_name == "webCoreImageCacheSize") {
return Value::CreateStringValue(
model_->GetResourceWebCoreImageCacheSize(i));
}
if (column_name == "webCoreImageCacheSizeValue") {
WebKit::WebCache::ResourceTypeStats resource_stats;
model_->GetWebCoreCacheStats(i, &resource_stats);
return Value::CreateDoubleValue(resource_stats.images.size);
}
if (column_name == "webCoreScriptsCacheSize") {
return Value::CreateStringValue(
model_->GetResourceWebCoreScriptsCacheSize(i));
}
if (column_name == "webCoreScriptsCacheSizeValue") {
WebKit::WebCache::ResourceTypeStats resource_stats;
model_->GetWebCoreCacheStats(i, &resource_stats);
return Value::CreateDoubleValue(resource_stats.scripts.size);
}
if (column_name == "webCoreCSSCacheSize")
return Value::CreateStringValue(model_->GetResourceWebCoreCSSCacheSize(i));
if (column_name == "webCoreCSSCacheSizeValue") {
WebKit::WebCache::ResourceTypeStats resource_stats;
model_->GetWebCoreCacheStats(i, &resource_stats);
return Value::CreateDoubleValue(resource_stats.cssStyleSheets.size);
}
if (column_name == "fps")
return Value::CreateStringValue(model_->GetResourceFPS(i));
if (column_name == "fpsValue") {
float fps;
model_->GetFPS(i, &fps);
return Value::CreateDoubleValue(fps);
}
if (column_name == "videoMemory")
return Value::CreateStringValue(model_->GetResourceVideoMemory(i));
if (column_name == "videoMemoryValue") {
size_t video_memory;
bool has_duplicates;
double value;
if (model_->GetVideoMemory(i, &video_memory, &has_duplicates))
value = static_cast<double>(video_memory);
else
value = 0;
return Value::CreateDoubleValue(value);
}
if (column_name == "sqliteMemoryUsed")
return Value::CreateStringValue(model_->GetResourceSqliteMemoryUsed(i));
if (column_name == "sqliteMemoryUsedValue") {
size_t sqlite_memory;
model_->GetSqliteMemoryUsedBytes(i, &sqlite_memory);
return Value::CreateDoubleValue(sqlite_memory);
}
if (column_name == "goatsTeleported")
return Value::CreateStringValue(model_->GetResourceGoatsTeleported(i));
if (column_name == "goatsTeleportedValue")
return Value::CreateIntegerValue(model_->GetGoatsTeleported(i));
if (column_name == "v8MemoryAllocatedSize") {
return Value::CreateStringValue(
model_->GetResourceV8MemoryAllocatedSize(i));
}
if (column_name == "v8MemoryAllocatedSizeValue") {
size_t v8_memory;
model_->GetV8Memory(i, &v8_memory);
return Value::CreateDoubleValue(v8_memory);
}
if (column_name == "canInspect")
return Value::CreateBooleanValue(model_->CanInspect(i));
if (column_name == "canActivate")
return Value::CreateBooleanValue(model_->CanActivate(i));
NOTREACHED();
return NULL;
}