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

Side by Side Diff: chrome/browser/ui/cocoa/task_manager_mac.mm

Issue 2197483003: Move the Mac Task Manager to the new backend code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cleanup Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/cocoa/task_manager_mac.h" 5 #include "chrome/browser/ui/cocoa/task_manager_mac.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/mac/bundle_locations.h" 12 #include "base/mac/bundle_locations.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/sys_string_conversions.h"
15 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/task_management/task_manager_interface.h" 17 #include "chrome/browser/task_management/task_manager_interface.h"
17 #include "chrome/browser/task_manager/task_manager.h"
18 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_dialogs.h" 19 #include "chrome/browser/ui/browser_dialogs.h"
20 #import "chrome/browser/ui/cocoa/window_size_autosaver.h" 20 #import "chrome/browser/ui/cocoa/window_size_autosaver.h"
21 #include "chrome/browser/ui/task_manager/task_manager_columns.h"
21 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
22 #include "chrome/grit/generated_resources.h" 23 #include "chrome/grit/generated_resources.h"
23 #include "components/prefs/pref_service.h" 24 #include "components/prefs/pref_service.h"
25 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/notification_source.h"
24 #include "third_party/skia/include/core/SkBitmap.h" 27 #include "third_party/skia/include/core/SkBitmap.h"
25 #include "ui/base/l10n/l10n_util_mac.h" 28 #include "ui/base/l10n/l10n_util_mac.h"
26 #include "ui/gfx/image/image_skia.h" 29 #include "ui/gfx/image/image_skia.h"
27 #include "ui/gfx/image/image_skia_util_mac.h" 30 #include "ui/gfx/image/image_skia_util_mac.h"
28 31
29 namespace { 32 namespace {
30 33
31 // Width of "a" and most other letters/digits in "small" table views. 34 NSString* ColumnIdentifier(int id) {
32 const int kCharWidth = 6; 35 return [NSString stringWithFormat:@"%d", id];
33 36 }
34 // Some of the strings below have spaces at the end or are missing letters, to
35 // make the columns look nicer, and to take potentially longer localized strings
36 // into account.
37 const struct ColumnWidth {
38 int columnId;
39 int minWidth;
40 int maxWidth; // If this is -1, 1.5*minColumWidth is used as max width.
41 } columnWidths[] = {
42 // Note that arraysize includes the trailing \0. That's intended.
43 { IDS_TASK_MANAGER_TASK_COLUMN, 120, 600 },
44 { IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, 60, 200 },
45 { IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
46 arraysize("800 MiB") * kCharWidth, -1 },
47 { IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
48 arraysize("800 MiB") * kCharWidth, -1 },
49 { IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
50 arraysize("800 MiB") * kCharWidth, -1 },
51 { IDS_TASK_MANAGER_CPU_COLUMN,
52 arraysize("99.9") * kCharWidth, -1 },
53 { IDS_TASK_MANAGER_NET_COLUMN,
54 arraysize("150 kiB/s") * kCharWidth, -1 },
55 { IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
56 arraysize("73099 ") * kCharWidth, -1 },
57 { IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN,
58 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 },
59 { IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN,
60 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 },
61 { IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN,
62 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 },
63 { IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN,
64 arraysize("2000.0K") * kCharWidth, -1 },
65 { IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN,
66 arraysize("800 kB") * kCharWidth, -1 },
67 { IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN,
68 arraysize("2000.0K (2000.0 live)") * kCharWidth, -1 },
69 { IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN,
70 arraysize("32767") * kCharWidth, -1 },
71 { IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN,
72 arraysize("idlewakeups") * kCharWidth, -1 },
73 };
74
75 class SortHelper {
76 public:
77 SortHelper(TaskManagerModel* model, NSSortDescriptor* column)
78 : sort_column_([[column key] intValue]),
79 ascending_([column ascending]),
80 model_(model) {}
81
82 bool operator()(int a, int b) {
83 TaskManagerModel::GroupRange group_range1 =
84 model_->GetGroupRangeForResource(a);
85 TaskManagerModel::GroupRange group_range2 =
86 model_->GetGroupRangeForResource(b);
87 if (group_range1 == group_range2) {
88 // The two rows are in the same group, sort so that items in the same
89 // group always appear in the same order. |ascending_| is intentionally
90 // ignored.
91 return a < b;
92 }
93 // Sort by the first entry of each of the groups.
94 int cmp_result = model_->CompareValues(
95 group_range1.first, group_range2.first, sort_column_);
96 if (!ascending_)
97 cmp_result = -cmp_result;
98 return cmp_result < 0;
99 }
100 private:
101 int sort_column_;
102 bool ascending_;
103 TaskManagerModel* model_; // weak;
104 };
105 37
106 } // namespace 38 } // namespace
107 39
108 @interface TaskManagerWindowController (Private) 40 @interface TaskManagerWindowController (Private)
109 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible; 41 - (NSTableColumn*)addColumnWithData:
42 (const task_management::TableColumnData&)columnData;
110 - (void)setUpTableColumns; 43 - (void)setUpTableColumns;
111 - (void)setUpTableHeaderContextMenu; 44 - (void)setUpTableHeaderContextMenu;
112 - (void)toggleColumn:(id)sender; 45 - (void)toggleColumn:(id)sender;
113 - (void)adjustSelectionAndEndProcessButton; 46 - (void)adjustSelectionAndEndProcessButton;
114 - (void)deselectRows; 47 - (void)deselectRows;
115 @end 48 @end
116 49
117 //////////////////////////////////////////////////////////////////////////////// 50 ////////////////////////////////////////////////////////////////////////////////
118 // TaskManagerWindowController implementation: 51 // TaskManagerWindowController implementation:
119 52
120 @implementation TaskManagerWindowController 53 @implementation TaskManagerWindowController
121 54
122 - (id)initWithTaskManagerObserver:(TaskManagerMac*)taskManagerObserver { 55 - (id)initWithTaskManagerMac:(task_management::TaskManagerMac*)taskManagerMac
56 tableModel:
57 (task_management::TaskManagerTableModel*)tableModel {
123 NSString* nibpath = [base::mac::FrameworkBundle() 58 NSString* nibpath = [base::mac::FrameworkBundle()
124 pathForResource:@"TaskManager" 59 pathForResource:@"TaskManager"
125 ofType:@"nib"]; 60 ofType:@"nib"];
126 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 61 if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
127 taskManagerObserver_ = taskManagerObserver; 62 taskManagerMac_ = taskManagerMac;
128 taskManager_ = taskManagerObserver_->task_manager(); 63 tableModel_ = tableModel;
129 model_ = taskManager_->model();
130 64
131 if (g_browser_process && g_browser_process->local_state()) { 65 if (g_browser_process && g_browser_process->local_state()) {
132 size_saver_.reset([[WindowSizeAutosaver alloc] 66 size_saver_.reset([[WindowSizeAutosaver alloc]
133 initWithWindow:[self window] 67 initWithWindow:[self window]
134 prefService:g_browser_process->local_state() 68 prefService:g_browser_process->local_state()
135 path:prefs::kTaskManagerWindowPlacement]); 69 path:prefs::kTaskManagerWindowPlacement]);
136 } 70 }
137 [[self window] setExcludedFromWindowsMenu:YES]; 71 [[self window] setExcludedFromWindowsMenu:YES];
72
73 [self reloadData];
138 [self showWindow:self]; 74 [self showWindow:self];
139 } 75 }
140 return self; 76 return self;
141 } 77 }
142 78
143 - (void)sortShuffleArray { 79 - (void)sortShuffleArray {
144 viewToModelMap_.resize(model_->ResourceCount()); 80 viewToModelMap_.resize(tableModel_->RowCount());
145 for (size_t i = 0; i < viewToModelMap_.size(); ++i) 81 for (size_t i = 0; i < viewToModelMap_.size(); ++i)
146 viewToModelMap_[i] = i; 82 viewToModelMap_[i] = i;
147 83
148 std::sort(viewToModelMap_.begin(), viewToModelMap_.end(), 84 if (currentSortDescriptor_.sorted_column_id != -1) {
149 SortHelper(model_, currentSortDescriptor_.get())); 85 task_management::TaskManagerTableModel* tableModel = tableModel_;
86 task_management::TableSortDescriptor currentSortDescriptor =
87 currentSortDescriptor_;
88 std::stable_sort(viewToModelMap_.begin(), viewToModelMap_.end(),
89 [tableModel, currentSortDescriptor](int a, int b) {
90 int aStart, aLength;
91 tableModel->GetRowsGroupRange(a, &aStart, &aLength);
92 int bStart, bLength;
93 tableModel->GetRowsGroupRange(b, &bStart, &bLength);
94 if (aStart == bStart) {
95 // The two rows are in the same group, sort so that
96 // items in the same group always appear in the same
97 // order. The sort descriptor's ascending value is
98 // intentionally ignored.
99 return a < b;
100 }
101
102 // Sort by the first entry of each of the groups.
103 int cmp_result = tableModel->CompareValues(
104 aStart, bStart,
105 currentSortDescriptor.sorted_column_id);
106 if (!currentSortDescriptor.is_ascending)
107 cmp_result = -cmp_result;
108 return cmp_result < 0;
109 });
110 }
150 111
151 modelToViewMap_.resize(viewToModelMap_.size()); 112 modelToViewMap_.resize(viewToModelMap_.size());
152 for (size_t i = 0; i < viewToModelMap_.size(); ++i) 113 for (size_t i = 0; i < viewToModelMap_.size(); ++i)
153 modelToViewMap_[viewToModelMap_[i]] = i; 114 modelToViewMap_[viewToModelMap_[i]] = i;
154 } 115 }
155 116
156 - (void)reloadData { 117 - (void)reloadData {
118 [self reloadDataWithRows:0 addedAtIndex:0];
119 }
120
121 - (void)reloadDataWithRows:(int)addedRows addedAtIndex:(int)addedRowIndex {
157 // Store old view indices, and the model indices they map to. 122 // Store old view indices, and the model indices they map to.
158 NSIndexSet* viewSelection = [tableView_ selectedRowIndexes]; 123 NSIndexSet* viewSelection = [tableView_ selectedRowIndexes];
159 std::vector<int> modelSelection; 124 std::vector<int> modelSelection;
160 for (NSUInteger i = [viewSelection lastIndex]; 125 for (NSUInteger i = [viewSelection lastIndex];
161 i != NSNotFound; 126 i != NSNotFound;
162 i = [viewSelection indexLessThanIndex:i]) { 127 i = [viewSelection indexLessThanIndex:i]) {
163 modelSelection.push_back(viewToModelMap_[i]); 128 modelSelection.push_back(viewToModelMap_[i]);
164 } 129 }
165 130
131 // Adjust for any added or removed rows.
132 if (addedRows != 0) {
133 for (int& selectedItem : modelSelection) {
134 if (addedRowIndex > selectedItem) {
135 // Nothing to do; added/removed items are beyond the selected item.
136 continue;
137 }
138
139 if (addedRows > 0) {
140 selectedItem += addedRows;
141 } else {
142 int removedRows = -addedRows;
143 if (addedRowIndex + removedRows <= selectedItem)
144 selectedItem -= removedRows;
145 else
146 selectedItem = -1; // The item was removed.
147 }
148 }
149 }
150
166 // Sort. 151 // Sort.
167 [self sortShuffleArray]; 152 [self sortShuffleArray];
168 153
169 // Use the model indices to get the new view indices of the selection, and 154 // Clear the selection and reload the NSTableView. Note that it is important
170 // set selection to that. This assumes that no rows were added or removed 155 // to clear the selection before reloading the data, and to reload the
171 // (in that case, the selection is cleared before -reloadData is called). 156 // selection after reloading the data, because otherwise the table will adjust
172 if (!modelSelection.empty()) 157 // the selection in ways that are not desirable.
173 DCHECK_EQ([tableView_ numberOfRows], model_->ResourceCount()); 158 [tableView_ deselectAll:nil];
159 [tableView_ reloadData];
160
161 // Reload the selection.
174 NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet]; 162 NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet];
175 for (size_t i = 0; i < modelSelection.size(); ++i) 163 for (auto selectedItem : modelSelection) {
176 [indexSet addIndex:modelToViewMap_[modelSelection[i]]]; 164 if (selectedItem != -1)
165 [indexSet addIndex:modelToViewMap_[selectedItem]];
166 }
177 [tableView_ selectRowIndexes:indexSet byExtendingSelection:NO]; 167 [tableView_ selectRowIndexes:indexSet byExtendingSelection:NO];
178 168
179 [tableView_ reloadData];
180 [self adjustSelectionAndEndProcessButton]; 169 [self adjustSelectionAndEndProcessButton];
181 } 170 }
182 171
172 - (task_management::TableSortDescriptor)sortDescriptor {
173 return currentSortDescriptor_;
174 }
175
176 - (void)setSortDescriptor:
177 (const task_management::TableSortDescriptor&)sortDescriptor {
178 base::scoped_nsobject<NSSortDescriptor> nsSortDescriptor(
179 [[NSSortDescriptor alloc]
180 initWithKey:ColumnIdentifier(sortDescriptor.sorted_column_id)
181 ascending:sortDescriptor.is_ascending]);
182 [tableView_ setSortDescriptors:@[ nsSortDescriptor ]];
183 }
184
185 - (BOOL)visibilityOfColumnWithId:(int)columnId {
186 NSTableColumn* column =
187 [tableView_ tableColumnWithIdentifier:ColumnIdentifier(columnId)];
188 return ![column isHidden];
189 }
190
191 - (void)setColumnWithId:(int)columnId toVisibility:(BOOL)visibility {
192 NSTableColumn* column =
193 [tableView_ tableColumnWithIdentifier:ColumnIdentifier(columnId)];
194 [column setHidden:!visibility];
195
196 [tableView_ sizeToFit];
197 [tableView_ setNeedsDisplay];
198 }
199
183 - (IBAction)killSelectedProcesses:(id)sender { 200 - (IBAction)killSelectedProcesses:(id)sender {
184 NSIndexSet* selection = [tableView_ selectedRowIndexes]; 201 NSIndexSet* selection = [tableView_ selectedRowIndexes];
185 for (NSUInteger i = [selection lastIndex]; 202 for (NSUInteger i = [selection lastIndex];
186 i != NSNotFound; 203 i != NSNotFound;
187 i = [selection indexLessThanIndex:i]) { 204 i = [selection indexLessThanIndex:i]) {
188 taskManager_->KillProcess(viewToModelMap_[i]); 205 tableModel_->KillTask(viewToModelMap_[i]);
189 } 206 }
190 } 207 }
191 208
192 - (void)selectDoubleClickedTab:(id)sender { 209 - (void)tableWasDoubleClicked:(id)sender {
193 NSInteger row = [tableView_ clickedRow]; 210 NSInteger row = [tableView_ clickedRow];
194 if (row < 0) 211 if (row < 0)
195 return; // Happens e.g. if the table header is double-clicked. 212 return; // Happens e.g. if the table header is double-clicked.
196 taskManager_->ActivateProcess(viewToModelMap_[row]); 213 tableModel_->ActivateTask(viewToModelMap_[row]);
197 }
198
199 - (NSTableView*)tableView {
200 return tableView_;
201 } 214 }
202 215
203 - (void)awakeFromNib { 216 - (void)awakeFromNib {
204 [self setUpTableColumns]; 217 [self setUpTableColumns];
205 [self setUpTableHeaderContextMenu]; 218 [self setUpTableHeaderContextMenu];
206 [self adjustSelectionAndEndProcessButton]; 219 [self adjustSelectionAndEndProcessButton];
207 220
208 [tableView_ setDoubleAction:@selector(selectDoubleClickedTab:)]; 221 [tableView_ setDoubleAction:@selector(tableWasDoubleClicked:)];
209 [tableView_ setIntercellSpacing:NSMakeSize(0.0, 0.0)]; 222 [tableView_ setIntercellSpacing:NSMakeSize(0.0, 0.0)];
210 [tableView_ sizeToFit]; 223 [tableView_ sizeToFit];
211 } 224 }
212 225
213 - (void)dealloc { 226 - (void)dealloc {
214 [tableView_ setDelegate:nil]; 227 [tableView_ setDelegate:nil];
215 [tableView_ setDataSource:nil]; 228 [tableView_ setDataSource:nil];
216 [super dealloc]; 229 [super dealloc];
217 } 230 }
218 231
219 // Adds a column which has the given string id as title. |isVisible| specifies 232 // Adds a column which has the given string id as title. |isVisible| specifies
220 // if the column is initially visible. 233 // if the column is initially visible.
221 - (NSTableColumn*)addColumnWithId:(int)columnId visible:(BOOL)isVisible { 234 - (NSTableColumn*)addColumnWithData:
235 (const task_management::TableColumnData&)columnData {
222 base::scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc] 236 base::scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc]
223 initWithIdentifier:[NSString stringWithFormat:@"%d", columnId]]); 237 initWithIdentifier:ColumnIdentifier(columnData.id)]);
224 238
225 NSTextAlignment textAlignment = 239 NSTextAlignment textAlignment = (columnData.align == ui::TableColumn::LEFT)
226 (columnId == IDS_TASK_MANAGER_TASK_COLUMN || 240 ? NSLeftTextAlignment
227 columnId == IDS_TASK_MANAGER_PROFILE_NAME_COLUMN) ? 241 : NSRightTextAlignment;
228 NSLeftTextAlignment : NSRightTextAlignment;
229 242
230 [[column.get() headerCell] 243 [[column.get() headerCell]
231 setStringValue:l10n_util::GetNSStringWithFixup(columnId)]; 244 setStringValue:l10n_util::GetNSStringWithFixup(columnData.id)];
232 [[column.get() headerCell] setAlignment:textAlignment]; 245 [[column.get() headerCell] setAlignment:textAlignment];
233 [[column.get() dataCell] setAlignment:textAlignment]; 246 [[column.get() dataCell] setAlignment:textAlignment];
234 247
235 NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; 248 NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
236 [[column.get() dataCell] setFont:font]; 249 [[column.get() dataCell] setFont:font];
237 250
238 [column.get() setHidden:!isVisible]; 251 [column.get() setHidden:!columnData.default_visibility];
239 [column.get() setEditable:NO]; 252 [column.get() setEditable:NO];
240 253
241 // The page column should by default be sorted ascending.
242 BOOL ascending = columnId == IDS_TASK_MANAGER_TASK_COLUMN;
243
244 base::scoped_nsobject<NSSortDescriptor> sortDescriptor( 254 base::scoped_nsobject<NSSortDescriptor> sortDescriptor(
245 [[NSSortDescriptor alloc] 255 [[NSSortDescriptor alloc]
246 initWithKey:[NSString stringWithFormat:@"%d", columnId] 256 initWithKey:ColumnIdentifier(columnData.id)
247 ascending:ascending]); 257 ascending:columnData.initial_sort_is_ascending]);
248 [column.get() setSortDescriptorPrototype:sortDescriptor.get()]; 258 [column.get() setSortDescriptorPrototype:sortDescriptor.get()];
249 259
250 // Default values, only used in release builds if nobody notices the DCHECK 260 [column.get() setMinWidth:columnData.min_width];
251 // during development when adding new columns. 261 int maxWidth = columnData.max_width;
252 int minWidth = 200, maxWidth = 400; 262 if (maxWidth < 0)
253 263 maxWidth = 3 * columnData.min_width / 2; // *1.5 for ints.
254 size_t i;
255 for (i = 0; i < arraysize(columnWidths); ++i) {
256 if (columnWidths[i].columnId == columnId) {
257 minWidth = columnWidths[i].minWidth;
258 maxWidth = columnWidths[i].maxWidth;
259 if (maxWidth < 0)
260 maxWidth = 3 * minWidth / 2; // *1.5 for ints.
261 break;
262 }
263 }
264 DCHECK(i < arraysize(columnWidths)) << "Could not find " << columnId;
265 [column.get() setMinWidth:minWidth];
266 [column.get() setMaxWidth:maxWidth]; 264 [column.get() setMaxWidth:maxWidth];
267 [column.get() setResizingMask:NSTableColumnAutoresizingMask | 265 [column.get() setResizingMask:NSTableColumnAutoresizingMask |
268 NSTableColumnUserResizingMask]; 266 NSTableColumnUserResizingMask];
269 267
270 [tableView_ addTableColumn:column.get()]; 268 [tableView_ addTableColumn:column.get()];
271 return column.get(); // Now retained by |tableView_|. 269 return column.get(); // Now retained by |tableView_|.
272 } 270 }
273 271
274 // Adds all the task manager's columns to the table. 272 // Adds all the task manager's columns to the table.
275 - (void)setUpTableColumns { 273 - (void)setUpTableColumns {
276 for (NSTableColumn* column in [tableView_ tableColumns]) 274 for (NSTableColumn* column in [tableView_ tableColumns])
277 [tableView_ removeTableColumn:column]; 275 [tableView_ removeTableColumn:column];
278 NSTableColumn* nameColumn = [self addColumnWithId:IDS_TASK_MANAGER_TASK_COLUMN
279 visible:YES];
280 // |nameColumn| displays an icon for every row -- this is done by an
281 // NSButtonCell.
282 base::scoped_nsobject<NSButtonCell> nameCell(
283 [[NSButtonCell alloc] initTextCell:@""]);
284 [nameCell.get() setImagePosition:NSImageLeft];
285 [nameCell.get() setButtonType:NSSwitchButton];
286 [nameCell.get() setAlignment:[[nameColumn dataCell] alignment]];
287 [nameCell.get() setFont:[[nameColumn dataCell] font]];
288 [nameColumn setDataCell:nameCell.get()];
289 276
290 // Initially, sort on the tab name. 277 for (size_t i = 0; i < task_management::kColumnsSize; ++i) {
291 [tableView_ setSortDescriptors: 278 const auto& columnData = task_management::kColumns[i];
292 [NSArray arrayWithObject:[nameColumn sortDescriptorPrototype]]]; 279 NSTableColumn* column = [self addColumnWithData:columnData];
293 [self addColumnWithId:IDS_TASK_MANAGER_PROFILE_NAME_COLUMN visible:NO]; 280
294 [self addColumnWithId:IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN visible:YES]; 281 if (columnData.id == IDS_TASK_MANAGER_TASK_COLUMN) {
295 [self addColumnWithId:IDS_TASK_MANAGER_SHARED_MEM_COLUMN visible:NO]; 282 // The task column displays an icon for every row, done by an
296 [self addColumnWithId:IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN visible:NO]; 283 // NSButtonCell.
297 [self addColumnWithId:IDS_TASK_MANAGER_CPU_COLUMN visible:YES]; 284 base::scoped_nsobject<NSButtonCell> nameCell(
298 [self addColumnWithId:IDS_TASK_MANAGER_NET_COLUMN visible:YES]; 285 [[NSButtonCell alloc] initTextCell:@""]);
299 [self addColumnWithId:IDS_TASK_MANAGER_PROCESS_ID_COLUMN visible:YES]; 286 [nameCell.get() setImagePosition:NSImageLeft];
300 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN 287 [nameCell.get() setButtonType:NSSwitchButton];
301 visible:NO]; 288 [nameCell.get() setAlignment:[[column dataCell] alignment]];
302 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN 289 [nameCell.get() setFont:[[column dataCell] font]];
303 visible:NO]; 290 [column setDataCell:nameCell.get()];
304 [self addColumnWithId:IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN visible:NO]; 291 }
305 [self addColumnWithId:IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN visible:NO]; 292 }
306 [self addColumnWithId:IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN visible:NO];
307 [self addColumnWithId:IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN
308 visible:NO];
309 [self addColumnWithId:IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN
310 visible:NO];
311 [self addColumnWithId:IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN
312 visible:NO];
313 } 293 }
314 294
315 // Creates a context menu for the table header that allows the user to toggle 295 // Creates a context menu for the table header that allows the user to toggle
316 // which columns should be shown and which should be hidden (like e.g. 296 // which columns should be shown and which should be hidden (like the Activity
317 // Task Manager.app's table header context menu). 297 // Monitor.app's table header context menu).
318 - (void)setUpTableHeaderContextMenu { 298 - (void)setUpTableHeaderContextMenu {
319 base::scoped_nsobject<NSMenu> contextMenu( 299 base::scoped_nsobject<NSMenu> contextMenu(
320 [[NSMenu alloc] initWithTitle:@"Task Manager context menu"]); 300 [[NSMenu alloc] initWithTitle:@"Task Manager context menu"]);
301 [contextMenu setDelegate:self];
302 [[tableView_ headerView] setMenu:contextMenu.get()];
303 }
304
305 - (void)menuNeedsUpdate:(NSMenu*)menu {
306 [menu removeAllItems];
307
321 for (NSTableColumn* column in [tableView_ tableColumns]) { 308 for (NSTableColumn* column in [tableView_ tableColumns]) {
322 NSMenuItem* item = [contextMenu.get() 309 NSMenuItem* item = [menu addItemWithTitle:[[column headerCell] stringValue]
323 addItemWithTitle:[[column headerCell] stringValue] 310 action:@selector(toggleColumn:)
324 action:@selector(toggleColumn:) 311 keyEquivalent:@""];
325 keyEquivalent:@""];
326 [item setTarget:self]; 312 [item setTarget:self];
327 [item setRepresentedObject:column]; 313 [item setRepresentedObject:column];
328 [item setState:[column isHidden] ? NSOffState : NSOnState]; 314 [item setState:[column isHidden] ? NSOffState : NSOnState];
329 } 315 }
330 [[tableView_ headerView] setMenu:contextMenu.get()];
331 } 316 }
332 317
333 // Callback for the table header context menu. Toggles visibility of the table 318 // Callback for the table header context menu. Toggles visibility of the table
334 // column associated with the clicked menu item. 319 // column associated with the clicked menu item.
335 - (void)toggleColumn:(id)item { 320 - (void)toggleColumn:(id)item {
336 DCHECK([item isKindOfClass:[NSMenuItem class]]); 321 DCHECK([item isKindOfClass:[NSMenuItem class]]);
337 if (![item isKindOfClass:[NSMenuItem class]]) 322 if (![item isKindOfClass:[NSMenuItem class]])
338 return; 323 return;
339 324
340 NSTableColumn* column = [item representedObject]; 325 NSTableColumn* column = [item representedObject];
326 int columnId = [[column identifier] intValue];
341 DCHECK(column); 327 DCHECK(column);
342 NSInteger oldState = [item state]; 328 NSInteger oldState = [item state];
343 NSInteger newState = oldState == NSOnState ? NSOffState : NSOnState; 329 NSInteger newState = oldState == NSOnState ? NSOffState : NSOnState;
344 330
345 // If hiding the column, make sure at least one column will remain visible. 331 // If hiding the column, make sure at least one column will remain visible.
346 if (newState == NSOffState) { 332 if (newState == NSOffState) {
347 // Find the first column that will be visible after hiding |column|. 333 // Find the first column that will be visible after hiding |column|.
348 NSTableColumn* firstRemainingVisibleColumn = nil; 334 NSTableColumn* firstRemainingVisibleColumn = nil;
349 335
350 for (NSTableColumn* nextColumn in [tableView_ tableColumns]) { 336 for (NSTableColumn* nextColumn in [tableView_ tableColumns]) {
(...skipping 13 matching lines...) Expand all
364 // on hiding the last visible column (perhaps they plan to choose another 350 // on hiding the last visible column (perhaps they plan to choose another
365 // one after that to be visible), odds are they will try making another 351 // one after that to be visible), odds are they will try making another
366 // column visible and then hiding the one column that would not hide. 352 // column visible and then hiding the one column that would not hide.
367 if (firstRemainingVisibleColumn == nil) { 353 if (firstRemainingVisibleColumn == nil) {
368 return; 354 return;
369 } 355 }
370 356
371 // If |column| is being used to sort the table (i.e. it's the primary sort 357 // If |column| is being used to sort the table (i.e. it's the primary sort
372 // column), make the first remaining visible column the new primary sort 358 // column), make the first remaining visible column the new primary sort
373 // column. 359 // column.
374 int primarySortColumnId = [[currentSortDescriptor_.get() key] intValue]; 360 int primarySortColumnId = currentSortDescriptor_.sorted_column_id;
375 DCHECK(primarySortColumnId); 361 DCHECK(primarySortColumnId);
376 int columnId = [[column identifier] intValue];
377 362
378 if (primarySortColumnId == columnId) { 363 if (primarySortColumnId == columnId) {
379 NSSortDescriptor* newSortDescriptor = 364 NSSortDescriptor* newSortDescriptor =
380 [firstRemainingVisibleColumn sortDescriptorPrototype]; 365 [firstRemainingVisibleColumn sortDescriptorPrototype];
381 [tableView_ setSortDescriptors: 366 [tableView_ setSortDescriptors:@[ newSortDescriptor ]];
382 [NSArray arrayWithObject:newSortDescriptor]];
383 } 367 }
384 } 368 }
385 369
386 // Make the change. 370 // Make the change. (This will call back into the SetColumnVisibility()
387 [column setHidden:newState == NSOffState]; 371 // function to actually do the visibility change.)
388 [item setState:newState]; 372 tableModel_->ToggleColumnVisibility(columnId);
389
390 [tableView_ sizeToFit];
391 [tableView_ setNeedsDisplay];
392 } 373 }
393 374
394 // This function appropriately sets the enabled states on the table's editing 375 // This function appropriately sets the enabled states on the table's editing
395 // buttons. 376 // buttons.
396 - (void)adjustSelectionAndEndProcessButton { 377 - (void)adjustSelectionAndEndProcessButton {
397 bool selectionContainsBrowserProcess = false; 378 bool allSelectionRowsAreKillableTasks = true;
379 NSMutableIndexSet* groupIndexes = [NSMutableIndexSet indexSet];
398 380
399 // If a row is selected, make sure that all rows belonging to the same process
400 // are selected as well. Also, check if the selection contains the browser
401 // process.
402 NSIndexSet* selection = [tableView_ selectedRowIndexes]; 381 NSIndexSet* selection = [tableView_ selectedRowIndexes];
403 for (NSUInteger i = [selection lastIndex]; 382 for (NSUInteger i = [selection lastIndex];
404 i != NSNotFound; 383 i != NSNotFound;
405 i = [selection indexLessThanIndex:i]) { 384 i = [selection indexLessThanIndex:i]) {
406 int modelIndex = viewToModelMap_[i]; 385 int modelIndex = viewToModelMap_[i];
407 if (taskManager_->IsBrowserProcess(modelIndex))
408 selectionContainsBrowserProcess = true;
409 386
410 TaskManagerModel::GroupRange rangePair = 387 if (!tableModel_->IsTaskKillable(modelIndex))
411 model_->GetGroupRangeForResource(modelIndex); 388 allSelectionRowsAreKillableTasks = false;
412 NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet]; 389
413 for (int j = 0; j < rangePair.second; ++j) 390 int groupStart, groupLength;
414 [indexSet addIndex:modelToViewMap_[rangePair.first + j]]; 391 tableModel_->GetRowsGroupRange(modelIndex, &groupStart, &groupLength);
415 [tableView_ selectRowIndexes:indexSet byExtendingSelection:YES]; 392 for (int j = 0; j < groupLength; ++j)
393 [groupIndexes addIndex:modelToViewMap_[groupStart + j]];
416 } 394 }
417 395
418 bool enabled = [selection count] > 0 && !selectionContainsBrowserProcess && 396 [tableView_ selectRowIndexes:groupIndexes byExtendingSelection:YES];
419 task_management::TaskManagerInterface::IsEndProcessEnabled(); 397
398 bool enabled = [selection count] > 0 && allSelectionRowsAreKillableTasks &&
399 task_management::TaskManagerInterface::IsEndProcessEnabled();
420 [endProcessButton_ setEnabled:enabled]; 400 [endProcessButton_ setEnabled:enabled];
421 } 401 }
422 402
423 - (void)deselectRows { 403 - (void)deselectRows {
424 [tableView_ deselectAll:self]; 404 [tableView_ deselectAll:self];
425 } 405 }
426 406
427 // Table view delegate methods. 407 // Table view delegate methods.
428 408
429 // The selection is being changed by mouse (drag/click). 409 // The selection is being changed by mouse (drag/click).
430 - (void)tableViewSelectionIsChanging:(NSNotification*)aNotification { 410 - (void)tableViewSelectionIsChanging:(NSNotification*)aNotification {
431 [self adjustSelectionAndEndProcessButton]; 411 [self adjustSelectionAndEndProcessButton];
432 } 412 }
433 413
434 // The selection is being changed by keyboard (arrows). 414 // The selection is being changed by keyboard (arrows).
435 - (void)tableViewSelectionDidChange:(NSNotification*)aNotification { 415 - (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
436 [self adjustSelectionAndEndProcessButton]; 416 [self adjustSelectionAndEndProcessButton];
437 } 417 }
438 418
439 - (void)windowWillClose:(NSNotification*)notification { 419 - (void)windowWillClose:(NSNotification*)notification {
440 if (taskManagerObserver_) { 420 if (taskManagerMac_) {
441 taskManagerObserver_->WindowWasClosed(); 421 tableModel_->StoreColumnsSettings();
442 taskManagerObserver_ = nil; 422 taskManagerMac_->WindowWasClosed();
423 taskManagerMac_ = nullptr;
424 tableModel_ = nullptr;
443 } 425 }
444 [self autorelease]; 426 [self autorelease];
445 } 427 }
446 428
447 @end 429 @end
448 430
449 @implementation TaskManagerWindowController (NSTableDataSource) 431 @implementation TaskManagerWindowController (NSTableDataSource)
450 432
451 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView { 433 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
452 DCHECK(tableView == tableView_ || tableView_ == nil); 434 DCHECK(tableView == tableView_ || tableView_ == nil);
453 return model_->ResourceCount(); 435 return tableModel_->RowCount();
454 } 436 }
455 437
456 - (NSString*)modelTextForRow:(int)row column:(int)columnId { 438 - (NSString*)modelTextForRow:(int)row column:(int)columnId {
457 DCHECK_LT(static_cast<size_t>(row), viewToModelMap_.size()); 439 DCHECK_LT(static_cast<size_t>(row), viewToModelMap_.size());
458 return base::SysUTF16ToNSString( 440 return base::SysUTF16ToNSString(
459 model_->GetResourceById(viewToModelMap_[row], columnId)); 441 tableModel_->GetText(viewToModelMap_[row], columnId));
460 } 442 }
461 443
462 - (id)tableView:(NSTableView*)tableView 444 - (id)tableView:(NSTableView*)tableView
463 objectValueForTableColumn:(NSTableColumn*)tableColumn 445 objectValueForTableColumn:(NSTableColumn*)tableColumn
464 row:(NSInteger)rowIndex { 446 row:(NSInteger)rowIndex {
465 // NSButtonCells expect an on/off state as objectValue. Their title is set 447 // NSButtonCells expect an on/off state as objectValue. Their title is set
466 // in |tableView:dataCellForTableColumn:row:| below. 448 // in |tableView:dataCellForTableColumn:row:| below.
467 if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_TASK_COLUMN) { 449 if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_TASK_COLUMN) {
468 return [NSNumber numberWithInt:NSOffState]; 450 return [NSNumber numberWithInt:NSOffState];
469 } 451 }
470 452
471 return [self modelTextForRow:rowIndex 453 return [self modelTextForRow:rowIndex
472 column:[[tableColumn identifier] intValue]]; 454 column:[[tableColumn identifier] intValue]];
473 } 455 }
474 456
475 - (NSCell*)tableView:(NSTableView*)tableView 457 - (NSCell*)tableView:(NSTableView*)tableView
476 dataCellForTableColumn:(NSTableColumn*)tableColumn 458 dataCellForTableColumn:(NSTableColumn*)tableColumn
477 row:(NSInteger)rowIndex { 459 row:(NSInteger)rowIndex {
478 NSCell* cell = [tableColumn dataCellForRow:rowIndex]; 460 NSCell* cell = [tableColumn dataCellForRow:rowIndex];
479 461
480 // Set the favicon and title for the task in the name column. 462 // Set the favicon and title for the task in the name column.
481 if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_TASK_COLUMN) { 463 if ([[tableColumn identifier] intValue] == IDS_TASK_MANAGER_TASK_COLUMN) {
482 DCHECK([cell isKindOfClass:[NSButtonCell class]]); 464 DCHECK([cell isKindOfClass:[NSButtonCell class]]);
483 NSButtonCell* buttonCell = static_cast<NSButtonCell*>(cell); 465 NSButtonCell* buttonCell = static_cast<NSButtonCell*>(cell);
484 NSString* title = [self modelTextForRow:rowIndex 466 NSString* title = [self modelTextForRow:rowIndex
485 column:[[tableColumn identifier] intValue]]; 467 column:[[tableColumn identifier] intValue]];
486 [buttonCell setTitle:title]; 468 [buttonCell setTitle:title];
487 [buttonCell setImage: 469 [buttonCell
488 taskManagerObserver_->GetImageForRow(viewToModelMap_[rowIndex])]; 470 setImage:taskManagerMac_->GetImageForRow(viewToModelMap_[rowIndex])];
489 [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button. 471 [buttonCell setRefusesFirstResponder:YES]; // Don't push in like a button.
490 [buttonCell setHighlightsBy:NSNoCellMask]; 472 [buttonCell setHighlightsBy:NSNoCellMask];
491 } 473 }
492 474
493 return cell; 475 return cell;
494 } 476 }
495 477
496 - (void) tableView:(NSTableView*)tableView 478 - (void)tableView:(NSTableView*)tableView
497 sortDescriptorsDidChange:(NSArray*)oldDescriptors { 479 sortDescriptorsDidChange:(NSArray*)oldDescriptors {
498 NSArray* newDescriptors = [tableView sortDescriptors]; 480 if (withinSortDescriptorsDidChange_)
499 if ([newDescriptors count] < 1) { 481 return;
500 currentSortDescriptor_.reset(nil); 482
483 NSSortDescriptor* oldDescriptor = [oldDescriptors firstObject];
484 NSSortDescriptor* newDescriptor = [[tableView sortDescriptors] firstObject];
485
486 // Implement three-way sorting, toggling "unsorted" as a third option.
487 if (oldDescriptor && newDescriptor &&
488 [[oldDescriptor key] isEqual:[newDescriptor key]]) {
489 // The user clicked to change the sort on the previously sorted column.
490 // AppKit toggled the sort order. However, if the sort was toggled to become
491 // the initial sorting direction, clear it instead.
492 NSTableColumn* column = [tableView
493 tableColumnWithIdentifier:ColumnIdentifier(
494 [[newDescriptor key] intValue])];
495 NSSortDescriptor* initialDescriptor = [column sortDescriptorPrototype];
496 if ([newDescriptor ascending] == [initialDescriptor ascending]) {
497 withinSortDescriptorsDidChange_ = YES;
498 [tableView_ setSortDescriptors:[NSArray array]];
499 newDescriptor = nil;
500 withinSortDescriptorsDidChange_ = NO;
501 }
502 }
503
504 if (newDescriptor) {
505 currentSortDescriptor_.sorted_column_id = [[newDescriptor key] intValue];
506 currentSortDescriptor_.is_ascending = [newDescriptor ascending];
501 } else { 507 } else {
502 currentSortDescriptor_.reset([[newDescriptors objectAtIndex:0] retain]); 508 currentSortDescriptor_.sorted_column_id = -1;
503 } 509 }
504 510
505 [self reloadData]; // Sorts. 511 [self reloadData]; // Sorts.
506 } 512 }
507 513
508 @end 514 @end
509 515
516 @implementation TaskManagerWindowController (TestingAPI)
517
518 - (NSTableView*)tableViewForTesting {
519 return tableView_;
520 }
521
522 - (NSButton*)endProcessButtonForTesting {
523 return endProcessButton_;
524 }
525
526 @end
527
528 namespace task_management {
529
510 //////////////////////////////////////////////////////////////////////////////// 530 ////////////////////////////////////////////////////////////////////////////////
511 // TaskManagerMac implementation: 531 // TaskManagerMac implementation:
512 532
513 TaskManagerMac::TaskManagerMac(TaskManager* task_manager) 533 TaskManagerMac::TaskManagerMac()
514 : task_manager_(task_manager), 534 : table_model_(new TaskManagerTableModel(
515 model_(task_manager->model()) { 535 REFRESH_TYPE_CPU | REFRESH_TYPE_MEMORY | REFRESH_TYPE_NETWORK_USAGE,
516 window_controller_ = 536 this)),
517 [[TaskManagerWindowController alloc] initWithTaskManagerObserver:this]; 537 window_controller_([[TaskManagerWindowController alloc]
518 model_->AddObserver(this); 538 initWithTaskManagerMac:this
539 tableModel:table_model_.get()]) {
540 table_model_->SetObserver(this); // Hook up the ui::TableModelObserver.
541 table_model_->RetrieveSavedColumnsSettingsAndUpdateTable();
542
543 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
544 content::NotificationService::AllSources());
519 } 545 }
520 546
521 // static 547 // static
522 TaskManagerMac* TaskManagerMac::instance_ = NULL; 548 TaskManagerMac* TaskManagerMac::instance_ = nullptr;
523 549
524 TaskManagerMac::~TaskManagerMac() { 550 TaskManagerMac::~TaskManagerMac() {
525 if (this == instance_) { 551 table_model_->SetObserver(nullptr);
526 // Do not do this when running in unit tests: |StartUpdating()| never got
527 // called in that case.
528 task_manager_->OnWindowClosed();
529 }
530 model_->RemoveObserver(this);
531 } 552 }
532 553
533 //////////////////////////////////////////////////////////////////////////////// 554 ////////////////////////////////////////////////////////////////////////////////
534 // TaskManagerMac, TaskManagerModelObserver implementation: 555 // ui::TableModelObserver implementation:
535 556
536 void TaskManagerMac::OnModelChanged() { 557 void TaskManagerMac::OnModelChanged() {
537 [window_controller_ deselectRows]; 558 [window_controller_ deselectRows];
538 [window_controller_ reloadData]; 559 [window_controller_ reloadData];
539 } 560 }
540 561
541 void TaskManagerMac::OnItemsChanged(int start, int length) { 562 void TaskManagerMac::OnItemsChanged(int start, int length) {
542 [window_controller_ reloadData]; 563 [window_controller_ reloadData];
543 } 564 }
544 565
545 void TaskManagerMac::OnItemsAdded(int start, int length) { 566 void TaskManagerMac::OnItemsAdded(int start, int length) {
546 [window_controller_ deselectRows]; 567 [window_controller_ reloadDataWithRows:length addedAtIndex:start];
547 [window_controller_ reloadData];
548 } 568 }
549 569
550 void TaskManagerMac::OnItemsRemoved(int start, int length) { 570 void TaskManagerMac::OnItemsRemoved(int start, int length) {
551 [window_controller_ deselectRows]; 571 [window_controller_ reloadDataWithRows:-length addedAtIndex:start];
552 [window_controller_ reloadData]; 572 }
573
574 ////////////////////////////////////////////////////////////////////////////////
575 // TableViewDelegate implementation:
576
577 bool TaskManagerMac::IsColumnVisible(int column_id) const {
578 return [window_controller_ visibilityOfColumnWithId:column_id];
579 }
580
581 void TaskManagerMac::SetColumnVisibility(int column_id, bool new_visibility) {
582 [window_controller_ setColumnWithId:column_id toVisibility:new_visibility];
583 }
584
585 bool TaskManagerMac::IsTableSorted() const {
586 return [window_controller_ sortDescriptor].sorted_column_id != -1;
587 }
588
589 TableSortDescriptor TaskManagerMac::GetSortDescriptor() const {
590 return [window_controller_ sortDescriptor];
591 }
592
593 void TaskManagerMac::SetSortDescriptor(const TableSortDescriptor& descriptor) {
594 [window_controller_ setSortDescriptor:descriptor];
595 }
596
597 ////////////////////////////////////////////////////////////////////////////////
598 // Called by the TaskManagerWindowController:
599
600 void TaskManagerMac::WindowWasClosed() {
601 delete this;
Mark Mentovai 2016/08/02 20:45:49 So can the destructor be private?
Avi (use Gerrit) 2016/08/02 20:52:50 Yes.
602 instance_ = nullptr; // |instance_| is static
553 } 603 }
554 604
555 NSImage* TaskManagerMac::GetImageForRow(int row) { 605 NSImage* TaskManagerMac::GetImageForRow(int row) {
556 return gfx::NSImageFromImageSkia(model_->GetResourceIcon(row)); 606 const CGFloat kImageWidth = 16.0;
607 NSImage* image = gfx::NSImageFromImageSkia(table_model_->GetIcon(row));
608 if (!image) {
609 image = [[[NSImage alloc] initWithSize:NSMakeSize(kImageWidth, kImageWidth)]
610 autorelease];
611 }
612 return image;
557 } 613 }
558 614
559 //////////////////////////////////////////////////////////////////////////////// 615 void TaskManagerMac::Observe(int type,
560 // TaskManagerMac, public: 616 const content::NotificationSource& source,
561 617 const content::NotificationDetails& details) {
562 void TaskManagerMac::WindowWasClosed() { 618 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
563 delete this; 619 Hide();
564 instance_ = NULL; // |instance_| is static
565 } 620 }
566 621
567 // static 622 // static
568 void TaskManagerMac::Show() { 623 TaskManagerTableModel* TaskManagerMac::Show() {
569 if (instance_) { 624 if (instance_) {
570 [[instance_->window_controller_ window] 625 [[instance_->window_controller_ window]
571 makeKeyAndOrderFront:instance_->window_controller_]; 626 makeKeyAndOrderFront:instance_->window_controller_];
572 return; 627 } else {
628 instance_ = new TaskManagerMac();
Mark Mentovai 2016/08/02 20:45:49 Likewise for the constructor.
Avi (use Gerrit) 2016/08/02 20:52:50 Done.
573 } 629 }
574 // Create a new instance. 630
575 instance_ = new TaskManagerMac(TaskManager::GetInstance()); 631 return instance_->table_model_.get();
576 instance_->model_->StartUpdating();
577 } 632 }
578 633
579 // static 634 // static
580 void TaskManagerMac::Hide() { 635 void TaskManagerMac::Hide() {
581 if (instance_) 636 if (instance_)
582 [instance_->window_controller_ close]; 637 [instance_->window_controller_ close];
583 } 638 }
584 639
640 } // namespace task_management
641
585 namespace chrome { 642 namespace chrome {
586 643
587 // Declared in browser_dialogs.h. 644 // Declared in browser_dialogs.h.
588 task_management::TaskManagerTableModel* ShowTaskManager(Browser* browser) { 645 task_management::TaskManagerTableModel* ShowTaskManager(Browser* browser) {
589 if (chrome::ToolkitViewsDialogsEnabled()) 646 if (chrome::ToolkitViewsDialogsEnabled())
590 return chrome::ShowTaskManagerViews(browser); 647 return chrome::ShowTaskManagerViews(browser);
591 648
592 TaskManagerMac::Show(); 649 return task_management::TaskManagerMac::Show();
593 return nullptr; // No ui::TableModel* to return on Mac, so return nullptr.
594 } 650 }
595 651
596 void HideTaskManager() { 652 void HideTaskManager() {
597 if (chrome::ToolkitViewsDialogsEnabled()) { 653 if (chrome::ToolkitViewsDialogsEnabled()) {
598 chrome::HideTaskManagerViews(); 654 chrome::HideTaskManagerViews();
599 return; 655 return;
600 } 656 }
601 657
602 TaskManagerMac::Hide(); 658 task_management::TaskManagerMac::Hide();
603 }
604
605 bool NotifyOldTaskManagerBytesRead(const net::URLRequest& request,
606 int64_t bytes_read) {
607 if (task_management::TaskManagerInterface::IsNewTaskManagerEnabled())
608 return false;
609
610 TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
611 return true;
612 } 659 }
613 660
614 } // namespace chrome 661 } // namespace chrome
615
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698