OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/new_task_manager_view.h" | 5 #include "chrome/browser/ui/views/new_task_manager_view.h" |
6 | 6 |
7 #include <map> | |
8 | |
9 #include "base/i18n/number_formatting.h" | |
10 #include "base/prefs/pref_service.h" | 7 #include "base/prefs/pref_service.h" |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "base/strings/stringprintf.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "chrome/browser/browser_process.h" | 8 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/profiles/profile_manager.h" | 9 #include "chrome/browser/profiles/profile_manager.h" |
16 #include "chrome/browser/profiles/profile_window.h" | 10 #include "chrome/browser/profiles/profile_window.h" |
17 #include "chrome/browser/task_management/task_manager_interface.h" | |
18 #include "chrome/browser/task_management/task_manager_observer.h" | 11 #include "chrome/browser/task_management/task_manager_observer.h" |
| 12 #include "chrome/browser/ui/task_manager/task_manager_columns.h" |
19 #include "chrome/browser/ui/user_manager.h" | 13 #include "chrome/browser/ui/user_manager.h" |
20 #include "chrome/common/pref_names.h" | 14 #include "chrome/common/pref_names.h" |
21 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
22 #include "chrome/grit/chromium_strings.h" | 16 #include "chrome/grit/chromium_strings.h" |
23 #include "chrome/grit/generated_resources.h" | 17 #include "chrome/grit/generated_resources.h" |
24 #include "components/nacl/browser/nacl_browser.h" | |
25 #include "content/public/common/result_codes.h" | |
26 #include "third_party/WebKit/public/web/WebCache.h" | |
27 #include "ui/base/l10n/l10n_util.h" | 18 #include "ui/base/l10n/l10n_util.h" |
28 #include "ui/base/models/table_model_observer.h" | 19 #include "ui/base/models/table_model_observer.h" |
29 #include "ui/base/text/bytes_formatting.h" | |
30 #include "ui/views/controls/label.h" | 20 #include "ui/views/controls/label.h" |
31 #include "ui/views/controls/link.h" | 21 #include "ui/views/controls/link.h" |
32 #include "ui/views/controls/table/table_grouper.h" | |
33 #include "ui/views/controls/table/table_view.h" | 22 #include "ui/views/controls/table/table_view.h" |
34 #include "ui/views/layout/layout_constants.h" | 23 #include "ui/views/layout/layout_constants.h" |
35 #include "ui/views/view.h" | 24 #include "ui/views/view.h" |
36 #include "ui/views/widget/widget.h" | 25 #include "ui/views/widget/widget.h" |
37 | 26 |
38 #if defined(USE_ASH) | 27 #if defined(USE_ASH) |
39 #include "ash/shelf/shelf_util.h" | 28 #include "ash/shelf/shelf_util.h" |
40 #include "ash/wm/window_util.h" | 29 #include "ash/wm/window_util.h" |
41 #include "grit/ash_resources.h" | 30 #include "grit/ash_resources.h" |
42 #endif // defined(USE_ASH) | 31 #endif // defined(USE_ASH) |
43 | 32 |
44 #if defined(OS_WIN) | 33 #if defined(OS_WIN) |
45 #include "chrome/browser/shell_integration.h" | 34 #include "chrome/browser/shell_integration.h" |
46 #include "ui/base/win/shell.h" | 35 #include "ui/base/win/shell.h" |
47 #include "ui/views/win/hwnd_util.h" | 36 #include "ui/views/win/hwnd_util.h" |
48 #endif // defined(OS_WIN) | 37 #endif // defined(OS_WIN) |
49 | 38 |
50 namespace task_management { | 39 namespace task_management { |
51 | 40 |
52 namespace { | 41 namespace { |
53 | 42 |
54 NewTaskManagerView* g_task_manager_view = nullptr; | 43 NewTaskManagerView* g_task_manager_view = nullptr; |
55 | 44 |
56 #if defined(OS_MACOSX) | |
57 // Match Activity Monitor's default refresh rate. | |
58 const int64 kRefreshTimeMS = 2000; | |
59 | |
60 // Activity Monitor shows %cpu with one decimal digit -- be consistent with | |
61 // that. | |
62 const char kCpuTextFormatString[] = "%.1f"; | |
63 #else | |
64 const int64 kRefreshTimeMS = 1000; | |
65 const char kCpuTextFormatString[] = "%.0f"; | |
66 #endif // defined(OS_MACOSX) | |
67 | |
68 // The columns that are shared by a group will show the value of the column | |
69 // only once per group. | |
70 bool IsSharedByGroup(int column_id) { | |
71 switch (column_id) { | |
72 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: | |
73 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: | |
74 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: | |
75 case IDS_TASK_MANAGER_CPU_COLUMN: | |
76 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: | |
77 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: | |
78 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: | |
79 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN: | |
80 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: | |
81 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: | |
82 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: | |
83 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: | |
84 return true; | |
85 default: | |
86 return false; | |
87 } | |
88 } | |
89 | |
90 // Opens the "about:memory" for the "stats for nerds" link. | 45 // Opens the "about:memory" for the "stats for nerds" link. |
91 void OpenAboutMemory(chrome::HostDesktopType desktop_type) { | 46 void OpenAboutMemory(chrome::HostDesktopType desktop_type) { |
92 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); | 47 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); |
93 if (profile->IsGuestSession() && | 48 if (profile->IsGuestSession() && |
94 !g_browser_process->local_state()->GetBoolean( | 49 !g_browser_process->local_state()->GetBoolean( |
95 prefs::kBrowserGuestModeEnabled)) { | 50 prefs::kBrowserGuestModeEnabled)) { |
96 UserManager::Show(base::FilePath(), | 51 UserManager::Show(base::FilePath(), |
97 profiles::USER_MANAGER_NO_TUTORIAL, | 52 profiles::USER_MANAGER_NO_TUTORIAL, |
98 profiles::USER_MANAGER_SELECT_PROFILE_CHROME_MEMORY); | 53 profiles::USER_MANAGER_SELECT_PROFILE_CHROME_MEMORY); |
99 return; | 54 return; |
100 } | 55 } |
101 | 56 |
102 chrome::NavigateParams params(profile, | 57 chrome::NavigateParams params(profile, |
103 GURL(chrome::kChromeUIMemoryURL), | 58 GURL(chrome::kChromeUIMemoryURL), |
104 ui::PAGE_TRANSITION_LINK); | 59 ui::PAGE_TRANSITION_LINK); |
105 params.disposition = NEW_FOREGROUND_TAB; | 60 params.disposition = NEW_FOREGROUND_TAB; |
106 params.host_desktop_type = desktop_type; | 61 params.host_desktop_type = desktop_type; |
107 chrome::Navigate(¶ms); | 62 chrome::Navigate(¶ms); |
108 } | 63 } |
109 | 64 |
110 // Used to sort various column values. | |
111 template <class T> | |
112 int ValueCompare(T value1, T value2) { | |
113 if (value1 == value2) | |
114 return 0; | |
115 return value1 < value2 ? -1 : 1; | |
116 } | |
117 | |
118 // Used when one or both of the results to compare are unavailable. | |
119 int OrderUnavailableValue(bool v1, bool v2) { | |
120 if (!v1 && !v2) | |
121 return 0; | |
122 return v1 ? 1 : -1; | |
123 } | |
124 | |
125 // A class to stringify the task manager's values into string16s and to | |
126 // cache the common strings that will be reused many times like "N/A" and so on. | |
127 class TaskManagerValuesStringifier { | |
128 public: | |
129 TaskManagerValuesStringifier() | |
130 : n_a_string_(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT)), | |
131 zero_string_(base::ASCIIToUTF16("0")), | |
132 asterisk_string_(base::ASCIIToUTF16("*")), | |
133 unknown_string_(l10n_util::GetStringUTF16( | |
134 IDS_TASK_MANAGER_UNKNOWN_VALUE_TEXT)) { | |
135 } | |
136 | |
137 ~TaskManagerValuesStringifier() {} | |
138 | |
139 base::string16 GetCpuUsageText(double cpu_usage) { | |
140 return base::UTF8ToUTF16(base::StringPrintf(kCpuTextFormatString, | |
141 cpu_usage)); | |
142 } | |
143 | |
144 base::string16 GetMemoryUsageText(int64 memory_usage, bool has_duplicates) { | |
145 if (memory_usage == -1) | |
146 return n_a_string_; | |
147 | |
148 #if defined(OS_MACOSX) | |
149 // System expectation is to show "100 kB", "200 MB", etc. | |
150 // TODO(thakis): [This TODO has been taken as is from the old task manager]: | |
151 // Switch to metric units (as opposed to powers of two). | |
152 base::string16 memory_text = ui::FormatBytes(memory_usage); | |
153 #else | |
154 base::string16 memory_text = base::FormatNumber(memory_usage / 1024); | |
155 // Adjust number string if necessary. | |
156 base::i18n::AdjustStringForLocaleDirection(&memory_text); | |
157 memory_text = l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_MEM_CELL_TEXT, | |
158 memory_text); | |
159 #endif // defined(OS_MACOSX) | |
160 | |
161 if (has_duplicates) | |
162 memory_text += asterisk_string_; | |
163 | |
164 return memory_text; | |
165 } | |
166 | |
167 base::string16 GetIdleWakeupsText(int idle_wakeups) { | |
168 if (idle_wakeups == -1) | |
169 return n_a_string_; | |
170 | |
171 return base::FormatNumber(idle_wakeups); | |
172 } | |
173 | |
174 base::string16 GetNaClPortText(int nacl_port) { | |
175 if (nacl_port == nacl::kGdbDebugStubPortUnused) | |
176 return n_a_string_; | |
177 | |
178 if (nacl_port == nacl::kGdbDebugStubPortUnknown) | |
179 return unknown_string_; | |
180 | |
181 return base::IntToString16(nacl_port); | |
182 } | |
183 | |
184 base::string16 GetWindowsHandlesText(int64 current, int64 peak) { | |
185 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_HANDLES_CELL_TEXT, | |
186 base::Int64ToString16(current), | |
187 base::Int64ToString16(peak)); | |
188 } | |
189 | |
190 base::string16 GetNetworkUsageText(int64 network_usage) { | |
191 if (network_usage == -1) | |
192 return n_a_string_; | |
193 | |
194 if (network_usage == 0) | |
195 return zero_string_; | |
196 | |
197 base::string16 net_byte = ui::FormatSpeed(network_usage); | |
198 // Force number string to have LTR directionality. | |
199 return base::i18n::GetDisplayStringInLTRDirectionality(net_byte); | |
200 } | |
201 | |
202 base::string16 GetProcessIdText(base::ProcessId proc_id) { | |
203 return base::IntToString16(proc_id); | |
204 } | |
205 | |
206 base::string16 FormatAllocatedAndUsedMemory(int64 allocated, int64 used) { | |
207 return l10n_util::GetStringFUTF16( | |
208 IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT, | |
209 ui::FormatBytesWithUnits(allocated, ui::DATA_UNITS_KIBIBYTE, false), | |
210 ui::FormatBytesWithUnits(used, ui::DATA_UNITS_KIBIBYTE, false)); | |
211 } | |
212 | |
213 base::string16 GetWebCacheStatText( | |
214 const blink::WebCache::ResourceTypeStat& stat) { | |
215 return FormatAllocatedAndUsedMemory(stat.size, stat.liveSize); | |
216 } | |
217 | |
218 const base::string16& n_a_string() const { return n_a_string_; } | |
219 const base::string16& zero_string() const { return zero_string_; } | |
220 const base::string16& asterisk_string() const { return asterisk_string_; } | |
221 const base::string16& unknown_string() const { return unknown_string_; } | |
222 | |
223 private: | |
224 // The localized string "N/A". | |
225 const base::string16 n_a_string_; | |
226 | |
227 // The value 0 as a string "0". | |
228 const base::string16 zero_string_; | |
229 | |
230 // The string "*" that is used to show that there exists duplicates in the | |
231 // GPU memory. | |
232 const base::string16 asterisk_string_; | |
233 | |
234 // The string "Unknown". | |
235 const base::string16 unknown_string_; | |
236 | |
237 DISALLOW_COPY_AND_ASSIGN(TaskManagerValuesStringifier); | |
238 }; | |
239 | |
240 } // namespace | 65 } // namespace |
241 | 66 |
242 //////////////////////////////////////////////////////////////////////////////// | |
243 | |
244 // IMPORTANT: Do NOT change the below list without changing the COLUMN_LIST | |
245 // macro below. | |
246 const TableColumnData kColumns[] = { | |
247 { IDS_TASK_MANAGER_TASK_COLUMN, ui::TableColumn::LEFT, -1, 1, true, true, | |
248 true }, | |
249 { IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, ui::TableColumn::LEFT, -1, 0, true, | |
250 true, false }, | |
251 { IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
252 false, true }, | |
253 { IDS_TASK_MANAGER_SHARED_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
254 false, false }, | |
255 { IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
256 false, false }, | |
257 { IDS_TASK_MANAGER_CPU_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, false, | |
258 true }, | |
259 { IDS_TASK_MANAGER_NET_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, false, | |
260 true }, | |
261 { IDS_TASK_MANAGER_PROCESS_ID_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
262 true, true }, | |
263 | |
264 #if defined(OS_WIN) | |
265 { IDS_TASK_MANAGER_GDI_HANDLES_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
266 false, false }, | |
267 { IDS_TASK_MANAGER_USER_HANDLES_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
268 false, false }, | |
269 #endif | |
270 | |
271 { IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, ui::TableColumn::RIGHT, -1, 0, | |
272 true, false, false }, | |
273 { IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, ui::TableColumn::RIGHT, -1, | |
274 0, true, false, false }, | |
275 { IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, ui::TableColumn::RIGHT, -1, 0, | |
276 true, false, false }, | |
277 { IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
278 false, false }, | |
279 { IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, ui::TableColumn::RIGHT, -1, 0, | |
280 true, false, false }, | |
281 | |
282 #if !defined(DISABLE_NACL) | |
283 { IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN, ui::TableColumn::RIGHT, -1, 0, | |
284 true, true, false }, | |
285 #endif // !defined(DISABLE_NACL) | |
286 | |
287 { IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, ui::TableColumn::RIGHT, | |
288 -1, 0, true, false, false }, | |
289 | |
290 #if defined(OS_MACOSX) || defined(OS_LINUX) | |
291 // TODO(port): Port the idle wakeups per second to platforms other than Linux | |
292 // and MacOS (http://crbug.com/120488). | |
293 { IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN, ui::TableColumn::RIGHT, -1, 0, true, | |
294 false, false }, | |
295 #endif // defined(OS_MACOSX) || defined(OS_LINUX) | |
296 }; | |
297 | |
298 const size_t kColumnsSize = arraysize(kColumns); | |
299 | |
300 const char kSortColumnIdKey[] = "sort_column_id"; | |
301 const char kSortIsAscendingKey[] = "sort_is_ascending"; | |
302 | |
303 // We can't use the integer IDs of the columns converted to strings as session | |
304 // restore keys. These integer values can change from one build to another as | |
305 // they are generated. Instead we use the literal string value of the column | |
306 // ID symbol (i.e. for the ID IDS_TASK_MANAGER_TASK_COLUMN, we use the literal | |
307 // string "IDS_TASK_MANAGER_TASK_COLUMN". The following macros help us | |
308 // efficiently get the literal ID for the integer value. | |
309 #define COLUMNS_LITS(def) \ | |
310 def(IDS_TASK_MANAGER_TASK_COLUMN) \ | |
311 def(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN) \ | |
312 def(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN) \ | |
313 def(IDS_TASK_MANAGER_SHARED_MEM_COLUMN) \ | |
314 def(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN) \ | |
315 def(IDS_TASK_MANAGER_CPU_COLUMN) \ | |
316 def(IDS_TASK_MANAGER_NET_COLUMN) \ | |
317 def(IDS_TASK_MANAGER_PROCESS_ID_COLUMN) \ | |
318 def(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN) \ | |
319 def(IDS_TASK_MANAGER_USER_HANDLES_COLUMN) \ | |
320 def(IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN) \ | |
321 def(IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN) \ | |
322 def(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN) \ | |
323 def(IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN) \ | |
324 def(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN) \ | |
325 def(IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN) \ | |
326 def(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN) \ | |
327 def(IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN) | |
328 // Add to the above list in the macro any new IDs added in the future. Also | |
329 // remove the removed ones. | |
330 | |
331 #define COLUMN_ID_AS_STRING(col_id) case col_id: return std::string(#col_id); | |
332 | |
333 std::string GetColumnIdAsString(int column_id) { | |
334 switch (column_id) { | |
335 COLUMNS_LITS(COLUMN_ID_AS_STRING) | |
336 default: | |
337 NOTREACHED(); | |
338 return std::string(); | |
339 } | |
340 } | |
341 | |
342 //////////////////////////////////////////////////////////////////////////////// | |
343 | |
344 // The table model of the task manager table view that will observe the | |
345 // task manager backend and adapt its interface to match the requirements of the | |
346 // TableView. | |
347 class NewTaskManagerView::TableModel | |
348 : public TaskManagerObserver, | |
349 public ui::TableModel, | |
350 public views::TableGrouper { | |
351 public: | |
352 explicit TableModel(int64 refresh_flags); | |
353 ~TableModel() override; | |
354 | |
355 // ui::TableModel: | |
356 int RowCount() override; | |
357 base::string16 GetText(int row, int column) override; | |
358 gfx::ImageSkia GetIcon(int row) override; | |
359 void SetObserver(ui::TableModelObserver* observer) override; | |
360 int CompareValues(int row1, int row2, int column_id) override; | |
361 | |
362 // views::TableGrouper: | |
363 void GetGroupRange(int model_index, views::GroupRange* range) override; | |
364 | |
365 // task_management::TaskManagerObserver: | |
366 void OnTaskAdded(TaskId id) override; | |
367 void OnTaskToBeRemoved(TaskId id) override; | |
368 void OnTasksRefreshed(const TaskIdList& task_ids) override; | |
369 | |
370 // Start / stop observing the task manager. | |
371 void StartUpdating(); | |
372 void StopUpdating(); | |
373 | |
374 // Activates the browser tab associated with the process in the specified | |
375 // |row_index|. | |
376 void ActivateTask(int row_index); | |
377 | |
378 // Kills the process on which the task at |row_index| is running. | |
379 void KillTask(int row_index); | |
380 | |
381 // Based on the given |visibility| and the |column_id|, a particular refresh | |
382 // type will be enabled or disabled. Multiple columns can map to the same | |
383 // refresh type, for that we need |table| to determine if any is visible. | |
384 void UpdateRefreshTypes(views::TableView* table, | |
385 int column_id, | |
386 bool visibility); | |
387 | |
388 | |
389 // Checks if the task at |row_index| is running on the browser process. | |
390 bool IsBrowserProcess(int row_index) const; | |
391 | |
392 private: | |
393 void OnRefresh(); | |
394 | |
395 // Checks whether the task at |row_index| is the first task in its process | |
396 // group of tasks. | |
397 bool IsTaskFirstInGroup(int row_index) const; | |
398 | |
399 // The table model observer that will be set by the table view of the task | |
400 // manager. | |
401 ui::TableModelObserver* table_model_observer_; | |
402 | |
403 // The sorted list of task IDs by process ID then by task ID. | |
404 std::vector<TaskId> tasks_; | |
405 | |
406 // The owned task manager values stringifier that will be used to convert the | |
407 // values to string16. | |
408 TaskManagerValuesStringifier stringifier_; | |
409 | |
410 DISALLOW_COPY_AND_ASSIGN(TableModel); | |
411 }; | |
412 | |
413 //////////////////////////////////////////////////////////////////////////////// | |
414 // NewTaskManagerView::TableModel Implementation: | |
415 //////////////////////////////////////////////////////////////////////////////// | |
416 | |
417 NewTaskManagerView::TableModel::TableModel(int64 refresh_flags) | |
418 : TaskManagerObserver(base::TimeDelta::FromMilliseconds(kRefreshTimeMS), | |
419 refresh_flags), | |
420 table_model_observer_(nullptr) { | |
421 } | |
422 | |
423 NewTaskManagerView::TableModel::~TableModel() { | |
424 } | |
425 | |
426 int NewTaskManagerView::TableModel::RowCount() { | |
427 return static_cast<int>(tasks_.size()); | |
428 } | |
429 | |
430 base::string16 NewTaskManagerView::TableModel::GetText(int row, int column) { | |
431 if (IsSharedByGroup(column) && !IsTaskFirstInGroup(row)) | |
432 return base::string16(); | |
433 | |
434 switch (column) { | |
435 case IDS_TASK_MANAGER_TASK_COLUMN: | |
436 return observed_task_manager()->GetTitle(tasks_[row]); | |
437 | |
438 case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN: | |
439 return observed_task_manager()->GetProfileName(tasks_[row]); | |
440 | |
441 case IDS_TASK_MANAGER_NET_COLUMN: | |
442 return stringifier_.GetNetworkUsageText( | |
443 observed_task_manager()->GetNetworkUsage(tasks_[row])); | |
444 | |
445 case IDS_TASK_MANAGER_CPU_COLUMN: | |
446 return stringifier_.GetCpuUsageText( | |
447 observed_task_manager()->GetCpuUsage(tasks_[row])); | |
448 | |
449 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: | |
450 return stringifier_.GetMemoryUsageText( | |
451 observed_task_manager()->GetPrivateMemoryUsage(tasks_[row]), false); | |
452 | |
453 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: | |
454 return stringifier_.GetMemoryUsageText( | |
455 observed_task_manager()->GetSharedMemoryUsage(tasks_[row]), false); | |
456 | |
457 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: | |
458 return stringifier_.GetMemoryUsageText( | |
459 observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row]), false); | |
460 | |
461 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: | |
462 return stringifier_.GetProcessIdText( | |
463 observed_task_manager()->GetProcessId(tasks_[row])); | |
464 | |
465 case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: { | |
466 int64 current, peak; | |
467 observed_task_manager()->GetGDIHandles(tasks_[row], ¤t, &peak); | |
468 return stringifier_.GetWindowsHandlesText(current, peak); | |
469 } | |
470 | |
471 case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: { | |
472 int64 current, peak; | |
473 observed_task_manager()->GetUSERHandles(tasks_[row], ¤t, &peak); | |
474 return stringifier_.GetWindowsHandlesText(current, peak); | |
475 } | |
476 | |
477 case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN: | |
478 return stringifier_.GetIdleWakeupsText( | |
479 observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row])); | |
480 | |
481 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: { | |
482 blink::WebCache::ResourceTypeStats stats; | |
483 if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats)) | |
484 return stringifier_.GetWebCacheStatText(stats.images); | |
485 return stringifier_.n_a_string(); | |
486 } | |
487 | |
488 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: { | |
489 blink::WebCache::ResourceTypeStats stats; | |
490 if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats)) | |
491 return stringifier_.GetWebCacheStatText(stats.scripts); | |
492 return stringifier_.n_a_string(); | |
493 } | |
494 | |
495 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: { | |
496 blink::WebCache::ResourceTypeStats stats; | |
497 if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats)) | |
498 return stringifier_.GetWebCacheStatText(stats.cssStyleSheets); | |
499 return stringifier_.n_a_string(); | |
500 } | |
501 | |
502 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: { | |
503 bool has_duplicates = false; | |
504 return stringifier_.GetMemoryUsageText( | |
505 observed_task_manager()->GetGpuMemoryUsage(tasks_[row], | |
506 &has_duplicates), | |
507 has_duplicates); | |
508 } | |
509 | |
510 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN: | |
511 return stringifier_.GetMemoryUsageText( | |
512 observed_task_manager()->GetSqliteMemoryUsed(tasks_[row]), false); | |
513 | |
514 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: { | |
515 int64 v8_allocated, v8_used; | |
516 if (observed_task_manager()->GetV8Memory(tasks_[row], | |
517 &v8_allocated, | |
518 &v8_used)) { | |
519 return stringifier_.FormatAllocatedAndUsedMemory(v8_allocated, | |
520 v8_used); | |
521 } | |
522 return stringifier_.n_a_string(); | |
523 } | |
524 | |
525 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: | |
526 return stringifier_.GetNaClPortText( | |
527 observed_task_manager()->GetNaClDebugStubPort(tasks_[row])); | |
528 | |
529 default: | |
530 NOTREACHED(); | |
531 return base::string16(); | |
532 } | |
533 } | |
534 | |
535 gfx::ImageSkia NewTaskManagerView::TableModel::GetIcon(int row) { | |
536 return observed_task_manager()->GetIcon(tasks_[row]); | |
537 } | |
538 | |
539 void NewTaskManagerView::TableModel::SetObserver( | |
540 ui::TableModelObserver* observer) { | |
541 table_model_observer_ = observer; | |
542 } | |
543 | |
544 int NewTaskManagerView::TableModel::CompareValues(int row1, | |
545 int row2, | |
546 int column_id) { | |
547 switch (column_id) { | |
548 case IDS_TASK_MANAGER_TASK_COLUMN: | |
549 case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN: | |
550 return ui::TableModel::CompareValues(row1, row2, column_id); | |
551 | |
552 case IDS_TASK_MANAGER_NET_COLUMN: | |
553 return ValueCompare( | |
554 observed_task_manager()->GetNetworkUsage(tasks_[row1]), | |
555 observed_task_manager()->GetNetworkUsage(tasks_[row2])); | |
556 | |
557 case IDS_TASK_MANAGER_CPU_COLUMN: | |
558 return ValueCompare(observed_task_manager()->GetCpuUsage(tasks_[row1]), | |
559 observed_task_manager()->GetCpuUsage(tasks_[row2])); | |
560 | |
561 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: | |
562 return ValueCompare( | |
563 observed_task_manager()->GetPrivateMemoryUsage(tasks_[row1]), | |
564 observed_task_manager()->GetPrivateMemoryUsage(tasks_[row2])); | |
565 | |
566 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: | |
567 return ValueCompare( | |
568 observed_task_manager()->GetSharedMemoryUsage(tasks_[row1]), | |
569 observed_task_manager()->GetSharedMemoryUsage(tasks_[row2])); | |
570 | |
571 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: | |
572 return ValueCompare( | |
573 observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row1]), | |
574 observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row2])); | |
575 | |
576 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: | |
577 return ValueCompare( | |
578 observed_task_manager()->GetNaClDebugStubPort(tasks_[row1]), | |
579 observed_task_manager()->GetNaClDebugStubPort(tasks_[row2])); | |
580 | |
581 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: | |
582 return ValueCompare(observed_task_manager()->GetProcessId(tasks_[row1]), | |
583 observed_task_manager()->GetProcessId(tasks_[row2])); | |
584 | |
585 case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: { | |
586 int64 current1, peak1, current2, peak2; | |
587 observed_task_manager()->GetGDIHandles(tasks_[row1], ¤t1, &peak1); | |
588 observed_task_manager()->GetGDIHandles(tasks_[row2], ¤t2, &peak2); | |
589 return ValueCompare(current1, current2); | |
590 } | |
591 | |
592 case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: { | |
593 int64 current1, peak1, current2, peak2; | |
594 observed_task_manager()->GetUSERHandles(tasks_[row1], ¤t1, &peak1); | |
595 observed_task_manager()->GetUSERHandles(tasks_[row2], ¤t2, &peak2); | |
596 return ValueCompare(current1, current2); | |
597 } | |
598 | |
599 case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN: | |
600 return ValueCompare( | |
601 observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row1]), | |
602 observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row2])); | |
603 | |
604 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: | |
605 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: | |
606 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: { | |
607 blink::WebCache::ResourceTypeStats stats1; | |
608 blink::WebCache::ResourceTypeStats stats2; | |
609 bool row1_stats_valid = | |
610 observed_task_manager()->GetWebCacheStats(tasks_[row1], &stats1); | |
611 bool row2_stats_valid = | |
612 observed_task_manager()->GetWebCacheStats(tasks_[row2], &stats2); | |
613 if (!row1_stats_valid || !row2_stats_valid) | |
614 return OrderUnavailableValue(row1_stats_valid, row2_stats_valid); | |
615 | |
616 switch (column_id) { | |
617 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: | |
618 return ValueCompare(stats1.images.size, stats2.images.size); | |
619 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: | |
620 return ValueCompare(stats1.scripts.size, stats2.scripts.size); | |
621 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: | |
622 return ValueCompare(stats1.cssStyleSheets.size, | |
623 stats2.cssStyleSheets.size); | |
624 default: | |
625 NOTREACHED(); | |
626 return 0; | |
627 } | |
628 } | |
629 | |
630 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: { | |
631 bool has_duplicates; | |
632 return ValueCompare( | |
633 observed_task_manager()->GetGpuMemoryUsage(tasks_[row1], | |
634 &has_duplicates), | |
635 observed_task_manager()->GetGpuMemoryUsage(tasks_[row2], | |
636 &has_duplicates)); | |
637 } | |
638 | |
639 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: { | |
640 int64 allocated1, allocated2, used1, used2; | |
641 observed_task_manager()->GetV8Memory(tasks_[row1], &allocated1, &used1); | |
642 observed_task_manager()->GetV8Memory(tasks_[row2], &allocated2, &used2); | |
643 return ValueCompare(allocated1, allocated2); | |
644 } | |
645 | |
646 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN: | |
647 return ValueCompare( | |
648 observed_task_manager()->GetSqliteMemoryUsed(tasks_[row1]), | |
649 observed_task_manager()->GetSqliteMemoryUsed(tasks_[row2])); | |
650 | |
651 default: | |
652 NOTREACHED(); | |
653 return 0; | |
654 } | |
655 } | |
656 | |
657 void NewTaskManagerView::TableModel::GetGroupRange(int model_index, | |
658 views::GroupRange* range) { | |
659 int i = model_index; | |
660 for ( ; i >= 0; --i) { | |
661 if (IsTaskFirstInGroup(i)) | |
662 break; | |
663 } | |
664 | |
665 CHECK_GE(i, 0); | |
666 | |
667 range->start = i; | |
668 range->length = observed_task_manager()->GetNumberOfTasksOnSameProcess( | |
669 tasks_[model_index]); | |
670 } | |
671 | |
672 void NewTaskManagerView::TableModel::OnTaskAdded(TaskId id) { | |
673 // For the table view scrollbar to behave correctly we must inform it that | |
674 // a new task has been added. | |
675 | |
676 // We will get a newly sorted list from the task manager as opposed to just | |
677 // adding |id| to |tasks_| because we want to keep |tasks_| sorted by proc IDs | |
678 // and then by Task IDs. | |
679 tasks_ = observed_task_manager()->GetTaskIdsList(); | |
680 if (table_model_observer_) | |
681 table_model_observer_->OnItemsAdded(RowCount() - 1, 1); | |
682 } | |
683 | |
684 void NewTaskManagerView::TableModel::OnTaskToBeRemoved(TaskId id) { | |
685 auto index = std::find(tasks_.begin(), tasks_.end(), id); | |
686 if (index == tasks_.end()) | |
687 return; | |
688 auto removed_index = index - tasks_.begin(); | |
689 tasks_.erase(index); | |
690 if (table_model_observer_) | |
691 table_model_observer_->OnItemsRemoved(removed_index, 1); | |
692 } | |
693 | |
694 void NewTaskManagerView::TableModel::OnTasksRefreshed( | |
695 const TaskIdList& task_ids) { | |
696 tasks_ = task_ids; | |
697 OnRefresh(); | |
698 } | |
699 | |
700 void NewTaskManagerView::TableModel::StartUpdating() { | |
701 TaskManagerInterface::GetTaskManager()->AddObserver(this); | |
702 tasks_ = observed_task_manager()->GetTaskIdsList(); | |
703 OnRefresh(); | |
704 } | |
705 | |
706 void NewTaskManagerView::TableModel::StopUpdating() { | |
707 observed_task_manager()->RemoveObserver(this); | |
708 } | |
709 | |
710 void NewTaskManagerView::TableModel::ActivateTask(int row_index) { | |
711 observed_task_manager()->ActivateTask(tasks_[row_index]); | |
712 } | |
713 | |
714 void NewTaskManagerView::TableModel::KillTask(int row_index) { | |
715 base::ProcessId proc_id = observed_task_manager()->GetProcessId( | |
716 tasks_[row_index]); | |
717 | |
718 DCHECK_NE(proc_id, base::GetCurrentProcId()); | |
719 | |
720 base::Process process = base::Process::Open(proc_id); | |
721 process.Terminate(content::RESULT_CODE_KILLED, false); | |
722 } | |
723 | |
724 void NewTaskManagerView::TableModel::UpdateRefreshTypes(views::TableView* table, | |
725 int column_id, | |
726 bool visibility) { | |
727 bool new_visibility = visibility; | |
728 RefreshType type = REFRESH_TYPE_NONE; | |
729 switch (column_id) { | |
730 case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN: | |
731 case IDS_TASK_MANAGER_TASK_COLUMN: | |
732 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN: | |
733 return; // The data is these columns do not change. | |
734 | |
735 case IDS_TASK_MANAGER_NET_COLUMN: | |
736 type = REFRESH_TYPE_NETWORK_USAGE; | |
737 break; | |
738 | |
739 case IDS_TASK_MANAGER_CPU_COLUMN: | |
740 type = REFRESH_TYPE_CPU; | |
741 break; | |
742 | |
743 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: | |
744 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: | |
745 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: | |
746 type = REFRESH_TYPE_MEMORY; | |
747 if (table->IsColumnVisible(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN) || | |
748 table->IsColumnVisible(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN) || | |
749 table->IsColumnVisible(IDS_TASK_MANAGER_SHARED_MEM_COLUMN)) { | |
750 new_visibility = true; | |
751 } | |
752 break; | |
753 | |
754 case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: | |
755 case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: | |
756 type = REFRESH_TYPE_HANDLES; | |
757 if (table->IsColumnVisible(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN) || | |
758 table->IsColumnVisible(IDS_TASK_MANAGER_USER_HANDLES_COLUMN)) { | |
759 new_visibility = true; | |
760 } | |
761 break; | |
762 | |
763 case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN: | |
764 type = REFRESH_TYPE_IDLE_WAKEUPS; | |
765 break; | |
766 | |
767 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: | |
768 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: | |
769 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: | |
770 type = REFRESH_TYPE_WEBCACHE_STATS; | |
771 if (table->IsColumnVisible(IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN) || | |
772 table->IsColumnVisible( | |
773 IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN) || | |
774 table->IsColumnVisible(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN)) { | |
775 new_visibility = true; | |
776 } | |
777 break; | |
778 | |
779 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: | |
780 type = REFRESH_TYPE_GPU_MEMORY; | |
781 break; | |
782 | |
783 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN: | |
784 type = REFRESH_TYPE_SQLITE_MEMORY; | |
785 break; | |
786 | |
787 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: | |
788 type = REFRESH_TYPE_V8_MEMORY; | |
789 break; | |
790 | |
791 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN: | |
792 type = REFRESH_TYPE_NACL; | |
793 break; | |
794 | |
795 default: | |
796 NOTREACHED(); | |
797 return; | |
798 } | |
799 | |
800 if (new_visibility) | |
801 AddRefreshType(type); | |
802 else | |
803 RemoveRefreshType(type); | |
804 } | |
805 | |
806 bool NewTaskManagerView::TableModel::IsBrowserProcess(int row_index) const { | |
807 return observed_task_manager()->GetProcessId(tasks_[row_index]) == | |
808 base::GetCurrentProcId(); | |
809 } | |
810 | |
811 void NewTaskManagerView::TableModel::OnRefresh() { | |
812 if (table_model_observer_) | |
813 table_model_observer_->OnItemsChanged(0, RowCount()); | |
814 } | |
815 | |
816 bool NewTaskManagerView::TableModel::IsTaskFirstInGroup(int row_index) const { | |
817 if (row_index == 0) | |
818 return true; | |
819 | |
820 return observed_task_manager()->GetProcessId(tasks_[row_index - 1]) != | |
821 observed_task_manager()->GetProcessId(tasks_[row_index]); | |
822 } | |
823 | |
824 //////////////////////////////////////////////////////////////////////////////// | |
825 // NewTaskManagerView Implementation: | |
826 //////////////////////////////////////////////////////////////////////////////// | |
827 | |
828 NewTaskManagerView::~NewTaskManagerView() { | 67 NewTaskManagerView::~NewTaskManagerView() { |
829 // Delete child views now, while our table model still exists. | 68 // Delete child views now, while our table model still exists. |
830 RemoveAllChildViews(true); | 69 RemoveAllChildViews(true); |
831 } | 70 } |
832 | 71 |
833 // static | 72 // static |
834 void NewTaskManagerView::Show(Browser* browser) { | 73 void NewTaskManagerView::Show(Browser* browser) { |
835 if (g_task_manager_view) { | 74 if (g_task_manager_view) { |
836 // If there's a Task manager window open already, just activate it. | 75 // If there's a Task manager window open already, just activate it. |
837 g_task_manager_view->GetWidget()->Activate(); | 76 g_task_manager_view->GetWidget()->Activate(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 native_window->title()); | 125 native_window->title()); |
887 #endif | 126 #endif |
888 } | 127 } |
889 | 128 |
890 // static | 129 // static |
891 void NewTaskManagerView::Hide() { | 130 void NewTaskManagerView::Hide() { |
892 if (g_task_manager_view) | 131 if (g_task_manager_view) |
893 g_task_manager_view->GetWidget()->Close(); | 132 g_task_manager_view->GetWidget()->Close(); |
894 } | 133 } |
895 | 134 |
| 135 bool NewTaskManagerView::IsColumnVisible(int column_id) const { |
| 136 return tab_table_->IsColumnVisible(column_id); |
| 137 } |
| 138 |
| 139 void NewTaskManagerView::SetColumnVisibility(int column_id, |
| 140 bool new_visibility) { |
| 141 tab_table_->SetColumnVisibility(column_id, new_visibility); |
| 142 } |
| 143 |
| 144 bool NewTaskManagerView::IsTableSorted() const { |
| 145 return tab_table_->is_sorted(); |
| 146 } |
| 147 |
| 148 TableSortDescriptor |
| 149 NewTaskManagerView::GetSortDescriptor() const { |
| 150 if (!IsTableSorted()) |
| 151 return TableSortDescriptor(); |
| 152 |
| 153 const auto& descriptor = tab_table_->sort_descriptors().front(); |
| 154 return TableSortDescriptor(descriptor.column_id, descriptor.ascending); |
| 155 } |
| 156 |
| 157 void NewTaskManagerView::ToggleSortOrder(int visible_column_index) { |
| 158 tab_table_->ToggleSortOrder(visible_column_index); |
| 159 } |
| 160 |
896 void NewTaskManagerView::Layout() { | 161 void NewTaskManagerView::Layout() { |
897 gfx::Size size = kill_button_->GetPreferredSize(); | 162 gfx::Size size = kill_button_->GetPreferredSize(); |
898 gfx::Rect parent_bounds = parent()->GetContentsBounds(); | 163 gfx::Rect parent_bounds = parent()->GetContentsBounds(); |
899 const int horizontal_margin = views::kPanelHorizMargin; | 164 const int horizontal_margin = views::kPanelHorizMargin; |
900 const int vertical_margin = views::kButtonVEdgeMargin; | 165 const int vertical_margin = views::kButtonVEdgeMargin; |
901 int x = width() - size.width() - horizontal_margin; | 166 int x = width() - size.width() - horizontal_margin; |
902 int y_buttons = parent_bounds.bottom() - size.height() - vertical_margin; | 167 int y_buttons = parent_bounds.bottom() - size.height() - vertical_margin; |
903 kill_button_->SetBounds(x, y_buttons, size.width(), size.height()); | 168 kill_button_->SetBounds(x, y_buttons, size.width(), size.height()); |
904 | 169 |
905 size = about_memory_link_->GetPreferredSize(); | 170 size = about_memory_link_->GetPreferredSize(); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 256 |
992 void NewTaskManagerView::WindowClosing() { | 257 void NewTaskManagerView::WindowClosing() { |
993 // Now that the window is closed, we can allow a new one to be opened. | 258 // Now that the window is closed, we can allow a new one to be opened. |
994 // (WindowClosing comes in asynchronously from the call to Close() and we | 259 // (WindowClosing comes in asynchronously from the call to Close() and we |
995 // may have already opened a new instance). | 260 // may have already opened a new instance). |
996 if (g_task_manager_view == this) { | 261 if (g_task_manager_view == this) { |
997 // We don't have to delete |g_task_manager_view| as we don't own it. It's | 262 // We don't have to delete |g_task_manager_view| as we don't own it. It's |
998 // owned by the Views hierarchy. | 263 // owned by the Views hierarchy. |
999 g_task_manager_view = nullptr; | 264 g_task_manager_view = nullptr; |
1000 } | 265 } |
1001 StoreColumnsSettings(); | 266 table_model_->StoreColumnsSettings(); |
1002 table_model_->StopUpdating(); | 267 table_model_->StopUpdating(); |
1003 } | 268 } |
1004 | 269 |
1005 bool NewTaskManagerView::UseNewStyleForThisDialog() const { | 270 bool NewTaskManagerView::UseNewStyleForThisDialog() const { |
1006 return false; | 271 return false; |
1007 } | 272 } |
1008 | 273 |
| 274 void NewTaskManagerView::GetGroupRange(int model_index, |
| 275 views::GroupRange* range) { |
| 276 table_model_->GetRowsGroupRange(model_index, &range->start, &range->length); |
| 277 } |
| 278 |
1009 void NewTaskManagerView::OnSelectionChanged() { | 279 void NewTaskManagerView::OnSelectionChanged() { |
1010 const ui::ListSelectionModel::SelectedIndices& selections( | 280 const ui::ListSelectionModel::SelectedIndices& selections( |
1011 tab_table_->selection_model().selected_indices()); | 281 tab_table_->selection_model().selected_indices()); |
1012 bool selection_contains_browser_process = false; | 282 bool selection_contains_browser_process = false; |
1013 for (const auto& selection : selections) { | 283 for (const auto& selection : selections) { |
1014 if (table_model_->IsBrowserProcess(selection)) { | 284 if (table_model_->IsBrowserProcess(selection)) { |
1015 selection_contains_browser_process = true; | 285 selection_contains_browser_process = true; |
1016 break; | 286 break; |
1017 } | 287 } |
1018 } | 288 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 return true; | 336 return true; |
1067 } | 337 } |
1068 | 338 |
1069 bool NewTaskManagerView::GetAcceleratorForCommandId( | 339 bool NewTaskManagerView::GetAcceleratorForCommandId( |
1070 int command_id, | 340 int command_id, |
1071 ui::Accelerator* accelerator) { | 341 ui::Accelerator* accelerator) { |
1072 return false; | 342 return false; |
1073 } | 343 } |
1074 | 344 |
1075 void NewTaskManagerView::ExecuteCommand(int id, int event_flags) { | 345 void NewTaskManagerView::ExecuteCommand(int id, int event_flags) { |
1076 ToggleColumnVisibility(id); | 346 table_model_->ToggleColumnVisibility(id); |
1077 } | 347 } |
1078 | 348 |
1079 NewTaskManagerView::NewTaskManagerView(chrome::HostDesktopType desktop_type) | 349 NewTaskManagerView::NewTaskManagerView(chrome::HostDesktopType desktop_type) |
1080 : table_model_( | 350 : kill_button_(nullptr), |
1081 new NewTaskManagerView::TableModel(REFRESH_TYPE_CPU | | |
1082 REFRESH_TYPE_MEMORY | | |
1083 REFRESH_TYPE_NETWORK_USAGE)), | |
1084 kill_button_(nullptr), | |
1085 about_memory_link_(nullptr), | 351 about_memory_link_(nullptr), |
1086 tab_table_(nullptr), | 352 tab_table_(nullptr), |
1087 tab_table_parent_(nullptr), | 353 tab_table_parent_(nullptr), |
1088 desktop_type_(desktop_type), | 354 desktop_type_(desktop_type), |
1089 is_always_on_top_(false) { | 355 is_always_on_top_(false) { |
1090 Init(); | 356 Init(); |
1091 } | 357 } |
1092 | 358 |
1093 // static | 359 // static |
1094 NewTaskManagerView* NewTaskManagerView::GetInstanceForTests() { | 360 NewTaskManagerView* NewTaskManagerView::GetInstanceForTests() { |
1095 return g_task_manager_view; | 361 return g_task_manager_view; |
1096 } | 362 } |
1097 | 363 |
1098 void NewTaskManagerView::Init() { | 364 void NewTaskManagerView::Init() { |
1099 columns_settings_.reset(new base::DictionaryValue); | |
1100 | |
1101 // Create the table columns. | 365 // Create the table columns. |
1102 for (size_t i = 0; i < kColumnsSize; ++i) { | 366 for (size_t i = 0; i < kColumnsSize; ++i) { |
1103 const auto& col_data = kColumns[i]; | 367 const auto& col_data = kColumns[i]; |
1104 columns_.push_back(ui::TableColumn(col_data.id, col_data.align, | 368 columns_.push_back(ui::TableColumn(col_data.id, col_data.align, |
1105 col_data.width, col_data.percent)); | 369 col_data.width, col_data.percent)); |
1106 columns_.back().sortable = col_data.sortable; | 370 columns_.back().sortable = col_data.sortable; |
1107 columns_.back().initial_sort_is_ascending = | 371 columns_.back().initial_sort_is_ascending = |
1108 col_data.initial_sort_is_ascending; | 372 col_data.initial_sort_is_ascending; |
1109 } | 373 } |
1110 | 374 |
1111 // Create the table view. | 375 // Create the table view. |
1112 tab_table_ = new views::TableView( | 376 tab_table_ = new views::TableView(nullptr, columns_, views::ICON_AND_TEXT, |
1113 table_model_.get(), columns_, views::ICON_AND_TEXT, false); | 377 false); |
1114 tab_table_->SetGrouper(table_model_.get()); | 378 table_model_.reset(new TaskManagerTableModel(REFRESH_TYPE_CPU | |
| 379 REFRESH_TYPE_MEMORY | |
| 380 REFRESH_TYPE_NETWORK_USAGE, |
| 381 this)); |
| 382 tab_table_->SetModel(table_model_.get()); |
| 383 tab_table_->SetGrouper(this); |
1115 tab_table_->SetObserver(this); | 384 tab_table_->SetObserver(this); |
1116 tab_table_->set_context_menu_controller(this); | 385 tab_table_->set_context_menu_controller(this); |
1117 set_context_menu_controller(this); | 386 set_context_menu_controller(this); |
1118 | 387 |
1119 RetrieveSavedColumnsSettingsAndUpdateTable(); | 388 table_model_->RetrieveSavedColumnsSettingsAndUpdateTable(); |
1120 | 389 |
1121 kill_button_ = new views::LabelButton(this, | 390 kill_button_ = new views::LabelButton(this, |
1122 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL)); | 391 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL)); |
1123 kill_button_->SetStyle(views::Button::STYLE_BUTTON); | 392 kill_button_->SetStyle(views::Button::STYLE_BUTTON); |
1124 | 393 |
1125 about_memory_link_ = new views::Link( | 394 about_memory_link_ = new views::Link( |
1126 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)); | 395 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)); |
1127 about_memory_link_->set_listener(this); | 396 about_memory_link_->set_listener(this); |
1128 | 397 |
1129 // Makes sure our state is consistent. | 398 // Makes sure our state is consistent. |
(...skipping 18 matching lines...) Expand all Loading... |
1148 | 417 |
1149 if (!g_browser_process->local_state()) | 418 if (!g_browser_process->local_state()) |
1150 return; | 419 return; |
1151 | 420 |
1152 const base::DictionaryValue* dictionary = | 421 const base::DictionaryValue* dictionary = |
1153 g_browser_process->local_state()->GetDictionary(GetWindowName()); | 422 g_browser_process->local_state()->GetDictionary(GetWindowName()); |
1154 if (dictionary) | 423 if (dictionary) |
1155 dictionary->GetBoolean("always_on_top", &is_always_on_top_); | 424 dictionary->GetBoolean("always_on_top", &is_always_on_top_); |
1156 } | 425 } |
1157 | 426 |
1158 void NewTaskManagerView::RetrieveSavedColumnsSettingsAndUpdateTable() { | |
1159 if (!g_browser_process->local_state()) | |
1160 return; | |
1161 | |
1162 const base::DictionaryValue* dictionary = | |
1163 g_browser_process->local_state()->GetDictionary( | |
1164 prefs::kTaskManagerColumnVisibility); | |
1165 if (!dictionary) | |
1166 return; | |
1167 | |
1168 // Do a best effort of retrieving the correct settings from the local state. | |
1169 // Use the default settings of the value if it fails to be retrieved. | |
1170 std::string sorted_col_id; | |
1171 bool sort_is_ascending = true; | |
1172 dictionary->GetString(kSortColumnIdKey, &sorted_col_id); | |
1173 dictionary->GetBoolean(kSortIsAscendingKey, &sort_is_ascending); | |
1174 | |
1175 int current_visible_column_index = 0; | |
1176 for (size_t i = 0; i < kColumnsSize; ++i) { | |
1177 const int col_id = kColumns[i].id; | |
1178 const std::string col_id_key(GetColumnIdAsString(col_id)); | |
1179 | |
1180 if (col_id_key.empty()) | |
1181 continue; | |
1182 | |
1183 bool col_visibility = kColumns[i].default_visibility; | |
1184 dictionary->GetBoolean(col_id_key, &col_visibility); | |
1185 | |
1186 // If the above GetBoolean() fails, the |col_visibility| remains at the | |
1187 // default visibility. | |
1188 columns_settings_->SetBoolean(col_id_key, col_visibility); | |
1189 tab_table_->SetColumnVisibility(col_id, col_visibility); | |
1190 table_model_->UpdateRefreshTypes(tab_table_, col_id, col_visibility); | |
1191 | |
1192 if (col_visibility) { | |
1193 if (sorted_col_id == col_id_key) { | |
1194 if (sort_is_ascending == kColumns[i].initial_sort_is_ascending) { | |
1195 tab_table_->ToggleSortOrder(current_visible_column_index); | |
1196 } else { | |
1197 // Unfortunately the API of ui::TableView doesn't provide a clean way | |
1198 // to sort by a particular column ID and a sort direction. If the | |
1199 // retrieved sort direction is different than the initial one, we have | |
1200 // to toggle the sort order twice! | |
1201 // Note that the function takes the visible_column_index rather than | |
1202 // a column ID. | |
1203 tab_table_->ToggleSortOrder(current_visible_column_index); | |
1204 tab_table_->ToggleSortOrder(current_visible_column_index); | |
1205 } | |
1206 } | |
1207 | |
1208 ++current_visible_column_index; | |
1209 } | |
1210 } | |
1211 } | |
1212 | |
1213 void NewTaskManagerView::StoreColumnsSettings() { | |
1214 PrefService* local_state = g_browser_process->local_state(); | |
1215 if (!local_state) | |
1216 return; | |
1217 | |
1218 DictionaryPrefUpdate dict_update(local_state, | |
1219 prefs::kTaskManagerColumnVisibility); | |
1220 | |
1221 base::DictionaryValue::Iterator it(*columns_settings_); | |
1222 while (!it.IsAtEnd()) { | |
1223 dict_update->Set(it.key(), it.value().CreateDeepCopy()); | |
1224 it.Advance(); | |
1225 } | |
1226 | |
1227 // Store the current sort status to be restored again at startup. | |
1228 if (tab_table_->sort_descriptors().empty()) { | |
1229 dict_update->SetString(kSortColumnIdKey, ""); | |
1230 } else { | |
1231 const auto& sort_descriptor = tab_table_->sort_descriptors().front(); | |
1232 dict_update->SetString(kSortColumnIdKey, | |
1233 GetColumnIdAsString(sort_descriptor.column_id)); | |
1234 dict_update->SetBoolean(kSortIsAscendingKey, sort_descriptor.ascending); | |
1235 } | |
1236 } | |
1237 | |
1238 void NewTaskManagerView::ToggleColumnVisibility(int column_id) { | |
1239 bool new_visibility = !tab_table_->IsColumnVisible(column_id); | |
1240 tab_table_->SetColumnVisibility(column_id, new_visibility); | |
1241 columns_settings_->SetBoolean(GetColumnIdAsString(column_id), new_visibility); | |
1242 table_model_->UpdateRefreshTypes(tab_table_, column_id, new_visibility); | |
1243 } | |
1244 | |
1245 } // namespace task_management | 427 } // namespace task_management |
OLD | NEW |