summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 14:01:58 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 14:01:58 +0000
commit0da19221d7b32e3331ad50b2c9e642697e49ff05 (patch)
tree19e1cebe40b9e3a21ed67675769ba82284f42e99 /chrome/browser
parent81c78ac1f4407d0a9b1fa1dbb41916ababa225c7 (diff)
downloadchromium_src-0da19221d7b32e3331ad50b2c9e642697e49ff05.zip
chromium_src-0da19221d7b32e3331ad50b2c9e642697e49ff05.tar.gz
chromium_src-0da19221d7b32e3331ad50b2c9e642697e49ff05.tar.bz2
Extract Windows-specific parts of TaskManager.
- task_manager.cc compiles on POSIX - task_manager_unittest.cc passes on Linux - stub TaskManagerViewImpl for Linux (so that the unit test can pass) TEST=Task manager should not be obviously broken on Windows. http://crbug.com/11461 Review URL: http://codereview.chromium.org/115295 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16053 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.vcproj4
-rw-r--r--chrome/browser/task_manager.cc515
-rw-r--r--chrome/browser/task_manager.h14
-rw-r--r--chrome/browser/task_manager_linux.cc64
-rw-r--r--chrome/browser/task_manager_unittest.cc6
-rw-r--r--chrome/browser/task_manager_win.cc521
6 files changed, 618 insertions, 506 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index dd12b4c..9c7094a 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -806,6 +806,10 @@
>
</File>
<File
+ RelativePath=".\task_manager_win.cc"
+ >
+ </File>
+ <File
RelativePath=".\task_manager_resource_providers.cc"
>
</File>
diff --git a/chrome/browser/task_manager.cc b/chrome/browser/task_manager.cc
index b4c9bbe..43d328d 100644
--- a/chrome/browser/task_manager.cc
+++ b/chrome/browser/task_manager.cc
@@ -22,31 +22,10 @@
#include "grit/theme_resources.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
-#include "views/accelerator.h"
-#include "views/background.h"
-#include "views/controls/button/native_button.h"
-#include "views/controls/link.h"
-#include "views/controls/menu/menu.h"
-#include "views/controls/table/group_table_view.h"
-#include "views/standard_layout.h"
-#include "views/widget/widget.h"
-#include "views/window/dialog_delegate.h"
-#include "views/window/window.h"
-
-// The task manager window default size.
-static const int kDefaultWidth = 460;
-static const int kDefaultHeight = 270;
// The delay between updates of the information (in ms).
static const int kUpdateTimeMs = 1000;
-// An id for the most important column, made sufficiently large so as not to
-// collide with anything else.
-static const int64 kNuthMagicNumber = 1737350766;
-static const int kBitMask = 0x7FFFFFFF;
-static const int kGoatsTeleportedColumn =
- (94024 * kNuthMagicNumber) & kBitMask;
-
template <class T>
static int ValueCompare(T value1, T value2) {
if (value1 < value2)
@@ -225,8 +204,8 @@ int TaskManagerModel::CompareValues(int row1, int row2, int col_id) const {
NOTREACHED();
}
}
- std::wstring title1 = GetResourceTitle(row1);
- std::wstring title2 = GetResourceTitle(row2);
+ string16 title1 = WideToUTF16(GetResourceTitle(row1));
+ string16 title2 = WideToUTF16(GetResourceTitle(row2));
UErrorCode compare_status = U_ZERO_ERROR;
UCollationResult compare_result = collator->compare(
static_cast<const UChar*>(title1.c_str()),
@@ -704,467 +683,6 @@ bool TaskManagerModel::GetProcessMetricsForRows(
}
////////////////////////////////////////////////////////////////////////////////
-// TaskManagerTableModel class
-////////////////////////////////////////////////////////////////////////////////
-
-class TaskManagerTableModel : public views::GroupTableModel,
- public TaskManagerModelObserver {
- public:
- explicit TaskManagerTableModel(TaskManagerModel* model)
- : model_(model),
- observer_(NULL) {
- model->SetObserver(this);
- }
- ~TaskManagerTableModel() {}
-
- // GroupTableModel.
- int RowCount();
- std::wstring GetText(int row, int column);
- SkBitmap GetIcon(int row);
- void GetGroupRangeForItem(int item, views::GroupRange* range);
- void SetObserver(views::TableModelObserver* observer);
- virtual int CompareValues(int row1, int row2, int column_id);
-
- // TaskManagerModelObserver.
- virtual void OnModelChanged();
- virtual void OnItemsChanged(int start, int length);
- virtual void OnItemsAdded(int start, int length);
- virtual void OnItemsRemoved(int start, int length);
-
- private:
- const TaskManagerModel* model_;
- views::TableModelObserver* observer_;
-};
-
-int TaskManagerTableModel::RowCount() {
- return model_->ResourceCount();
-}
-
-std::wstring TaskManagerTableModel::GetText(int row, int col_id) {
- switch (col_id) {
- case IDS_TASK_MANAGER_PAGE_COLUMN: // Process
- return model_->GetResourceTitle(row);
-
- case IDS_TASK_MANAGER_NET_COLUMN: // Net
- return model_->GetResourceNetworkUsage(row);
-
- case IDS_TASK_MANAGER_CPU_COLUMN: // CPU
- if (!model_->IsResourceFirstInGroup(row))
- return std::wstring();
- return model_->GetResourceCPUUsage(row);
-
- case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory
- if (!model_->IsResourceFirstInGroup(row))
- return std::wstring();
- return model_->GetResourcePrivateMemory(row);
-
- case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory
- if (!model_->IsResourceFirstInGroup(row))
- return std::wstring();
- return model_->GetResourceSharedMemory(row);
-
- case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: // Memory
- if (!model_->IsResourceFirstInGroup(row))
- return std::wstring();
- return model_->GetResourcePhysicalMemory(row);
-
- case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
- if (!model_->IsResourceFirstInGroup(row))
- return std::wstring();
- return model_->GetResourceProcessId(row);
-
- case kGoatsTeleportedColumn: // Goats Teleported!
- return model_->GetResourceGoatsTeleported(row);
-
- default:
- return model_->GetResourceStatsValue(row, col_id);
- }
-}
-
-SkBitmap TaskManagerTableModel::GetIcon(int row) {
- return model_->GetResourceIcon(row);
-}
-
-void TaskManagerTableModel::GetGroupRangeForItem(int item,
- views::GroupRange* range) {
- std::pair<int, int> range_pair = model_->GetGroupRangeForResource(item);
- range->start = range_pair.first;
- range->length = range_pair.second;
-}
-
-void TaskManagerTableModel::SetObserver(views::TableModelObserver* observer) {
- observer_ = observer;
-}
-
-int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) {
- return model_->CompareValues(row1, row2, column_id);
-}
-
-void TaskManagerTableModel::OnModelChanged() {
- if (observer_)
- observer_->OnModelChanged();
-}
-
-void TaskManagerTableModel::OnItemsChanged(int start, int length) {
- if (observer_)
- observer_->OnItemsChanged(start, length);
-}
-
-void TaskManagerTableModel::OnItemsAdded(int start, int length) {
- if (observer_)
- observer_->OnItemsAdded(start, length);
-}
-
-void TaskManagerTableModel::OnItemsRemoved(int start, int length) {
- if (observer_)
- observer_->OnItemsRemoved(start, length);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TaskManagerContents class
-//
-// The view containing the different widgets.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-class TaskManagerContents : public views::View,
- public views::ButtonListener,
- public views::DialogDelegate,
- public views::TableViewObserver,
- public views::LinkController,
- public views::ContextMenuController,
- public Menu::Delegate {
- public:
- TaskManagerContents(TaskManager* task_manager,
- TaskManagerModel* model);
- virtual ~TaskManagerContents();
-
- void Init(TaskManagerModel* model);
- virtual void Layout();
- virtual gfx::Size GetPreferredSize();
- virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
- views::View* child);
- void GetSelection(std::vector<int>* selection);
- void GetFocused(std::vector<int>* focused);
-
- // ButtonListener implementation.
- virtual void ButtonPressed(views::Button* sender);
-
- // views::DialogDelegate
- virtual bool CanResize() const;
- virtual bool CanMaximize() const;
- virtual bool IsAlwaysOnTop() const;
- virtual bool HasAlwaysOnTopMenu() const;
- virtual std::wstring GetWindowTitle() const;
- virtual std::wstring GetWindowName() const;
- virtual int GetDialogButtons() const;
- virtual void WindowClosing();
- virtual void DeleteDelegate();
- virtual views::View* GetContentsView();
-
- // views::TableViewObserver implementation.
- virtual void OnSelectionChanged();
- virtual void OnDoubleClick();
- virtual void OnKeyDown(unsigned short virtual_keycode);
-
- // views::LinkController implementation.
- virtual void LinkActivated(views::Link* source, int event_flags);
-
- // Called by the column picker to pick up any new stat counters that
- // may have appeared since last time.
- void UpdateStatsCounters();
-
- // Menu::Delegate
- virtual void ShowContextMenu(views::View* source,
- int x,
- int y,
- bool is_mouse_gesture);
- virtual bool IsItemChecked(int id) const;
- virtual void ExecuteCommand(int id);
-
- private:
- scoped_ptr<views::NativeButton> kill_button_;
- scoped_ptr<views::Link> about_memory_link_;
- views::GroupTableView* tab_table_;
-
- TaskManager* task_manager_;
-
- // all possible columns, not necessarily visible
- std::vector<views::TableColumn> columns_;
-
- scoped_ptr<TaskManagerTableModel> table_model_;
-
- DISALLOW_EVIL_CONSTRUCTORS(TaskManagerContents);
-};
-
-TaskManagerContents::TaskManagerContents(TaskManager* task_manager,
- TaskManagerModel* model)
- : task_manager_(task_manager) {
- Init(model);
-}
-
-TaskManagerContents::~TaskManagerContents() {
-}
-
-void TaskManagerContents::Init(TaskManagerModel* model) {
- table_model_.reset(new TaskManagerTableModel(model));
-
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN,
- views::TableColumn::LEFT, -1, 1));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_CPU_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_NET_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
- columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
- views::TableColumn::RIGHT, -1, 0));
- columns_.back().sortable = true;
-
- tab_table_ = new views::GroupTableView(table_model_.get(), columns_,
- views::ICON_AND_TEXT, false, true,
- true);
-
- // Hide some columns by default
- tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, false);
- tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false);
- tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false);
-
- UpdateStatsCounters();
- views::TableColumn col(kGoatsTeleportedColumn, L"Goats Teleported",
- views::TableColumn::RIGHT, -1, 0);
- col.sortable = true;
- columns_.push_back(col);
- tab_table_->AddColumn(col);
- tab_table_->SetObserver(this);
- SetContextMenuController(this);
- kill_button_.reset(new views::NativeButton(
- this, l10n_util::GetString(IDS_TASK_MANAGER_KILL)));
- kill_button_->AddAccelerator(views::Accelerator('E', false, false, false));
- kill_button_->SetAccessibleKeyboardShortcut(L"E");
- about_memory_link_.reset(new views::Link(
- l10n_util::GetString(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)));
- about_memory_link_->SetController(this);
-
- AddChildView(tab_table_);
-
- // Makes sure our state is consistent.
- OnSelectionChanged();
-}
-
-void TaskManagerContents::UpdateStatsCounters() {
- StatsTable* stats = StatsTable::current();
- if (stats != NULL) {
- int max = stats->GetMaxCounters();
- // skip the first row (it's header data)
- for (int i = 1; i < max; i++) {
- const char* row = stats->GetRowName(i);
- if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) {
- // TODO(erikkay): Use l10n to get display names for stats. Right
- // now we're just displaying the internal counter name. Perhaps
- // stat names not in the string table would be filtered out.
- // TODO(erikkay): Width is hard-coded right now, so many column
- // names are clipped.
- views::TableColumn col(i, ASCIIToWide(row), views::TableColumn::RIGHT,
- 90, 0);
- col.sortable = true;
- columns_.push_back(col);
- tab_table_->AddColumn(col);
- }
- }
- }
-}
-
-void TaskManagerContents::ViewHierarchyChanged(bool is_add,
- views::View* parent,
- views::View* child) {
- // Since we want the Kill button and the Memory Details link to show up in
- // the same visual row as the close button, which is provided by the
- // framework, we must add the buttons to the non-client view, which is the
- // parent of this view. Similarly, when we're removed from the view
- // hierarchy, we must take care to clean up those items as well.
- if (child == this) {
- if (is_add) {
- parent->AddChildView(kill_button_.get());
- parent->AddChildView(about_memory_link_.get());
- } else {
- parent->RemoveChildView(kill_button_.get());
- parent->RemoveChildView(about_memory_link_.get());
- // Note that these items aren't deleted here, since this object is owned
- // by the TaskManager, whose lifetime surpasses the window, and the next
- // time we are inserted into a window these items will need to be valid.
- }
- }
-}
-
-void TaskManagerContents::Layout() {
- // kPanelHorizMargin is too big.
- const int kTableButtonSpacing = 12;
-
- gfx::Size size = kill_button_->GetPreferredSize();
- int prefered_width = size.width();
- int prefered_height = size.height();
-
- tab_table_->SetBounds(x() + kPanelHorizMargin,
- y() + kPanelVertMargin,
- width() - 2 * kPanelHorizMargin,
- height() - 2 * kPanelVertMargin - prefered_height);
-
- // y-coordinate of button top left.
- gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
- int y_buttons = parent_bounds.bottom() - prefered_height - kButtonVEdgeMargin;
-
- kill_button_->SetBounds(x() + width() - prefered_width - kPanelHorizMargin,
- y_buttons,
- prefered_width,
- prefered_height);
-
- size = about_memory_link_->GetPreferredSize();
- int link_prefered_width = size.width();
- int link_prefered_height = size.height();
- // center between the two buttons horizontally, and line up with
- // bottom of buttons vertically.
- int link_y_offset = std::max(0, prefered_height - link_prefered_height) / 2;
- about_memory_link_->SetBounds(
- x() + kPanelHorizMargin,
- y_buttons + prefered_height - link_prefered_height - link_y_offset,
- link_prefered_width,
- link_prefered_height);
-}
-
-gfx::Size TaskManagerContents::GetPreferredSize() {
- return gfx::Size(kDefaultWidth, kDefaultHeight);
-}
-
-void TaskManagerContents::GetSelection(std::vector<int>* selection) {
- DCHECK(selection);
- for (views::TableSelectionIterator iter = tab_table_->SelectionBegin();
- iter != tab_table_->SelectionEnd(); ++iter) {
- // The TableView returns the selection starting from the end.
- selection->insert(selection->begin(), *iter);
- }
-}
-
-void TaskManagerContents::GetFocused(std::vector<int>* focused) {
- DCHECK(focused);
- int row_count = tab_table_->RowCount();
- for (int i = 0; i < row_count; ++i) {
- // The TableView returns the selection starting from the end.
- if (tab_table_->ItemHasTheFocus(i))
- focused->insert(focused->begin(), i);
- }
-}
-
-// ButtonListener implementation.
-void TaskManagerContents::ButtonPressed(views::Button* sender) {
- if (sender == kill_button_.get())
- task_manager_->KillSelectedProcesses();
-}
-
-// DialogDelegate implementation.
-bool TaskManagerContents::CanResize() const {
- return true;
-}
-
-bool TaskManagerContents::CanMaximize() const {
- return true;
-}
-
-bool TaskManagerContents::IsAlwaysOnTop() const {
- return true;
-}
-
-bool TaskManagerContents::HasAlwaysOnTopMenu() const {
- return true;
-};
-
-std::wstring TaskManagerContents::GetWindowTitle() const {
- return l10n_util::GetString(IDS_TASK_MANAGER_TITLE);
-}
-
-std::wstring TaskManagerContents::GetWindowName() const {
- return prefs::kTaskManagerWindowPlacement;
-}
-
-int TaskManagerContents::GetDialogButtons() const {
- return MessageBoxFlags::DIALOGBUTTON_NONE;
-}
-
-void TaskManagerContents::WindowClosing() {
- // Remove the view from its parent to trigger the contents'
- // ViewHierarchyChanged notification to unhook the extra buttons from the
- // non-client view.
- GetParent()->RemoveChildView(this);
- task_manager_->Close();
-}
-
-void TaskManagerContents::DeleteDelegate() {
- ReleaseWindow();
-}
-
-views::View* TaskManagerContents::GetContentsView() {
- return this;
-}
-
-// views::TableViewObserver implementation.
-void TaskManagerContents::OnSelectionChanged() {
- kill_button_->SetEnabled(!task_manager_->BrowserProcessIsSelected() &&
- tab_table_->SelectedRowCount() > 0);
-}
-
-void TaskManagerContents::OnDoubleClick() {
- task_manager_->ActivateFocusedTab();
-}
-
-void TaskManagerContents::OnKeyDown(unsigned short virtual_keycode) {
- if (virtual_keycode == VK_RETURN)
- task_manager_->ActivateFocusedTab();
-}
-
-// views::LinkController implementation
-void TaskManagerContents::LinkActivated(views::Link* source,
- int event_flags) {
- DCHECK(source == about_memory_link_);
- Browser* browser = BrowserList::GetLastActive();
- DCHECK(browser);
- browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB,
- PageTransition::LINK);
- // In case the browser window is minimzed, show it.
- browser->window()->Show();
-}
-
-void TaskManagerContents::ShowContextMenu(views::View* source,
- int x,
- int y,
- bool is_mouse_gesture) {
- UpdateStatsCounters();
- Menu menu(this, Menu::TOPLEFT, source->GetWidget()->GetNativeView());
- for (std::vector<views::TableColumn>::iterator i =
- columns_.begin(); i != columns_.end(); ++i) {
- menu.AppendMenuItem(i->id, i->title, Menu::CHECKBOX);
- }
- menu.RunMenuAt(x, y);
-}
-
-bool TaskManagerContents::IsItemChecked(int id) const {
- return tab_table_->IsColumnVisible(id);
-}
-
-void TaskManagerContents::ExecuteCommand(int id) {
- tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id));
-}
-
-////////////////////////////////////////////////////////////////////////////////
// TaskManager class
////////////////////////////////////////////////////////////////////////////////
@@ -1173,9 +691,8 @@ void TaskManager::RegisterPrefs(PrefService* prefs) {
prefs->RegisterDictionaryPref(prefs::kTaskManagerWindowPlacement);
}
-TaskManager::TaskManager() {
- model_ = new TaskManagerModel(this);
- contents_.reset(new TaskManagerContents(this, model_.get()));
+TaskManager::TaskManager() : model_(new TaskManagerModel(this)) {
+ Init();
}
TaskManager::~TaskManager() {
@@ -1184,14 +701,7 @@ TaskManager::~TaskManager() {
// static
void TaskManager::Open() {
TaskManager* task_manager = GetInstance();
- if (task_manager->contents_->window()) {
- task_manager->contents_->window()->Activate();
- } else {
- views::Window::CreateChromeWindow(NULL, gfx::Rect(),
- task_manager->contents_.get());
- task_manager->model_->StartUpdating();
- task_manager->contents_->window()->Show();
- }
+ task_manager->view_->OpenWindow();
}
void TaskManager::Close() {
@@ -1200,17 +710,18 @@ void TaskManager::Close() {
}
bool TaskManager::BrowserProcessIsSelected() {
- if (!contents_.get())
+ if (!view_.get())
return false;
std::vector<int> selection;
- contents_->GetSelection(&selection);
+ view_->GetSelection(&selection);
for (std::vector<int>::const_iterator iter = selection.begin();
iter != selection.end(); ++iter) {
// If some of the selection is out of bounds, ignore. This may happen when
// killing a process that manages several pages.
if (*iter >= model_->ResourceCount())
continue;
- if (model_->GetResourceProcessHandle(*iter) == GetCurrentProcess())
+ if (model_->GetResourceProcessHandle(*iter) ==
+ base::GetCurrentProcessHandle())
return true;
}
return false;
@@ -1218,20 +729,20 @@ bool TaskManager::BrowserProcessIsSelected() {
void TaskManager::KillSelectedProcesses() {
std::vector<int> selection;
- contents_->GetSelection(&selection);
+ view_->GetSelection(&selection);
for (std::vector<int>::const_iterator iter = selection.begin();
iter != selection.end(); ++iter) {
base::ProcessHandle process = model_->GetResourceProcessHandle(*iter);
DCHECK(process);
- if (process == GetCurrentProcess())
+ if (process == base::GetCurrentProcessHandle())
continue;
- TerminateProcess(process, 0);
+ base::KillProcess(process, base::PROCESS_END_KILLED_BY_USER, false);
}
}
void TaskManager::ActivateFocusedTab() {
std::vector<int> focused;
- contents_->GetFocused(&focused);
+ view_->GetFocused(&focused);
int focused_size = static_cast<int>(focused.size());
DCHECK(focused_size == 1);
diff --git a/chrome/browser/task_manager.h b/chrome/browser/task_manager.h
index b01a30f..d58a21e 100644
--- a/chrome/browser/task_manager.h
+++ b/chrome/browser/task_manager.h
@@ -24,7 +24,7 @@
class MessageLoop;
class SkBitmap;
class TaskManager;
-class TaskManagerContents;
+class TaskManagerView;
class TaskManagerModel;
struct BytesReadParam;
@@ -138,7 +138,7 @@ class TaskManager {
scoped_refptr<TaskManagerModel> model_;
// A container containing the buttons and table.
- scoped_ptr<TaskManagerContents> contents_;
+ scoped_ptr<TaskManagerView> view_;
DISALLOW_COPY_AND_ASSIGN(TaskManager);
};
@@ -346,4 +346,14 @@ class TaskManagerModel : public URLRequestJobTracker::JobObserver,
DISALLOW_COPY_AND_ASSIGN(TaskManagerModel);
};
+class TaskManagerView {
+ public:
+ virtual ~TaskManagerView() {}
+
+ virtual void GetSelection(std::vector<int>* selection) = 0;
+ virtual void GetFocused(std::vector<int>* focused) = 0;
+
+ virtual void OpenWindow() = 0;
+};
+
#endif // CHROME_BROWSER_TASK_MANAGER_H_
diff --git a/chrome/browser/task_manager_linux.cc b/chrome/browser/task_manager_linux.cc
new file mode 100644
index 0000000..f4568de
--- /dev/null
+++ b/chrome/browser/task_manager_linux.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager.h"
+
+#include <vector>
+
+#include "base/logging.h"
+
+namespace {
+
+class TaskManagerViewImpl : public TaskManagerView,
+ public TaskManagerModelObserver {
+ public:
+ TaskManagerViewImpl(TaskManagerModel* model) {
+ model->SetObserver(this);
+ }
+
+ // TaskManagerView
+ virtual void GetSelection(std::vector<int>* selection);
+ virtual void GetFocused(std::vector<int>* focused);
+ virtual void OpenWindow();
+
+ // TaskManagerModelObserver
+ virtual void OnModelChanged();
+ virtual void OnItemsChanged(int start, int length);
+ virtual void OnItemsAdded(int start, int length);
+ virtual void OnItemsRemoved(int start, int length);
+};
+
+void TaskManagerViewImpl::GetSelection(std::vector<int>* selection) {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::GetFocused(std::vector<int>* focused) {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::OpenWindow() {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::OnModelChanged() {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::OnItemsChanged(int start, int length) {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::OnItemsAdded(int start, int length) {
+ NOTIMPLEMENTED();
+}
+
+void TaskManagerViewImpl::OnItemsRemoved(int start, int length) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace
+
+void TaskManager::Init() {
+ view_.reset(new TaskManagerViewImpl(model_.get()));
+}
diff --git a/chrome/browser/task_manager_unittest.cc b/chrome/browser/task_manager_unittest.cc
index 4550f8b..70bb710 100644
--- a/chrome/browser/task_manager_unittest.cc
+++ b/chrome/browser/task_manager_unittest.cc
@@ -7,10 +7,10 @@
#include <string>
#include "app/l10n_util.h"
+#include "base/process_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "views/controls/table/table_view.h"
namespace {
@@ -18,7 +18,9 @@ class TestResource : public TaskManager::Resource {
public:
virtual std::wstring GetTitle() const { return L"test title"; }
virtual SkBitmap GetIcon() const { return SkBitmap(); }
- virtual HANDLE GetProcess() const { return NULL; }
+ virtual base::ProcessHandle GetProcess() const {
+ return base::GetCurrentProcessHandle();
+ }
virtual bool SupportNetworkUsage() const { return false; }
virtual void SetSupportNetworkUsage() { NOTREACHED(); }
};
diff --git a/chrome/browser/task_manager_win.cc b/chrome/browser/task_manager_win.cc
new file mode 100644
index 0000000..9fa0eba
--- /dev/null
+++ b/chrome/browser/task_manager_win.cc
@@ -0,0 +1,521 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager.h"
+
+#include "base/stats_table.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "views/accelerator.h"
+#include "views/background.h"
+#include "views/controls/button/native_button.h"
+#include "views/controls/link.h"
+#include "views/controls/menu/menu.h"
+#include "views/controls/table/group_table_view.h"
+#include "views/standard_layout.h"
+#include "views/widget/widget.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
+
+// The task manager window default size.
+static const int kDefaultWidth = 460;
+static const int kDefaultHeight = 270;
+
+// An id for the most important column, made sufficiently large so as not to
+// collide with anything else.
+static const int64 kNuthMagicNumber = 1737350766;
+static const int kBitMask = 0x7FFFFFFF;
+static const int kGoatsTeleportedColumn =
+ (94024 * kNuthMagicNumber) & kBitMask;
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerTableModel class
+////////////////////////////////////////////////////////////////////////////////
+
+class TaskManagerTableModel : public views::GroupTableModel,
+ public TaskManagerModelObserver {
+ public:
+ explicit TaskManagerTableModel(TaskManagerModel* model)
+ : model_(model),
+ observer_(NULL) {
+ model->SetObserver(this);
+ }
+ ~TaskManagerTableModel() {}
+
+ // GroupTableModel.
+ int RowCount();
+ std::wstring GetText(int row, int column);
+ SkBitmap GetIcon(int row);
+ void GetGroupRangeForItem(int item, views::GroupRange* range);
+ void SetObserver(views::TableModelObserver* observer);
+ virtual int CompareValues(int row1, int row2, int column_id);
+
+ // TaskManagerModelObserver.
+ virtual void OnModelChanged();
+ virtual void OnItemsChanged(int start, int length);
+ virtual void OnItemsAdded(int start, int length);
+ virtual void OnItemsRemoved(int start, int length);
+
+ private:
+ const TaskManagerModel* model_;
+ views::TableModelObserver* observer_;
+};
+
+int TaskManagerTableModel::RowCount() {
+ return model_->ResourceCount();
+}
+
+std::wstring TaskManagerTableModel::GetText(int row, int col_id) {
+ switch (col_id) {
+ case IDS_TASK_MANAGER_PAGE_COLUMN: // Process
+ return model_->GetResourceTitle(row);
+
+ case IDS_TASK_MANAGER_NET_COLUMN: // Net
+ return model_->GetResourceNetworkUsage(row);
+
+ case IDS_TASK_MANAGER_CPU_COLUMN: // CPU
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::wstring();
+ return model_->GetResourceCPUUsage(row);
+
+ case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::wstring();
+ return model_->GetResourcePrivateMemory(row);
+
+ case IDS_TASK_MANAGER_SHARED_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::wstring();
+ return model_->GetResourceSharedMemory(row);
+
+ case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN: // Memory
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::wstring();
+ return model_->GetResourcePhysicalMemory(row);
+
+ case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
+ if (!model_->IsResourceFirstInGroup(row))
+ return std::wstring();
+ return model_->GetResourceProcessId(row);
+
+ case kGoatsTeleportedColumn: // Goats Teleported!
+ return model_->GetResourceGoatsTeleported(row);
+
+ default:
+ return model_->GetResourceStatsValue(row, col_id);
+ }
+}
+
+SkBitmap TaskManagerTableModel::GetIcon(int row) {
+ return model_->GetResourceIcon(row);
+}
+
+void TaskManagerTableModel::GetGroupRangeForItem(int item,
+ views::GroupRange* range) {
+ std::pair<int, int> range_pair = model_->GetGroupRangeForResource(item);
+ range->start = range_pair.first;
+ range->length = range_pair.second;
+}
+
+void TaskManagerTableModel::SetObserver(views::TableModelObserver* observer) {
+ observer_ = observer;
+}
+
+int TaskManagerTableModel::CompareValues(int row1, int row2, int column_id) {
+ return model_->CompareValues(row1, row2, column_id);
+}
+
+void TaskManagerTableModel::OnModelChanged() {
+ if (observer_)
+ observer_->OnModelChanged();
+}
+
+void TaskManagerTableModel::OnItemsChanged(int start, int length) {
+ if (observer_)
+ observer_->OnItemsChanged(start, length);
+}
+
+void TaskManagerTableModel::OnItemsAdded(int start, int length) {
+ if (observer_)
+ observer_->OnItemsAdded(start, length);
+}
+
+void TaskManagerTableModel::OnItemsRemoved(int start, int length) {
+ if (observer_)
+ observer_->OnItemsRemoved(start, length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TaskManagerViewImpl class
+//
+// The view containing the different widgets.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+class TaskManagerViewImpl : public TaskManagerView,
+ public views::View,
+ public views::ButtonListener,
+ public views::DialogDelegate,
+ public views::TableViewObserver,
+ public views::LinkController,
+ public views::ContextMenuController,
+ public Menu::Delegate {
+ public:
+ TaskManagerViewImpl(TaskManager* task_manager,
+ TaskManagerModel* model);
+ virtual ~TaskManagerViewImpl();
+
+ void Init();
+ virtual void Layout();
+ virtual gfx::Size GetPreferredSize();
+ virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
+ views::View* child);
+
+ // TaskManagerView
+ virtual void GetSelection(std::vector<int>* selection);
+ virtual void GetFocused(std::vector<int>* focused);
+ virtual void OpenWindow();
+
+ // ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* sender);
+
+ // views::DialogDelegate
+ virtual bool CanResize() const;
+ virtual bool CanMaximize() const;
+ virtual bool IsAlwaysOnTop() const;
+ virtual bool HasAlwaysOnTopMenu() const;
+ virtual std::wstring GetWindowTitle() const;
+ virtual std::wstring GetWindowName() const;
+ virtual int GetDialogButtons() const;
+ virtual void WindowClosing();
+ virtual void DeleteDelegate();
+ virtual views::View* GetContentsView();
+
+ // views::TableViewObserver implementation.
+ virtual void OnSelectionChanged();
+ virtual void OnDoubleClick();
+ virtual void OnKeyDown(unsigned short virtual_keycode);
+
+ // views::LinkController implementation.
+ virtual void LinkActivated(views::Link* source, int event_flags);
+
+ // Called by the column picker to pick up any new stat counters that
+ // may have appeared since last time.
+ void UpdateStatsCounters();
+
+ // Menu::Delegate
+ virtual void ShowContextMenu(views::View* source,
+ int x,
+ int y,
+ bool is_mouse_gesture);
+ virtual bool IsItemChecked(int id) const;
+ virtual void ExecuteCommand(int id);
+
+ private:
+ scoped_ptr<views::NativeButton> kill_button_;
+ scoped_ptr<views::Link> about_memory_link_;
+ views::GroupTableView* tab_table_;
+
+ TaskManager* task_manager_;
+
+ TaskManagerModel* model_;
+
+ // all possible columns, not necessarily visible
+ std::vector<views::TableColumn> columns_;
+
+ scoped_ptr<TaskManagerTableModel> table_model_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskManagerViewImpl);
+};
+
+TaskManagerViewImpl::TaskManagerViewImpl(TaskManager* task_manager,
+ TaskManagerModel* model)
+ : task_manager_(task_manager),
+ model_(model) {
+ Init();
+}
+
+TaskManagerViewImpl::~TaskManagerViewImpl() {
+}
+
+void TaskManagerViewImpl::Init() {
+ table_model_.reset(new TaskManagerTableModel(model_));
+
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PAGE_COLUMN,
+ views::TableColumn::LEFT, -1, 1));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_SHARED_MEM_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_CPU_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_NET_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+ columns_.push_back(views::TableColumn(IDS_TASK_MANAGER_PROCESS_ID_COLUMN,
+ views::TableColumn::RIGHT, -1, 0));
+ columns_.back().sortable = true;
+
+ tab_table_ = new views::GroupTableView(table_model_.get(), columns_,
+ views::ICON_AND_TEXT, false, true,
+ true);
+
+ // Hide some columns by default
+ tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PROCESS_ID_COLUMN, false);
+ tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_SHARED_MEM_COLUMN, false);
+ tab_table_->SetColumnVisibility(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, false);
+
+ UpdateStatsCounters();
+ views::TableColumn col(kGoatsTeleportedColumn, L"Goats Teleported",
+ views::TableColumn::RIGHT, -1, 0);
+ col.sortable = true;
+ columns_.push_back(col);
+ tab_table_->AddColumn(col);
+ tab_table_->SetObserver(this);
+ SetContextMenuController(this);
+ kill_button_.reset(new views::NativeButton(
+ this, l10n_util::GetString(IDS_TASK_MANAGER_KILL)));
+ kill_button_->AddAccelerator(views::Accelerator('E', false, false, false));
+ kill_button_->SetAccessibleKeyboardShortcut(L"E");
+ about_memory_link_.reset(new views::Link(
+ l10n_util::GetString(IDS_TASK_MANAGER_ABOUT_MEMORY_LINK)));
+ about_memory_link_->SetController(this);
+
+ AddChildView(tab_table_);
+
+ // Makes sure our state is consistent.
+ OnSelectionChanged();
+}
+
+void TaskManagerViewImpl::UpdateStatsCounters() {
+ StatsTable* stats = StatsTable::current();
+ if (stats != NULL) {
+ int max = stats->GetMaxCounters();
+ // skip the first row (it's header data)
+ for (int i = 1; i < max; i++) {
+ const char* row = stats->GetRowName(i);
+ if (row != NULL && row[0] != '\0' && !tab_table_->HasColumn(i)) {
+ // TODO(erikkay): Use l10n to get display names for stats. Right
+ // now we're just displaying the internal counter name. Perhaps
+ // stat names not in the string table would be filtered out.
+ // TODO(erikkay): Width is hard-coded right now, so many column
+ // names are clipped.
+ views::TableColumn col(i, ASCIIToWide(row), views::TableColumn::RIGHT,
+ 90, 0);
+ col.sortable = true;
+ columns_.push_back(col);
+ tab_table_->AddColumn(col);
+ }
+ }
+ }
+}
+
+void TaskManagerViewImpl::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ // Since we want the Kill button and the Memory Details link to show up in
+ // the same visual row as the close button, which is provided by the
+ // framework, we must add the buttons to the non-client view, which is the
+ // parent of this view. Similarly, when we're removed from the view
+ // hierarchy, we must take care to clean up those items as well.
+ if (child == this) {
+ if (is_add) {
+ parent->AddChildView(kill_button_.get());
+ parent->AddChildView(about_memory_link_.get());
+ } else {
+ parent->RemoveChildView(kill_button_.get());
+ parent->RemoveChildView(about_memory_link_.get());
+ // Note that these items aren't deleted here, since this object is owned
+ // by the TaskManager, whose lifetime surpasses the window, and the next
+ // time we are inserted into a window these items will need to be valid.
+ }
+ }
+}
+
+void TaskManagerViewImpl::Layout() {
+ // kPanelHorizMargin is too big.
+ const int kTableButtonSpacing = 12;
+
+ gfx::Size size = kill_button_->GetPreferredSize();
+ int prefered_width = size.width();
+ int prefered_height = size.height();
+
+ tab_table_->SetBounds(x() + kPanelHorizMargin,
+ y() + kPanelVertMargin,
+ width() - 2 * kPanelHorizMargin,
+ height() - 2 * kPanelVertMargin - prefered_height);
+
+ // y-coordinate of button top left.
+ gfx::Rect parent_bounds = GetParent()->GetLocalBounds(false);
+ int y_buttons = parent_bounds.bottom() - prefered_height - kButtonVEdgeMargin;
+
+ kill_button_->SetBounds(x() + width() - prefered_width - kPanelHorizMargin,
+ y_buttons,
+ prefered_width,
+ prefered_height);
+
+ size = about_memory_link_->GetPreferredSize();
+ int link_prefered_width = size.width();
+ int link_prefered_height = size.height();
+ // center between the two buttons horizontally, and line up with
+ // bottom of buttons vertically.
+ int link_y_offset = std::max(0, prefered_height - link_prefered_height) / 2;
+ about_memory_link_->SetBounds(
+ x() + kPanelHorizMargin,
+ y_buttons + prefered_height - link_prefered_height - link_y_offset,
+ link_prefered_width,
+ link_prefered_height);
+}
+
+gfx::Size TaskManagerViewImpl::GetPreferredSize() {
+ return gfx::Size(kDefaultWidth, kDefaultHeight);
+}
+
+void TaskManagerViewImpl::GetSelection(std::vector<int>* selection) {
+ DCHECK(selection);
+ for (views::TableSelectionIterator iter = tab_table_->SelectionBegin();
+ iter != tab_table_->SelectionEnd(); ++iter) {
+ // The TableView returns the selection starting from the end.
+ selection->insert(selection->begin(), *iter);
+ }
+}
+
+void TaskManagerViewImpl::GetFocused(std::vector<int>* focused) {
+ DCHECK(focused);
+ int row_count = tab_table_->RowCount();
+ for (int i = 0; i < row_count; ++i) {
+ // The TableView returns the selection starting from the end.
+ if (tab_table_->ItemHasTheFocus(i))
+ focused->insert(focused->begin(), i);
+ }
+}
+
+void TaskManagerViewImpl::OpenWindow() {
+ if (window()) {
+ window()->Activate();
+ } else {
+ views::Window::CreateChromeWindow(NULL, gfx::Rect(), this);
+ model_->StartUpdating();
+ window()->Show();
+ }
+}
+
+// ButtonListener implementation.
+void TaskManagerViewImpl::ButtonPressed(views::Button* sender) {
+ if (sender == kill_button_.get())
+ task_manager_->KillSelectedProcesses();
+}
+
+// DialogDelegate implementation.
+bool TaskManagerViewImpl::CanResize() const {
+ return true;
+}
+
+bool TaskManagerViewImpl::CanMaximize() const {
+ return true;
+}
+
+bool TaskManagerViewImpl::IsAlwaysOnTop() const {
+ return true;
+}
+
+bool TaskManagerViewImpl::HasAlwaysOnTopMenu() const {
+ return true;
+};
+
+std::wstring TaskManagerViewImpl::GetWindowTitle() const {
+ return l10n_util::GetString(IDS_TASK_MANAGER_TITLE);
+}
+
+std::wstring TaskManagerViewImpl::GetWindowName() const {
+ return prefs::kTaskManagerWindowPlacement;
+}
+
+int TaskManagerViewImpl::GetDialogButtons() const {
+ return MessageBoxFlags::DIALOGBUTTON_NONE;
+}
+
+void TaskManagerViewImpl::WindowClosing() {
+ // Remove the view from its parent to trigger the contents'
+ // ViewHierarchyChanged notification to unhook the extra buttons from the
+ // non-client view.
+ GetParent()->RemoveChildView(this);
+ task_manager_->Close();
+}
+
+void TaskManagerViewImpl::DeleteDelegate() {
+ ReleaseWindow();
+}
+
+views::View* TaskManagerViewImpl::GetContentsView() {
+ return this;
+}
+
+// views::TableViewObserver implementation.
+void TaskManagerViewImpl::OnSelectionChanged() {
+ kill_button_->SetEnabled(!task_manager_->BrowserProcessIsSelected() &&
+ tab_table_->SelectedRowCount() > 0);
+}
+
+void TaskManagerViewImpl::OnDoubleClick() {
+ task_manager_->ActivateFocusedTab();
+}
+
+void TaskManagerViewImpl::OnKeyDown(unsigned short virtual_keycode) {
+ if (virtual_keycode == VK_RETURN)
+ task_manager_->ActivateFocusedTab();
+}
+
+// views::LinkController implementation
+void TaskManagerViewImpl::LinkActivated(views::Link* source,
+ int event_flags) {
+ DCHECK(source == about_memory_link_);
+ Browser* browser = BrowserList::GetLastActive();
+ DCHECK(browser);
+ browser->OpenURL(GURL("about:memory"), GURL(), NEW_FOREGROUND_TAB,
+ PageTransition::LINK);
+ // In case the browser window is minimzed, show it.
+ browser->window()->Show();
+}
+
+void TaskManagerViewImpl::ShowContextMenu(views::View* source,
+ int x,
+ int y,
+ bool is_mouse_gesture) {
+ UpdateStatsCounters();
+ Menu menu(this, Menu::TOPLEFT, source->GetWidget()->GetNativeView());
+ for (std::vector<views::TableColumn>::iterator i =
+ columns_.begin(); i != columns_.end(); ++i) {
+ menu.AppendMenuItem(i->id, i->title, Menu::CHECKBOX);
+ }
+ menu.RunMenuAt(x, y);
+}
+
+bool TaskManagerViewImpl::IsItemChecked(int id) const {
+ return tab_table_->IsColumnVisible(id);
+}
+
+void TaskManagerViewImpl::ExecuteCommand(int id) {
+ tab_table_->SetColumnVisibility(id, !tab_table_->IsColumnVisible(id));
+}
+
+} // namespace
+
+void TaskManager::Init() {
+ view_.reset(new TaskManagerViewImpl(this, model_.get()));
+}