| Index: chrome/browser/ui/task_manager/task_manager_table_model.cc
|
| diff --git a/chrome/browser/ui/task_manager/task_manager_table_model.cc b/chrome/browser/ui/task_manager/task_manager_table_model.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..90f8865268757317063c0a49b6b4998fc7e2acc0
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/task_manager/task_manager_table_model.cc
|
| @@ -0,0 +1,721 @@
|
| +// Copyright 2015 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/ui/task_manager/task_manager_table_model.h"
|
| +
|
| +#include "base/i18n/number_formatting.h"
|
| +#include "base/i18n/rtl.h"
|
| +#include "base/prefs/scoped_user_pref_update.h"
|
| +#include "base/process/process_handle.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/task_management/task_manager_interface.h"
|
| +#include "chrome/browser/ui/task_manager/task_manager_columns.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "chrome/grit/generated_resources.h"
|
| +#include "components/nacl/browser/nacl_browser.h"
|
| +#include "content/public/common/result_codes.h"
|
| +#include "third_party/WebKit/public/web/WebCache.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/models/table_model_observer.h"
|
| +#include "ui/base/text/bytes_formatting.h"
|
| +
|
| +namespace task_management {
|
| +
|
| +namespace {
|
| +
|
| +#if defined(OS_MACOSX)
|
| +// Match Activity Monitor's default refresh rate.
|
| +const int64 kRefreshTimeMS = 2000;
|
| +
|
| +// Activity Monitor shows %cpu with one decimal digit -- be consistent with
|
| +// that.
|
| +const char kCpuTextFormatString[] = "%.1f";
|
| +#else
|
| +const int64 kRefreshTimeMS = 1000;
|
| +const char kCpuTextFormatString[] = "%.0f";
|
| +#endif // defined(OS_MACOSX)
|
| +
|
| +// The columns that are shared by a group will show the value of the column
|
| +// only once per group.
|
| +bool IsSharedByGroup(int column_id) {
|
| + switch (column_id) {
|
| + case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
|
| + case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
|
| + case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
|
| + case IDS_TASK_MANAGER_CPU_COLUMN:
|
| + case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
|
| + case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
|
| + case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN:
|
| + case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +// Used to sort various column values.
|
| +template <class T>
|
| +int ValueCompare(T value1, T value2) {
|
| + if (value1 == value2)
|
| + return 0;
|
| + return value1 < value2 ? -1 : 1;
|
| +}
|
| +
|
| +// Used when one or both of the results to compare are unavailable.
|
| +int OrderUnavailableValue(bool v1, bool v2) {
|
| + if (!v1 && !v2)
|
| + return 0;
|
| + return v1 ? 1 : -1;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// A class to stringify the task manager's values into string16s and to
|
| +// cache the common strings that will be reused many times like "N/A" and so on.
|
| +class TaskManagerValuesStringifier {
|
| + public:
|
| + TaskManagerValuesStringifier()
|
| + : n_a_string_(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT)),
|
| + zero_string_(base::ASCIIToUTF16("0")),
|
| + asterisk_string_(base::ASCIIToUTF16("*")),
|
| + unknown_string_(l10n_util::GetStringUTF16(
|
| + IDS_TASK_MANAGER_UNKNOWN_VALUE_TEXT)) {
|
| + }
|
| +
|
| + ~TaskManagerValuesStringifier() {}
|
| +
|
| + base::string16 GetCpuUsageText(double cpu_usage) {
|
| + return base::UTF8ToUTF16(base::StringPrintf(kCpuTextFormatString,
|
| + cpu_usage));
|
| + }
|
| +
|
| + base::string16 GetMemoryUsageText(int64 memory_usage, bool has_duplicates) {
|
| + if (memory_usage == -1)
|
| + return n_a_string_;
|
| +
|
| +#if defined(OS_MACOSX)
|
| + // System expectation is to show "100 kB", "200 MB", etc.
|
| + // TODO(thakis): [This TODO has been taken as is from the old task manager]:
|
| + // Switch to metric units (as opposed to powers of two).
|
| + base::string16 memory_text = ui::FormatBytes(memory_usage);
|
| +#else
|
| + base::string16 memory_text = base::FormatNumber(memory_usage / 1024);
|
| + // Adjust number string if necessary.
|
| + base::i18n::AdjustStringForLocaleDirection(&memory_text);
|
| + memory_text = l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_MEM_CELL_TEXT,
|
| + memory_text);
|
| +#endif // defined(OS_MACOSX)
|
| +
|
| + if (has_duplicates)
|
| + memory_text += asterisk_string_;
|
| +
|
| + return memory_text;
|
| + }
|
| +
|
| + base::string16 GetIdleWakeupsText(int idle_wakeups) {
|
| + if (idle_wakeups == -1)
|
| + return n_a_string_;
|
| +
|
| + return base::FormatNumber(idle_wakeups);
|
| + }
|
| +
|
| + base::string16 GetNaClPortText(int nacl_port) {
|
| + if (nacl_port == nacl::kGdbDebugStubPortUnused)
|
| + return n_a_string_;
|
| +
|
| + if (nacl_port == nacl::kGdbDebugStubPortUnknown)
|
| + return unknown_string_;
|
| +
|
| + return base::IntToString16(nacl_port);
|
| + }
|
| +
|
| + base::string16 GetWindowsHandlesText(int64 current, int64 peak) {
|
| + return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_HANDLES_CELL_TEXT,
|
| + base::Int64ToString16(current),
|
| + base::Int64ToString16(peak));
|
| + }
|
| +
|
| + base::string16 GetNetworkUsageText(int64 network_usage) {
|
| + if (network_usage == -1)
|
| + return n_a_string_;
|
| +
|
| + if (network_usage == 0)
|
| + return zero_string_;
|
| +
|
| + base::string16 net_byte = ui::FormatSpeed(network_usage);
|
| + // Force number string to have LTR directionality.
|
| + return base::i18n::GetDisplayStringInLTRDirectionality(net_byte);
|
| + }
|
| +
|
| + base::string16 GetProcessIdText(base::ProcessId proc_id) {
|
| + return base::IntToString16(proc_id);
|
| + }
|
| +
|
| + base::string16 FormatAllocatedAndUsedMemory(int64 allocated, int64 used) {
|
| + return l10n_util::GetStringFUTF16(
|
| + IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT,
|
| + ui::FormatBytesWithUnits(allocated, ui::DATA_UNITS_KIBIBYTE, false),
|
| + ui::FormatBytesWithUnits(used, ui::DATA_UNITS_KIBIBYTE, false));
|
| + }
|
| +
|
| + base::string16 GetWebCacheStatText(
|
| + const blink::WebCache::ResourceTypeStat& stat) {
|
| + return FormatAllocatedAndUsedMemory(stat.size, stat.liveSize);
|
| + }
|
| +
|
| + const base::string16& n_a_string() const { return n_a_string_; }
|
| + const base::string16& zero_string() const { return zero_string_; }
|
| + const base::string16& asterisk_string() const { return asterisk_string_; }
|
| + const base::string16& unknown_string() const { return unknown_string_; }
|
| +
|
| + private:
|
| + // The localized string "N/A".
|
| + const base::string16 n_a_string_;
|
| +
|
| + // The value 0 as a string "0".
|
| + const base::string16 zero_string_;
|
| +
|
| + // The string "*" that is used to show that there exists duplicates in the
|
| + // GPU memory.
|
| + const base::string16 asterisk_string_;
|
| +
|
| + // The string "Unknown".
|
| + const base::string16 unknown_string_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TaskManagerValuesStringifier);
|
| +};
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// TableSortDescriptor:
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +TableSortDescriptor::TableSortDescriptor()
|
| + : sorted_column_id(-1),
|
| + is_ascending(false) {
|
| +}
|
| +
|
| +TableSortDescriptor::TableSortDescriptor(int col_id, bool ascending)
|
| + : sorted_column_id(col_id),
|
| + is_ascending(ascending) {
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// TaskManagerTableModel:
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +TaskManagerTableModel::TaskManagerTableModel(int64_t refresh_flags,
|
| + TableViewDelegate* delegate)
|
| + : TaskManagerObserver(base::TimeDelta::FromMilliseconds(kRefreshTimeMS),
|
| + refresh_flags),
|
| + table_view_delegate_(delegate),
|
| + columns_settings_(new base::DictionaryValue),
|
| + table_model_observer_(nullptr),
|
| + stringifier_(new TaskManagerValuesStringifier) {
|
| + DCHECK(delegate);
|
| +}
|
| +
|
| +TaskManagerTableModel::~TaskManagerTableModel() {
|
| +}
|
| +
|
| +int TaskManagerTableModel::RowCount() {
|
| + return static_cast<int>(tasks_.size());
|
| +}
|
| +
|
| +base::string16 TaskManagerTableModel::GetText(int row, int column) {
|
| + if (IsSharedByGroup(column) && !IsTaskFirstInGroup(row))
|
| + return base::string16();
|
| +
|
| + switch (column) {
|
| + case IDS_TASK_MANAGER_TASK_COLUMN:
|
| + return observed_task_manager()->GetTitle(tasks_[row]);
|
| +
|
| + case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN:
|
| + return observed_task_manager()->GetProfileName(tasks_[row]);
|
| +
|
| + case IDS_TASK_MANAGER_NET_COLUMN:
|
| + return stringifier_->GetNetworkUsageText(
|
| + observed_task_manager()->GetNetworkUsage(tasks_[row]));
|
| +
|
| + case IDS_TASK_MANAGER_CPU_COLUMN:
|
| + return stringifier_->GetCpuUsageText(
|
| + observed_task_manager()->GetCpuUsage(tasks_[row]));
|
| +
|
| + case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
|
| + return stringifier_->GetMemoryUsageText(
|
| + observed_task_manager()->GetPrivateMemoryUsage(tasks_[row]), false);
|
| +
|
| + case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
|
| + return stringifier_->GetMemoryUsageText(
|
| + observed_task_manager()->GetSharedMemoryUsage(tasks_[row]), false);
|
| +
|
| + case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
|
| + return stringifier_->GetMemoryUsageText(
|
| + observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row]), false);
|
| +
|
| + case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
|
| + return stringifier_->GetProcessIdText(
|
| + observed_task_manager()->GetProcessId(tasks_[row]));
|
| +
|
| + case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: {
|
| + int64 current, peak;
|
| + observed_task_manager()->GetGDIHandles(tasks_[row], ¤t, &peak);
|
| + return stringifier_->GetWindowsHandlesText(current, peak);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: {
|
| + int64 current, peak;
|
| + observed_task_manager()->GetUSERHandles(tasks_[row], ¤t, &peak);
|
| + return stringifier_->GetWindowsHandlesText(current, peak);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
|
| + return stringifier_->GetIdleWakeupsText(
|
| + observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row]));
|
| +
|
| + case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN: {
|
| + blink::WebCache::ResourceTypeStats stats;
|
| + if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats))
|
| + return stringifier_->GetWebCacheStatText(stats.images);
|
| + return stringifier_->n_a_string();
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN: {
|
| + blink::WebCache::ResourceTypeStats stats;
|
| + if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats))
|
| + return stringifier_->GetWebCacheStatText(stats.scripts);
|
| + return stringifier_->n_a_string();
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: {
|
| + blink::WebCache::ResourceTypeStats stats;
|
| + if (observed_task_manager()->GetWebCacheStats(tasks_[row], &stats))
|
| + return stringifier_->GetWebCacheStatText(stats.cssStyleSheets);
|
| + return stringifier_->n_a_string();
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: {
|
| + bool has_duplicates = false;
|
| + return stringifier_->GetMemoryUsageText(
|
| + observed_task_manager()->GetGpuMemoryUsage(tasks_[row],
|
| + &has_duplicates),
|
| + has_duplicates);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
|
| + return stringifier_->GetMemoryUsageText(
|
| + observed_task_manager()->GetSqliteMemoryUsed(tasks_[row]), false);
|
| +
|
| + case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: {
|
| + int64 v8_allocated, v8_used;
|
| + if (observed_task_manager()->GetV8Memory(tasks_[row],
|
| + &v8_allocated,
|
| + &v8_used)) {
|
| + return stringifier_->FormatAllocatedAndUsedMemory(v8_allocated,
|
| + v8_used);
|
| + }
|
| + return stringifier_->n_a_string();
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
|
| + return stringifier_->GetNaClPortText(
|
| + observed_task_manager()->GetNaClDebugStubPort(tasks_[row]));
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + return base::string16();
|
| + }
|
| +}
|
| +
|
| +gfx::ImageSkia TaskManagerTableModel::GetIcon(int row) {
|
| + return observed_task_manager()->GetIcon(tasks_[row]);
|
| +}
|
| +
|
| +void TaskManagerTableModel::SetObserver(
|
| + ui::TableModelObserver* observer) {
|
| + table_model_observer_ = observer;
|
| +}
|
| +
|
| +int TaskManagerTableModel::CompareValues(int row1,
|
| + int row2,
|
| + int column_id) {
|
| + switch (column_id) {
|
| + case IDS_TASK_MANAGER_TASK_COLUMN:
|
| + case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN:
|
| + return ui::TableModel::CompareValues(row1, row2, column_id);
|
| +
|
| + case IDS_TASK_MANAGER_NET_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetNetworkUsage(tasks_[row1]),
|
| + observed_task_manager()->GetNetworkUsage(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_CPU_COLUMN:
|
| + return ValueCompare(observed_task_manager()->GetCpuUsage(tasks_[row1]),
|
| + observed_task_manager()->GetCpuUsage(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetPrivateMemoryUsage(tasks_[row1]),
|
| + observed_task_manager()->GetPrivateMemoryUsage(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetSharedMemoryUsage(tasks_[row1]),
|
| + observed_task_manager()->GetSharedMemoryUsage(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row1]),
|
| + observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetNaClDebugStubPort(tasks_[row1]),
|
| + observed_task_manager()->GetNaClDebugStubPort(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
|
| + return ValueCompare(observed_task_manager()->GetProcessId(tasks_[row1]),
|
| + observed_task_manager()->GetProcessId(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: {
|
| + int64 current1, peak1, current2, peak2;
|
| + observed_task_manager()->GetGDIHandles(tasks_[row1], ¤t1, &peak1);
|
| + observed_task_manager()->GetGDIHandles(tasks_[row2], ¤t2, &peak2);
|
| + return ValueCompare(current1, current2);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: {
|
| + int64 current1, peak1, current2, peak2;
|
| + observed_task_manager()->GetUSERHandles(tasks_[row1], ¤t1, &peak1);
|
| + observed_task_manager()->GetUSERHandles(tasks_[row2], ¤t2, &peak2);
|
| + return ValueCompare(current1, current2);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row1]),
|
| + observed_task_manager()->GetIdleWakeupsPerSecond(tasks_[row2]));
|
| +
|
| + case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: {
|
| + blink::WebCache::ResourceTypeStats stats1;
|
| + blink::WebCache::ResourceTypeStats stats2;
|
| + bool row1_stats_valid =
|
| + observed_task_manager()->GetWebCacheStats(tasks_[row1], &stats1);
|
| + bool row2_stats_valid =
|
| + observed_task_manager()->GetWebCacheStats(tasks_[row2], &stats2);
|
| + if (!row1_stats_valid || !row2_stats_valid)
|
| + return OrderUnavailableValue(row1_stats_valid, row2_stats_valid);
|
| +
|
| + switch (column_id) {
|
| + case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
|
| + return ValueCompare(stats1.images.size, stats2.images.size);
|
| + case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
|
| + return ValueCompare(stats1.scripts.size, stats2.scripts.size);
|
| + case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
|
| + return ValueCompare(stats1.cssStyleSheets.size,
|
| + stats2.cssStyleSheets.size);
|
| + default:
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: {
|
| + bool has_duplicates;
|
| + return ValueCompare(
|
| + observed_task_manager()->GetGpuMemoryUsage(tasks_[row1],
|
| + &has_duplicates),
|
| + observed_task_manager()->GetGpuMemoryUsage(tasks_[row2],
|
| + &has_duplicates));
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN: {
|
| + int64 allocated1, allocated2, used1, used2;
|
| + observed_task_manager()->GetV8Memory(tasks_[row1], &allocated1, &used1);
|
| + observed_task_manager()->GetV8Memory(tasks_[row2], &allocated2, &used2);
|
| + return ValueCompare(allocated1, allocated2);
|
| + }
|
| +
|
| + case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
|
| + return ValueCompare(
|
| + observed_task_manager()->GetSqliteMemoryUsed(tasks_[row1]),
|
| + observed_task_manager()->GetSqliteMemoryUsed(tasks_[row2]));
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| +void TaskManagerTableModel::GetRowsGroupRange(int row_index,
|
| + int* out_start,
|
| + int* out_length) {
|
| + int i = row_index;
|
| + for ( ; i >= 0; --i) {
|
| + if (IsTaskFirstInGroup(i))
|
| + break;
|
| + }
|
| +
|
| + CHECK_GE(i, 0);
|
| +
|
| + *out_start = i;
|
| + *out_length = observed_task_manager()->GetNumberOfTasksOnSameProcess(
|
| + tasks_[row_index]);
|
| +}
|
| +
|
| +void TaskManagerTableModel::OnTaskAdded(TaskId id) {
|
| + // For the table view scrollbar to behave correctly we must inform it that
|
| + // a new task has been added.
|
| +
|
| + // We will get a newly sorted list from the task manager as opposed to just
|
| + // adding |id| to |tasks_| because we want to keep |tasks_| sorted by proc IDs
|
| + // and then by Task IDs.
|
| + tasks_ = observed_task_manager()->GetTaskIdsList();
|
| + if (table_model_observer_)
|
| + table_model_observer_->OnItemsAdded(RowCount() - 1, 1);
|
| +}
|
| +
|
| +void TaskManagerTableModel::OnTaskToBeRemoved(TaskId id) {
|
| + auto index = std::find(tasks_.begin(), tasks_.end(), id);
|
| + if (index == tasks_.end())
|
| + return;
|
| + auto removed_index = index - tasks_.begin();
|
| + tasks_.erase(index);
|
| + if (table_model_observer_)
|
| + table_model_observer_->OnItemsRemoved(removed_index, 1);
|
| +}
|
| +
|
| +void TaskManagerTableModel::OnTasksRefreshed(
|
| + const TaskIdList& task_ids) {
|
| + tasks_ = task_ids;
|
| + OnRefresh();
|
| +}
|
| +
|
| +void TaskManagerTableModel::StartUpdating() {
|
| + TaskManagerInterface::GetTaskManager()->AddObserver(this);
|
| + tasks_ = observed_task_manager()->GetTaskIdsList();
|
| + OnRefresh();
|
| +}
|
| +
|
| +void TaskManagerTableModel::StopUpdating() {
|
| + observed_task_manager()->RemoveObserver(this);
|
| +}
|
| +
|
| +void TaskManagerTableModel::ActivateTask(int row_index) {
|
| + observed_task_manager()->ActivateTask(tasks_[row_index]);
|
| +}
|
| +
|
| +void TaskManagerTableModel::KillTask(int row_index) {
|
| + base::ProcessId proc_id = observed_task_manager()->GetProcessId(
|
| + tasks_[row_index]);
|
| +
|
| + DCHECK_NE(proc_id, base::GetCurrentProcId());
|
| +
|
| + base::Process process = base::Process::Open(proc_id);
|
| + process.Terminate(content::RESULT_CODE_KILLED, false);
|
| +}
|
| +
|
| +void TaskManagerTableModel::UpdateRefreshTypes(int column_id, bool visibility) {
|
| + bool new_visibility = visibility;
|
| + RefreshType type = REFRESH_TYPE_NONE;
|
| + switch (column_id) {
|
| + case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN:
|
| + case IDS_TASK_MANAGER_TASK_COLUMN:
|
| + case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
|
| + return; // The data is these columns do not change.
|
| +
|
| + case IDS_TASK_MANAGER_NET_COLUMN:
|
| + type = REFRESH_TYPE_NETWORK_USAGE;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_CPU_COLUMN:
|
| + type = REFRESH_TYPE_CPU;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
|
| + case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
|
| + case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
|
| + type = REFRESH_TYPE_MEMORY;
|
| + if (table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN) ||
|
| + table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN) ||
|
| + table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_SHARED_MEM_COLUMN)) {
|
| + new_visibility = true;
|
| + }
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN:
|
| + case IDS_TASK_MANAGER_USER_HANDLES_COLUMN:
|
| + type = REFRESH_TYPE_HANDLES;
|
| + if (table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_GDI_HANDLES_COLUMN) ||
|
| + table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_USER_HANDLES_COLUMN)) {
|
| + new_visibility = true;
|
| + }
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
|
| + type = REFRESH_TYPE_IDLE_WAKEUPS;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
|
| + case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
|
| + type = REFRESH_TYPE_WEBCACHE_STATS;
|
| + if (table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN) ||
|
| + table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN) ||
|
| + table_view_delegate_->IsColumnVisible(
|
| + IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN)) {
|
| + new_visibility = true;
|
| + }
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN:
|
| + type = REFRESH_TYPE_GPU_MEMORY;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
|
| + type = REFRESH_TYPE_SQLITE_MEMORY;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
|
| + type = REFRESH_TYPE_V8_MEMORY;
|
| + break;
|
| +
|
| + case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
|
| + type = REFRESH_TYPE_NACL;
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + if (new_visibility)
|
| + AddRefreshType(type);
|
| + else
|
| + RemoveRefreshType(type);
|
| +}
|
| +
|
| +bool TaskManagerTableModel::IsBrowserProcess(int row_index) const {
|
| + return observed_task_manager()->GetProcessId(tasks_[row_index]) ==
|
| + base::GetCurrentProcId();
|
| +}
|
| +
|
| +void TaskManagerTableModel::RetrieveSavedColumnsSettingsAndUpdateTable() {
|
| + if (!g_browser_process->local_state())
|
| + return;
|
| +
|
| + const base::DictionaryValue* dictionary =
|
| + g_browser_process->local_state()->GetDictionary(
|
| + prefs::kTaskManagerColumnVisibility);
|
| + if (!dictionary)
|
| + return;
|
| +
|
| + // Do a best effort of retrieving the correct settings from the local state.
|
| + // Use the default settings of the value if it fails to be retrieved.
|
| + std::string sorted_col_id;
|
| + bool sort_is_ascending = true;
|
| + dictionary->GetString(kSortColumnIdKey, &sorted_col_id);
|
| + dictionary->GetBoolean(kSortIsAscendingKey, &sort_is_ascending);
|
| +
|
| + int current_visible_column_index = 0;
|
| + for (size_t i = 0; i < kColumnsSize; ++i) {
|
| + const int col_id = kColumns[i].id;
|
| + const std::string col_id_key(GetColumnIdAsString(col_id));
|
| +
|
| + if (col_id_key.empty())
|
| + continue;
|
| +
|
| + bool col_visibility = kColumns[i].default_visibility;
|
| + dictionary->GetBoolean(col_id_key, &col_visibility);
|
| +
|
| + // If the above GetBoolean() fails, the |col_visibility| remains at the
|
| + // default visibility.
|
| + columns_settings_->SetBoolean(col_id_key, col_visibility);
|
| + table_view_delegate_->SetColumnVisibility(col_id, col_visibility);
|
| + UpdateRefreshTypes(col_id, col_visibility);
|
| +
|
| + if (col_visibility) {
|
| + if (sorted_col_id == col_id_key) {
|
| + if (sort_is_ascending == kColumns[i].initial_sort_is_ascending) {
|
| + table_view_delegate_->ToggleSortOrder(current_visible_column_index);
|
| + } else {
|
| + // Unfortunately the API of ui::TableView doesn't provide a clean way
|
| + // to sort by a particular column ID and a sort direction. If the
|
| + // retrieved sort direction is different than the initial one, we have
|
| + // to toggle the sort order twice!
|
| + // Note that the function takes the visible_column_index rather than
|
| + // a column ID.
|
| + table_view_delegate_->ToggleSortOrder(current_visible_column_index);
|
| + table_view_delegate_->ToggleSortOrder(current_visible_column_index);
|
| + }
|
| + }
|
| +
|
| + ++current_visible_column_index;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void TaskManagerTableModel::StoreColumnsSettings() {
|
| + PrefService* local_state = g_browser_process->local_state();
|
| + if (!local_state)
|
| + return;
|
| +
|
| + DictionaryPrefUpdate dict_update(local_state,
|
| + prefs::kTaskManagerColumnVisibility);
|
| +
|
| + base::DictionaryValue::Iterator it(*columns_settings_);
|
| + while (!it.IsAtEnd()) {
|
| + dict_update->Set(it.key(), it.value().CreateDeepCopy());
|
| + it.Advance();
|
| + }
|
| +
|
| + // Store the current sort status to be restored again at startup.
|
| + if (!table_view_delegate_->IsTableSorted()) {
|
| + dict_update->SetString(kSortColumnIdKey, "");
|
| + } else {
|
| + const auto& sort_descriptor = table_view_delegate_->GetSortDescriptor();
|
| + dict_update->SetString(
|
| + kSortColumnIdKey,
|
| + GetColumnIdAsString(sort_descriptor.sorted_column_id));
|
| + dict_update->SetBoolean(kSortIsAscendingKey, sort_descriptor.is_ascending);
|
| + }
|
| +}
|
| +
|
| +void TaskManagerTableModel::ToggleColumnVisibility(int column_id) {
|
| + bool new_visibility = !table_view_delegate_->IsColumnVisible(column_id);
|
| + table_view_delegate_->SetColumnVisibility(column_id, new_visibility);
|
| + columns_settings_->SetBoolean(GetColumnIdAsString(column_id), new_visibility);
|
| + UpdateRefreshTypes(column_id, new_visibility);
|
| +}
|
| +
|
| +void TaskManagerTableModel::OnRefresh() {
|
| + if (table_model_observer_)
|
| + table_model_observer_->OnItemsChanged(0, RowCount());
|
| +}
|
| +
|
| +bool TaskManagerTableModel::IsTaskFirstInGroup(int row_index) const {
|
| + if (row_index == 0)
|
| + return true;
|
| +
|
| + return observed_task_manager()->GetProcessId(tasks_[row_index - 1]) !=
|
| + observed_task_manager()->GetProcessId(tasks_[row_index]);
|
| +}
|
| +
|
| +
|
| +} // namespace task_management
|
|
|