task_manager_view.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/task_manager/task_manager.h" 6 7#include "base/command_line.h" 8#include "base/compiler_specific.h" 9#include "base/metrics/stats_table.h" 10#include "base/prefs/pref_service.h" 11#include "base/prefs/scoped_user_pref_update.h" 12#include "base/strings/utf_string_conversions.h" 13#include "chrome/app/chrome_command_ids.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/memory_purger.h" 16#include "chrome/browser/ui/browser.h" 17#include "chrome/browser/ui/browser_list.h" 18#include "chrome/browser/ui/browser_window.h" 19#include "chrome/browser/ui/host_desktop.h" 20#include "chrome/browser/ui/views/browser_dialogs.h" 21#include "chrome/common/chrome_switches.h" 22#include "chrome/common/pref_names.h" 23#include "grit/chromium_strings.h" 24#include "grit/generated_resources.h" 25#include "grit/theme_resources.h" 26#include "ui/base/accelerators/accelerator.h" 27#include "ui/base/l10n/l10n_util.h" 28#include "ui/base/models/simple_menu_model.h" 29#include "ui/base/models/table_model.h" 30#include "ui/base/models/table_model_observer.h" 31#include "ui/events/event_constants.h" 32#include "ui/events/keycodes/keyboard_codes.h" 33#include "ui/gfx/canvas.h" 34#include "ui/views/context_menu_controller.h" 35#include "ui/views/controls/button/label_button.h" 36#include "ui/views/controls/link.h" 37#include "ui/views/controls/link_listener.h" 38#include "ui/views/controls/menu/menu_runner.h" 39#include "ui/views/controls/table/table_grouper.h" 40#include "ui/views/controls/table/table_view.h" 41#include "ui/views/controls/table/table_view_observer.h" 42#include "ui/views/layout/layout_constants.h" 43#include "ui/views/widget/widget.h" 44#include "ui/views/window/dialog_delegate.h" 45 46#if defined(USE_ASH) 47#include "ash/wm/window_util.h" 48#include "chrome/browser/ui/ash/launcher/launcher_item_util.h" 49#include "grit/ash_resources.h" 50#endif 51 52#if defined(OS_WIN) 53#include "chrome/browser/shell_integration.h" 54#include "ui/base/win/shell.h" 55#include "ui/views/win/hwnd_util.h" 56#include "win8/util/win8_util.h" 57#endif 58 59namespace { 60 61//////////////////////////////////////////////////////////////////////////////// 62// TaskManagerTableModel class 63//////////////////////////////////////////////////////////////////////////////// 64 65class TaskManagerTableModel 66 : public ui::TableModel, 67 public views::TableGrouper, 68 public TaskManagerModelObserver { 69 public: 70 explicit TaskManagerTableModel(TaskManagerModel* model) 71 : model_(model), 72 observer_(NULL) { 73 model_->AddObserver(this); 74 } 75 76 virtual ~TaskManagerTableModel() { 77 model_->RemoveObserver(this); 78 } 79 80 // TableModel overrides: 81 virtual int RowCount() OVERRIDE; 82 virtual base::string16 GetText(int row, int column) OVERRIDE; 83 virtual gfx::ImageSkia GetIcon(int row) OVERRIDE; 84 virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE; 85 virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE; 86 87 // TableGrouper overrides: 88 virtual void GetGroupRange(int model_index, 89 views::GroupRange* range) OVERRIDE; 90 91 // TaskManagerModelObserver overrides: 92 virtual void OnModelChanged() OVERRIDE; 93 virtual void OnItemsChanged(int start, int length) OVERRIDE; 94 virtual void OnItemsAdded(int start, int length) OVERRIDE; 95 virtual void OnItemsRemoved(int start, int length) OVERRIDE; 96 97 private: 98 TaskManagerModel* model_; 99 ui::TableModelObserver* observer_; 100 101 DISALLOW_COPY_AND_ASSIGN(TaskManagerTableModel); 102}; 103 104int TaskManagerTableModel::RowCount() { 105 return model_->ResourceCount(); 106} 107 108base::string16 TaskManagerTableModel::GetText(int row, int col_id) { 109 return model_->GetResourceById(row, col_id); 110} 111 112gfx::ImageSkia TaskManagerTableModel::GetIcon(int row) { 113 return model_->GetResourceIcon(row); 114} 115 116void TaskManagerTableModel::SetObserver(ui::TableModelObserver* observer) { 117 observer_ = observer; 118} 119 120int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) { 121 return model_->CompareValues(row1, row2, column_id); 122} 123 124void TaskManagerTableModel::GetGroupRange(int model_index, 125 views::GroupRange* range) { 126 TaskManagerModel::GroupRange range_pair = 127 model_->GetGroupRangeForResource(model_index); 128 range->start = range_pair.first; 129 range->length = range_pair.second; 130} 131 132void TaskManagerTableModel::OnModelChanged() { 133 if (observer_) 134 observer_->OnModelChanged(); 135} 136 137void TaskManagerTableModel::OnItemsChanged(int start, int length) { 138 if (observer_) 139 observer_->OnItemsChanged(start, length); 140} 141 142void TaskManagerTableModel::OnItemsAdded(int start, int length) { 143 if (observer_) 144 observer_->OnItemsAdded(start, length); 145} 146 147void TaskManagerTableModel::OnItemsRemoved(int start, int length) { 148 if (observer_) 149 observer_->OnItemsRemoved(start, length); 150} 151 152// The Task manager UI container. 153class TaskManagerView : public views::ButtonListener, 154 public views::DialogDelegateView, 155 public views::TableViewObserver, 156 public views::LinkListener, 157 public views::ContextMenuController, 158 public ui::SimpleMenuModel::Delegate { 159 public: 160 explicit TaskManagerView(chrome::HostDesktopType desktop_type); 161 virtual ~TaskManagerView(); 162 163 // Shows the Task manager window, or re-activates an existing one. 164 static void Show(Browser* browser); 165 166 // views::View: 167 virtual void Layout() OVERRIDE; 168 virtual gfx::Size GetPreferredSize() OVERRIDE; 169 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 170 virtual void ViewHierarchyChanged( 171 const ViewHierarchyChangedDetails& details) OVERRIDE; 172 173 // views::ButtonListener: 174 virtual void ButtonPressed(views::Button* sender, 175 const ui::Event& event) OVERRIDE; 176 177 // views::DialogDelegateView: 178 virtual bool CanResize() const OVERRIDE; 179 virtual bool CanMaximize() const OVERRIDE; 180 virtual bool ExecuteWindowsCommand(int command_id) OVERRIDE; 181 virtual base::string16 GetWindowTitle() const OVERRIDE; 182 virtual std::string GetWindowName() const OVERRIDE; 183 virtual int GetDialogButtons() const OVERRIDE; 184 virtual void WindowClosing() OVERRIDE; 185 virtual bool UseNewStyleForThisDialog() const OVERRIDE; 186 187 // views::TableViewObserver: 188 virtual void OnSelectionChanged() OVERRIDE; 189 virtual void OnDoubleClick() OVERRIDE; 190 virtual void OnKeyDown(ui::KeyboardCode keycode) OVERRIDE; 191 192 // views::LinkListener: 193 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 194 195 // Called by the column picker to pick up any new stat counters that 196 // may have appeared since last time. 197 void UpdateStatsCounters(); 198 199 // views::ContextMenuController: 200 virtual void ShowContextMenuForView(views::View* source, 201 const gfx::Point& point, 202 ui::MenuSourceType source_type) OVERRIDE; 203 204 // ui::SimpleMenuModel::Delegate: 205 virtual bool IsCommandIdChecked(int id) const OVERRIDE; 206 virtual bool IsCommandIdEnabled(int id) const OVERRIDE; 207 virtual bool GetAcceleratorForCommandId( 208 int command_id, 209 ui::Accelerator* accelerator) OVERRIDE; 210 virtual void ExecuteCommand(int id, int event_flags) OVERRIDE; 211 212 private: 213 // Creates the child controls. 214 void Init(); 215 216 // Initializes the state of the always-on-top setting as the window is shown. 217 void InitAlwaysOnTopState(); 218 219 // Activates the tab associated with the focused row. 220 void ActivateFocusedTab(); 221 222 // Restores saved always on top state from a previous session. 223 bool GetSavedAlwaysOnTopState(bool* always_on_top) const; 224 225 views::LabelButton* purge_memory_button_; 226 views::LabelButton* kill_button_; 227 views::Link* about_memory_link_; 228 views::TableView* tab_table_; 229 views::View* tab_table_parent_; 230 231 TaskManager* task_manager_; 232 233 TaskManagerModel* model_; 234 235 // all possible columns, not necessarily visible 236 std::vector<ui::TableColumn> columns_; 237 238 scoped_ptr<TaskManagerTableModel> table_model_; 239 240 // True when the Task Manager window should be shown on top of other windows. 241 bool is_always_on_top_; 242 243 // The host desktop type this task manager belongs to. 244 const chrome::HostDesktopType desktop_type_; 245 246 // We need to own the text of the menu, the Windows API does not copy it. 247 base::string16 always_on_top_menu_text_; 248 249 // An open Task manager window. There can only be one open at a time. This 250 // is reset to NULL when the window is closed. 251 static TaskManagerView* instance_; 252 253 scoped_ptr<views::MenuRunner> menu_runner_; 254 255 DISALLOW_COPY_AND_ASSIGN(TaskManagerView); 256}; 257 258// static 259TaskManagerView* TaskManagerView::instance_ = NULL; 260 261 262TaskManagerView::TaskManagerView(chrome::HostDesktopType desktop_type) 263 : purge_memory_button_(NULL), 264 kill_button_(NULL), 265 about_memory_link_(NULL), 266 tab_table_(NULL), 267 tab_table_parent_(NULL), 268 task_manager_(TaskManager::GetInstance()), 269 model_(TaskManager::GetInstance()->model()), 270 is_always_on_top_(false), 271 desktop_type_(desktop_type) { 272 Init(); 273} 274 275TaskManagerView::~TaskManagerView() { 276 // Delete child views now, while our table model still exists. 277 RemoveAllChildViews(true); 278} 279 280void TaskManagerView::Init() { 281 table_model_.reset(new TaskManagerTableModel(model_)); 282 283 // Page column has no header label. 284 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_TASK_COLUMN, 285 ui::TableColumn::LEFT, -1, 1)); 286 columns_.back().sortable = true; 287 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, 288 ui::TableColumn::LEFT, -1, 0)); 289 columns_.back().sortable = true; 290 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, 291 ui::TableColumn::RIGHT, -1, 0)); 292 columns_.back().sortable = true; 293 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, 294 ui::TableColumn::RIGHT, -1, 0)); 295 columns_.back().sortable = true; 296 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, 297 ui::TableColumn::RIGHT, -1, 0)); 298 columns_.back().sortable = true; 299 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_CPU_COLUMN, 300 ui::TableColumn::RIGHT, -1, 0)); 301 columns_.back().sortable = true; 302 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_NET_COLUMN, 303 ui::TableColumn::RIGHT, -1, 0)); 304 columns_.back().sortable = true; 305 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, 306 ui::TableColumn::RIGHT, -1, 0)); 307 columns_.back().sortable = true; 308#if defined(OS_WIN) 309 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN, 310 ui::TableColumn::RIGHT, -1, 0)); 311 columns_.back().sortable = true; 312 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_USER_HANDLES_COLUMN, 313 ui::TableColumn::RIGHT, -1, 0)); 314 columns_.back().sortable = true; 315#endif 316 columns_.push_back(ui::TableColumn( 317 IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, 318 ui::TableColumn::RIGHT, -1, 0)); 319 columns_.back().sortable = true; 320 columns_.push_back(ui::TableColumn( 321 IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, 322 ui::TableColumn::RIGHT, -1, 0)); 323 columns_.back().sortable = true; 324 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, 325 ui::TableColumn::RIGHT, -1, 0)); 326 columns_.back().sortable = true; 327 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_FPS_COLUMN, 328 ui::TableColumn::RIGHT, -1, 0)); 329 columns_.back().sortable = true; 330 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN, 331 ui::TableColumn::RIGHT, -1, 0)); 332 columns_.back().sortable = true; 333 columns_.push_back(ui::TableColumn(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, 334 ui::TableColumn::RIGHT, -1, 0)); 335 columns_.back().sortable = true; 336 columns_.push_back(ui::TableColumn( 337 IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN, 338 ui::TableColumn::RIGHT, -1, 0)); 339 columns_.back().sortable = true; 340 columns_.push_back( 341 ui::TableColumn(IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, 342 ui::TableColumn::RIGHT, -1, 0)); 343 columns_.back().sortable = true; 344 345 tab_table_ = new views::TableView( 346 table_model_.get(), columns_, views::ICON_AND_TEXT, false); 347 tab_table_->SetGrouper(table_model_.get()); 348 349 // Hide some columns by default 350 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN, false); 351 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false); 352 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false); 353 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN, 354 false); 355 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN, 356 false); 357 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN, 358 false); 359 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN, 360 false); 361 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN, 362 false); 363 tab_table_->SetColumnVisibility( 364 IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN, false); 365 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN, 366 false); 367 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_GDI_HANDLES_COLUMN, false); 368 tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_USER_HANDLES_COLUMN, false); 369 370 UpdateStatsCounters(); 371 tab_table_->SetObserver(this); 372 tab_table_->set_context_menu_controller(this); 373 set_context_menu_controller(this); 374 // If we're running with --purge-memory-button, add a "Purge memory" button. 375 if (CommandLine::ForCurrentProcess()->HasSwitch( 376 switches::kPurgeMemoryButton)) { 377 purge_memory_button_ = new views::LabelButton(this, 378 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_PURGE_MEMORY)); 379 purge_memory_button_->SetStyle(views::Button::STYLE_BUTTON); 380 } 381 kill_button_ = new views::LabelButton(this, 382 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL)); 383 kill_button_->SetStyle(views::Button::STYLE_BUTTON); 384 about_memory_link_ = new views::Link( 385 l10n_util::GetStringUTF16(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)); 386 about_memory_link_->set_listener(this); 387 388 // Makes sure our state is consistent. 389 OnSelectionChanged(); 390 391 ui::Accelerator ctrl_w(ui::VKEY_W, ui::EF_CONTROL_DOWN); 392 AddAccelerator(ctrl_w); 393} 394 395void TaskManagerView::UpdateStatsCounters() { 396 base::StatsTable* stats = base::StatsTable::current(); 397 if (stats != NULL) { 398 int max = stats->GetMaxCounters(); 399 // skip the first row (it's header data) 400 for (int i = 1; i < max; i++) { 401 const char* row = stats->GetRowName(i); 402 if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) { 403 // TODO(erikkay): Use l10n to get display names for stats. Right 404 // now we're just displaying the internal counter name. Perhaps 405 // stat names not in the string table would be filtered out. 406 ui::TableColumn col; 407 col.id = i; 408 col.title = base::ASCIIToUTF16(row); 409 col.alignment = ui::TableColumn::RIGHT; 410 // TODO(erikkay): Width is hard-coded right now, so many column 411 // names are clipped. 412 col.width = 90; 413 col.sortable = true; 414 columns_.push_back(col); 415 tab_table_->AddColumn(col); 416 } 417 } 418 } 419} 420 421void TaskManagerView::ViewHierarchyChanged( 422 const ViewHierarchyChangedDetails& details) { 423 // Since we want the Kill button and the Memory Details link to show up in 424 // the same visual row as the close button, which is provided by the 425 // framework, we must add the buttons to the non-client view, which is the 426 // parent of this view. Similarly, when we're removed from the view 427 // hierarchy, we must take care to clean up those items as well. 428 if (details.child == this) { 429 if (details.is_add) { 430 details.parent->AddChildView(about_memory_link_); 431 if (purge_memory_button_) 432 details.parent->AddChildView(purge_memory_button_); 433 details.parent->AddChildView(kill_button_); 434 tab_table_parent_ = tab_table_->CreateParentIfNecessary(); 435 AddChildView(tab_table_parent_); 436 } else { 437 details.parent->RemoveChildView(kill_button_); 438 if (purge_memory_button_) 439 details.parent->RemoveChildView(purge_memory_button_); 440 details.parent->RemoveChildView(about_memory_link_); 441 } 442 } 443} 444 445void TaskManagerView::Layout() { 446 gfx::Size size = kill_button_->GetPreferredSize(); 447 gfx::Rect parent_bounds = parent()->GetContentsBounds(); 448 const int horizontal_margin = views::kPanelHorizMargin; 449 const int vertical_margin = views::kButtonVEdgeMargin; 450 int x = width() - size.width() - horizontal_margin; 451 int y_buttons = parent_bounds.bottom() - size.height() - vertical_margin; 452 kill_button_->SetBounds(x, y_buttons, size.width(), size.height()); 453 454 if (purge_memory_button_) { 455 size = purge_memory_button_->GetPreferredSize(); 456 purge_memory_button_->SetBounds( 457 kill_button_->x() - size.width() - 458 views::kUnrelatedControlHorizontalSpacing, 459 y_buttons, size.width(), size.height()); 460 } 461 462 size = about_memory_link_->GetPreferredSize(); 463 about_memory_link_->SetBounds( 464 horizontal_margin, 465 y_buttons + (kill_button_->height() - size.height()) / 2, 466 size.width(), size.height()); 467 468 gfx::Rect rect = GetLocalBounds(); 469 rect.Inset(horizontal_margin, views::kPanelVertMargin); 470 rect.Inset(0, 0, 0, 471 kill_button_->height() + views::kUnrelatedControlVerticalSpacing); 472 tab_table_parent_->SetBoundsRect(rect); 473} 474 475gfx::Size TaskManagerView::GetPreferredSize() { 476 return gfx::Size(460, 270); 477} 478 479bool TaskManagerView::AcceleratorPressed(const ui::Accelerator& accelerator) { 480 DCHECK_EQ(ui::VKEY_W, accelerator.key_code()); 481 DCHECK_EQ(ui::EF_CONTROL_DOWN, accelerator.modifiers()); 482 GetWidget()->Close(); 483 return true; 484} 485 486// static 487void TaskManagerView::Show(Browser* browser) { 488#if defined(OS_WIN) 489 // In Windows Metro it's not good to open this native window. 490 DCHECK(!win8::IsSingleWindowMetroMode()); 491#endif 492 // In ash we can come here through the ChromeShellDelegate. If there is no 493 // browser window at that time of the call, browser could be passed as NULL. 494 const chrome::HostDesktopType desktop_type = 495 browser ? browser->host_desktop_type() : chrome::HOST_DESKTOP_TYPE_ASH; 496 497 if (instance_) { 498 // If there's a Task manager window open already, just activate it. 499 instance_->GetWidget()->Activate(); 500 return; 501 } 502 instance_ = new TaskManagerView(desktop_type); 503 gfx::NativeWindow window = 504 browser ? browser->window()->GetNativeWindow() : NULL; 505#if defined(USE_ASH) 506 if (!window) 507 window = ash::wm::GetActiveWindow(); 508#endif 509 DialogDelegate::CreateDialogWidget(instance_, window, NULL); 510 instance_->InitAlwaysOnTopState(); 511 instance_->model_->StartUpdating(); 512#if defined(OS_WIN) 513 // Set the app id for the task manager to the app id of its parent browser. If 514 // no parent is specified, the app id will default to that of the initial 515 // process. 516 if (browser) { 517 ui::win::SetAppIdForWindow( 518 ShellIntegration::GetChromiumModelIdForProfile( 519 browser->profile()->GetPath()), 520 views::HWNDForWidget(instance_->GetWidget())); 521 } 522#endif 523 instance_->GetWidget()->Show(); 524 525 // Set the initial focus to the list of tasks. 526 views::FocusManager* focus_manager = instance_->GetFocusManager(); 527 if (focus_manager) 528 focus_manager->SetFocusedView(instance_->tab_table_); 529 530#if defined(USE_ASH) 531 CreateShelfItemForDialog(IDR_AURA_LAUNCHER_ICON_TASK_MANAGER, 532 instance_->GetWidget()->GetNativeWindow()); 533#endif 534} 535 536// ButtonListener implementation. 537void TaskManagerView::ButtonPressed( 538 views::Button* sender, 539 const ui::Event& event) { 540 if (purge_memory_button_ && (sender == purge_memory_button_)) { 541 MemoryPurger::PurgeAll(); 542 } else { 543 typedef ui::ListSelectionModel::SelectedIndices SelectedIndices; 544 DCHECK_EQ(kill_button_, sender); 545 SelectedIndices selection(tab_table_->selection_model().selected_indices()); 546 for (SelectedIndices::const_reverse_iterator i = selection.rbegin(); 547 i != selection.rend(); ++i) { 548 task_manager_->KillProcess(*i); 549 } 550 } 551} 552 553// DialogDelegate implementation. 554bool TaskManagerView::CanResize() const { 555 return true; 556} 557 558bool TaskManagerView::CanMaximize() const { 559 return true; 560} 561 562bool TaskManagerView::ExecuteWindowsCommand(int command_id) { 563 return false; 564} 565 566base::string16 TaskManagerView::GetWindowTitle() const { 567 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_TITLE); 568} 569 570std::string TaskManagerView::GetWindowName() const { 571 return prefs::kTaskManagerWindowPlacement; 572} 573 574int TaskManagerView::GetDialogButtons() const { 575 return ui::DIALOG_BUTTON_NONE; 576} 577 578void TaskManagerView::WindowClosing() { 579 // Now that the window is closed, we can allow a new one to be opened. 580 // (WindowClosing comes in asynchronously from the call to Close() and we 581 // may have already opened a new instance). 582 if (instance_ == this) 583 instance_ = NULL; 584 task_manager_->OnWindowClosed(); 585} 586 587bool TaskManagerView::UseNewStyleForThisDialog() const { 588 return false; 589} 590 591// views::TableViewObserver implementation. 592void TaskManagerView::OnSelectionChanged() { 593 const ui::ListSelectionModel::SelectedIndices& selection( 594 tab_table_->selection_model().selected_indices()); 595 bool selection_contains_browser_process = false; 596 for (size_t i = 0; i < selection.size(); ++i) { 597 if (task_manager_->IsBrowserProcess(selection[i])) { 598 selection_contains_browser_process = true; 599 break; 600 } 601 } 602 kill_button_->SetEnabled(!selection_contains_browser_process && 603 !selection.empty()); 604} 605 606void TaskManagerView::OnDoubleClick() { 607 ActivateFocusedTab(); 608} 609 610void TaskManagerView::OnKeyDown(ui::KeyboardCode keycode) { 611 if (keycode == ui::VKEY_RETURN) 612 ActivateFocusedTab(); 613} 614 615void TaskManagerView::LinkClicked(views::Link* source, int event_flags) { 616 DCHECK_EQ(about_memory_link_, source); 617 task_manager_->OpenAboutMemory(desktop_type_); 618} 619 620void TaskManagerView::ShowContextMenuForView(views::View* source, 621 const gfx::Point& point, 622 ui::MenuSourceType source_type) { 623 UpdateStatsCounters(); 624 ui::SimpleMenuModel menu_model(this); 625 for (std::vector<ui::TableColumn>::iterator i(columns_.begin()); 626 i != columns_.end(); ++i) { 627 menu_model.AddCheckItem(i->id, l10n_util::GetStringUTF16(i->id)); 628 } 629 menu_runner_.reset(new views::MenuRunner(&menu_model)); 630 if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point, gfx::Size()), 631 views::MenuItemView::TOPLEFT, source_type, 632 views::MenuRunner::CONTEXT_MENU) == 633 views::MenuRunner::MENU_DELETED) 634 return; 635} 636 637bool TaskManagerView::IsCommandIdChecked(int id) const { 638 return tab_table_->IsColumnVisible(id); 639} 640 641bool TaskManagerView::IsCommandIdEnabled(int id) const { 642 return true; 643} 644 645bool TaskManagerView::GetAcceleratorForCommandId( 646 int command_id, 647 ui::Accelerator* accelerator) { 648 return false; 649} 650 651void TaskManagerView::ExecuteCommand(int id, int event_flags) { 652 tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id)); 653} 654 655void TaskManagerView::InitAlwaysOnTopState() { 656 is_always_on_top_ = false; 657 if (GetSavedAlwaysOnTopState(&is_always_on_top_)) 658 GetWidget()->SetAlwaysOnTop(is_always_on_top_); 659} 660 661void TaskManagerView::ActivateFocusedTab() { 662 const int active_row = tab_table_->selection_model().active(); 663 if (active_row != -1) 664 task_manager_->ActivateProcess(active_row); 665} 666 667bool TaskManagerView::GetSavedAlwaysOnTopState(bool* always_on_top) const { 668 if (!g_browser_process->local_state()) 669 return false; 670 671 const base::DictionaryValue* dictionary = 672 g_browser_process->local_state()->GetDictionary(GetWindowName().c_str()); 673 return dictionary && 674 dictionary->GetBoolean("always_on_top", always_on_top) && always_on_top; 675} 676 677} // namespace 678 679namespace chrome { 680 681// Declared in browser_dialogs.h so others don't need to depend on our header. 682void ShowTaskManager(Browser* browser) { 683 TaskManagerView::Show(browser); 684} 685 686} // namespace chrome 687