- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / task_manager / task_manager_handler.cc
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 #include "chrome/browser/ui/webui/task_manager/task_manager_handler.h"
6
7 #include <algorithm>
8 #include <functional>
9
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"
23
24 namespace {
25
26 struct ColumnType {
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;
33 };
34
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},
52   {"fps", true, true},
53   {"videoMemory", true, false},
54   {"goatsTeleported", true, true},
55   {"canInspect", false, true},
56   {"canActivate", false, true}
57 };
58
59 }  // namespace
60
61 TaskManagerHandler::TaskManagerHandler(TaskManager* tm)
62     : task_manager_(tm),
63       model_(tm->model()),
64       is_enabled_(false) {
65 }
66
67 TaskManagerHandler::~TaskManagerHandler() {
68   DisableTaskManager(NULL);
69 }
70
71 // TaskManagerHandler, public: -----------------------------------------------
72
73 void TaskManagerHandler::OnModelChanged() {
74   OnGroupChanged(0, model_->GroupCount());
75 }
76
77 void TaskManagerHandler::OnItemsChanged(const int start, const int length) {
78   OnGroupChanged(0, model_->GroupCount());
79 }
80
81 void TaskManagerHandler::OnItemsAdded(const int start, const int length) {
82 }
83
84 void TaskManagerHandler::OnItemsRemoved(const int start, const int length) {
85 }
86
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)));
109 }
110
111 static int parseIndex(const Value* value) {
112   int index = -1;
113   string16 string16_index;
114   double double_index;
115   if (value->GetAsString(&string16_index)) {
116     bool converted = base::StringToInt(string16_index, &index);
117     DCHECK(converted);
118   } else if (value->GetAsDouble(&double_index)) {
119     index = static_cast<int>(double_index);
120   } else {
121     value->GetAsInteger(&index);
122   }
123   return index;
124 }
125
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)
132       continue;
133
134     task_manager_->KillProcess(resource_index);
135   }
136 }
137
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)
144       continue;
145
146     task_manager_->ActivateProcess(resource_index);
147     break;
148   }
149 }
150
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)
157       continue;
158
159     if (model_->CanInspect(resource_index))
160       model_->Inspect(resource_index);
161     break;
162   }
163 }
164
165 void TaskManagerHandler::DisableTaskManager(const ListValue* indexes) {
166   if (!is_enabled_)
167     return;
168
169   is_enabled_ = false;
170   model_->StopUpdating();
171   model_->RemoveObserver(this);
172 }
173
174 void TaskManagerHandler::EnableTaskManager(const ListValue* indexes) {
175   if (is_enabled_)
176     return;
177
178   is_enabled_ = true;
179
180   OnGroupChanged(0, model_->GroupCount());
181
182   model_->AddObserver(this);
183   model_->StartUpdating();
184 }
185
186 void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
187   content::RenderViewHost* rvh =
188       web_ui()->GetWebContents()->GetRenderViewHost();
189   if (rvh) {
190     WebPreferences webkit_prefs = rvh->GetWebkitPreferences();
191     webkit_prefs.allow_scripts_to_close_windows = true;
192     rvh->UpdateWebkitPreferences(webkit_prefs);
193   } else {
194     DCHECK(false);
195   }
196
197   task_manager_->OpenAboutMemory(chrome::GetActiveDesktop());
198 }
199
200 void TaskManagerHandler::HandleSetUpdateColumn(const ListValue* args) {
201   DCHECK_EQ(2U, args->GetSize());
202
203   bool ret = true;
204   std::string column_id;
205   ret &= args->GetString(0, &column_id);
206   bool is_enabled;
207   ret &= args->GetBoolean(1, &is_enabled);
208   DCHECK(ret);
209
210   if (is_enabled)
211     enabled_columns_.insert(column_id);
212   else
213     enabled_columns_.erase(column_id);
214 }
215
216 // TaskManagerHandler, private: -----------------------------------------------
217
218 bool TaskManagerHandler::is_alive() {
219   return web_ui()->GetWebContents()->GetRenderViewHost() != NULL;
220 }
221
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;
227
228   for (int i = 0; i < group_length; ++i) {
229     tasks_value.Append(CreateTaskGroupValue(group_start + i));
230   }
231
232   if (is_enabled_ && is_alive()) {
233     web_ui()->CallJavascriptFunction("taskChanged",
234                                      start_value, length_value, tasks_value);
235   }
236 }
237
238 void TaskManagerHandler::OnGroupAdded(const int group_start,
239                                       const int group_length) {
240 }
241
242 void TaskManagerHandler::OnGroupRemoved(const int group_start,
243                                         const int group_length) {
244 }
245
246 void TaskManagerHandler::OnReadyPeriodicalUpdate() {
247 }
248
249 base::DictionaryValue* TaskManagerHandler::CreateTaskGroupValue(
250     int group_index) {
251   DictionaryValue* val = new DictionaryValue();
252
253   if (group_index >= model_->GroupCount())
254      return val;
255
256   int index = model_->GetResourceIndexForGroup(group_index, 0);
257   int length = model_->GetGroupRangeForResource(index).second;
258
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);
264
265   for (size_t i = 0; i < arraysize(kColumnsList); ++i) {
266     const std::string column_id = kColumnsList[i].column_id;
267
268     if (enabled_columns_.find(column_id) == enabled_columns_.end())
269       continue;
270
271     int column_length = kColumnsList[i].has_multiple_data ? length : 1;
272     CreateGroupColumnList(column_id, index, column_length, val);
273
274     if (kColumnsList[i].has_real_value)
275       CreateGroupColumnList(column_id + "Value", index, column_length, val);
276   }
277
278   return val;
279 }
280
281 void TaskManagerHandler::CreateGroupColumnList(const std::string& column_name,
282                                                const int index,
283                                                const int length,
284                                                DictionaryValue* val) {
285   ListValue* list = new ListValue();
286   for (int i = index; i < (index + length); ++i) {
287     list->Append(CreateColumnValue(column_name, i));
288   }
289   val->Set(column_name, list);
290 }
291
292 base::Value* TaskManagerHandler::CreateColumnValue(
293     const std::string& column_name,
294     const int i) {
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)));
301   }
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);
316   }
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);
323   }
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);
330   }
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()));
338   }
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));
350   }
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);
355   }
356   if (column_name == "webCoreScriptsCacheSize") {
357     return Value::CreateStringValue(
358         model_->GetResourceWebCoreScriptsCacheSize(i));
359   }
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);
364   }
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);
371   }
372   if (column_name == "fps")
373     return Value::CreateStringValue(model_->GetResourceFPS(i));
374   if (column_name == "fpsValue") {
375     float fps;
376     model_->GetFPS(i, &fps);
377     return Value::CreateDoubleValue(fps);
378   }
379   if (column_name == "videoMemory")
380     return Value::CreateStringValue(model_->GetResourceVideoMemory(i));
381   if (column_name == "videoMemoryValue") {
382     size_t video_memory;
383     bool has_duplicates;
384     double value;
385     if (model_->GetVideoMemory(i, &video_memory, &has_duplicates))
386       value = static_cast<double>(video_memory);
387     else
388       value = 0;
389     return Value::CreateDoubleValue(value);
390   }
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);
397   }
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));
405   }
406   if (column_name == "v8MemoryAllocatedSizeValue") {
407     size_t v8_memory;
408     model_->GetV8Memory(i, &v8_memory);
409     return Value::CreateDoubleValue(v8_memory);
410   }
411   if (column_name == "canInspect")
412     return Value::CreateBooleanValue(model_->CanInspect(i));
413   if (column_name == "canActivate")
414     return Value::CreateBooleanValue(model_->CanActivate(i));
415
416   NOTREACHED();
417   return NULL;
418 }