Index: chrome/browser/task_manager/task_manager_browsertest_util.cc |
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.cc b/chrome/browser/task_manager/task_manager_browsertest_util.cc |
index edeccd0f4a2dc840a22a4dd3433dfa79aa03c7b7..d5b0aca85f62da49dcc001b4c3a58aab8db54fb0 100644 |
--- a/chrome/browser/task_manager/task_manager_browsertest_util.cc |
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.cc |
@@ -4,8 +4,10 @@ |
#include "chrome/browser/task_manager/task_manager_browsertest_util.h" |
+#include "base/bind_helpers.h" |
#include "base/command_line.h" |
#include "base/location.h" |
+#include "base/memory/ptr_util.h" |
#include "base/run_loop.h" |
#include "base/single_thread_task_runner.h" |
#include "base/strings/pattern.h" |
@@ -17,40 +19,267 @@ |
#include "base/timer/timer.h" |
#include "chrome/browser/browser_process.h" |
#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/sessions/session_tab_helper.h" |
+#include "chrome/browser/task_management/task_manager_interface.h" |
#include "chrome/browser/task_manager/resource_provider.h" |
#include "chrome/browser/task_manager/task_manager.h" |
+#include "chrome/browser/ui/browser_dialogs.h" |
+#include "chrome/browser/ui/task_manager/task_manager_table_model.h" |
#include "chrome/common/chrome_switches.h" |
#include "chrome/grit/generated_resources.h" |
#include "extensions/strings/grit/extensions_strings.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/models/table_model_observer.h" |
namespace task_manager { |
namespace browsertest_util { |
namespace { |
-class ResourceChangeObserver : public TaskManagerModelObserver { |
+// Returns whether chrome::ShowTaskManager() will, for the current platform and |
+// command line, show a view backed by a task_management::TaskManagerTableModel. |
+bool IsNewTaskManagerViewEnabled() { |
+#if defined(OS_MACOSX) |
+ if (!chrome::ToolkitViewsDialogsEnabled()) |
+ return false; |
+#endif |
+ return switches::NewTaskManagerEnabled(); |
+} |
+ |
+// Temporarily intercepts the calls between a TableModel and its Observer, |
+// running |callback| whenever anything happens. |
+class ScopedInterceptTableModelObserver : public ui::TableModelObserver { |
public: |
- ResourceChangeObserver(const TaskManagerModel* model, |
- int required_count, |
- const base::string16& title_pattern, |
- ColumnSpecifier column_specifier, |
- size_t min_column_value) |
- : model_(model), |
- required_count_(required_count), |
- title_pattern_(title_pattern), |
- column_specifier_(column_specifier), |
- min_column_value_(min_column_value) {} |
+ ScopedInterceptTableModelObserver( |
+ ui::TableModel* model_to_intercept, |
+ ui::TableModelObserver* real_table_model_observer, |
+ const base::Closure& callback) |
+ : model_to_intercept_(model_to_intercept), |
+ real_table_model_observer_(real_table_model_observer), |
+ callback_(callback) { |
+ model_to_intercept_->SetObserver(this); |
+ } |
- void OnModelChanged() override { OnResourceChange(); } |
+ ~ScopedInterceptTableModelObserver() override { |
+ model_to_intercept_->SetObserver(real_table_model_observer_); |
+ } |
- void OnItemsChanged(int start, int length) override { OnResourceChange(); } |
+ // ui::TableModelObserver: |
+ void OnModelChanged() override { |
+ real_table_model_observer_->OnModelChanged(); |
+ callback_.Run(); |
+ } |
+ void OnItemsChanged(int start, int length) override { |
+ real_table_model_observer_->OnItemsChanged(start, length); |
+ callback_.Run(); |
+ } |
+ void OnItemsAdded(int start, int length) override { |
+ real_table_model_observer_->OnItemsAdded(start, length); |
+ callback_.Run(); |
+ } |
+ void OnItemsRemoved(int start, int length) override { |
+ real_table_model_observer_->OnItemsRemoved(start, length); |
+ callback_.Run(); |
+ } |
- void OnItemsAdded(int start, int length) override { OnResourceChange(); } |
+ private: |
+ ui::TableModel* model_to_intercept_; |
+ ui::TableModelObserver* real_table_model_observer_; |
+ base::Closure callback_; |
+}; |
+ |
+} // namespace |
+ |
+// Implementation of TaskManagerTester for the 'new' TaskManager. |
+class TaskManagerTesterImpl : public TaskManagerTester { |
+ public: |
+ explicit TaskManagerTesterImpl(const base::Closure& on_resource_change) |
+ : model_(GetRealModel()) { |
+ // Eavesdrop the model->view conversation, since the model only supports |
+ // single observation. |
+ if (!on_resource_change.is_null()) { |
+ interceptor_.reset(new ScopedInterceptTableModelObserver( |
+ model_, model_->table_model_observer_, on_resource_change)); |
+ } |
+ } |
+ |
+ ~TaskManagerTesterImpl() override { |
+ CHECK_EQ(GetRealModel(), model_) << "Task Manager should not be hidden " |
+ "while TaskManagerTester is alive. " |
+ "This indicates a test bug."; |
+ } |
+ |
+ // TaskManagerTester: |
+ int GetRowCount() override { return model_->RowCount(); } |
+ |
+ base::string16 GetRowTitle(int row) override { |
+ return model_->GetText(row, IDS_TASK_MANAGER_TASK_COLUMN); |
+ } |
+ |
+ void ToggleColumnVisibility(ColumnSpecifier column) override { |
+ int column_id = 0; |
+ switch (column) { |
+ case COLUMN_NONE: |
+ return; |
+ case SQLITE_MEMORY_USED: |
+ column_id = IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN; |
+ break; |
+ case V8_MEMORY_USED: |
+ case V8_MEMORY: |
+ column_id = IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN; |
+ break; |
+ } |
+ model_->ToggleColumnVisibility(column_id); |
+ } |
+ |
+ int64_t GetColumnValue(ColumnSpecifier column, int row) override { |
+ task_management::TaskId task_id = model_->tasks_[row]; |
+ int64_t value = 0; |
+ int64_t ignored = 0; |
+ bool success = false; |
+ |
+ switch (column) { |
+ case COLUMN_NONE: |
+ break; |
+ case V8_MEMORY: |
+ success = task_manager()->GetV8Memory(task_id, &value, &ignored); |
+ break; |
+ case V8_MEMORY_USED: |
+ success = task_manager()->GetV8Memory(task_id, &ignored, &value); |
+ break; |
+ case SQLITE_MEMORY_USED: |
+ value = task_manager()->GetSqliteMemoryUsed(task_id); |
+ success = true; |
+ break; |
+ } |
+ if (!success) |
+ return 0; |
+ return value; |
+ } |
+ |
+ int32_t GetTabId(int row) override { |
+ task_management::TaskId task_id = model_->tasks_[row]; |
+ return task_manager()->GetTabId(task_id); |
+ } |
+ |
+ void Kill(int row) override { model_->KillTask(row); } |
+ |
+ private: |
+ task_management::TaskManagerInterface* task_manager() { |
+ return model_->observed_task_manager(); |
+ } |
+ |
+ // Returns the TaskManagerTableModel for the the visible NewTaskManagerView. |
+ static task_management::TaskManagerTableModel* GetRealModel() { |
+ CHECK(IsNewTaskManagerViewEnabled()); |
+ // This downcast is safe, as long as the new task manager is enabled. |
+ task_management::TaskManagerTableModel* result = |
+ static_cast<task_management::TaskManagerTableModel*>( |
+ chrome::ShowTaskManager(nullptr)); |
+ return result; |
+ } |
+ |
+ task_management::TaskManagerTableModel* model_; |
+ std::unique_ptr<ScopedInterceptTableModelObserver> interceptor_; |
+}; |
+ |
+namespace { |
+ |
+class LegacyTaskManagerTesterImpl : public TaskManagerTester, |
+ public TaskManagerModelObserver { |
+ public: |
+ explicit LegacyTaskManagerTesterImpl(const base::Closure& on_resource_change) |
+ : on_resource_change_(on_resource_change), |
+ model_(TaskManager::GetInstance()->model()) { |
+ if (!on_resource_change_.is_null()) |
+ model_->AddObserver(this); |
+ } |
+ ~LegacyTaskManagerTesterImpl() override { |
+ if (!on_resource_change_.is_null()) |
+ model_->RemoveObserver(this); |
+ } |
+ |
+ // TaskManagerTester: |
+ int GetRowCount() override { return model_->ResourceCount(); } |
+ |
+ base::string16 GetRowTitle(int row) override { |
+ return model_->GetResourceTitle(row); |
+ } |
+ |
+ int64_t GetColumnValue(ColumnSpecifier column, int row) override { |
+ size_t value = 0; |
+ bool success = false; |
+ switch (column) { |
+ case COLUMN_NONE: |
+ break; |
+ case V8_MEMORY: |
+ success = model_->GetV8Memory(row, &value); |
+ break; |
+ case V8_MEMORY_USED: |
+ success = model_->GetV8MemoryUsed(row, &value); |
+ break; |
+ case SQLITE_MEMORY_USED: |
+ success = model_->GetSqliteMemoryUsedBytes(row, &value); |
+ break; |
+ } |
+ if (!success) |
+ return 0; |
+ return static_cast<int64_t>(value); |
+ } |
+ |
+ void ToggleColumnVisibility(ColumnSpecifier column) override { |
+ // Doing nothing is okay here; the legacy TaskManager always collects all |
+ // stats. |
+ } |
+ |
+ int32_t GetTabId(int row) override { |
+ if (model_->GetResourceWebContents(row)) { |
+ return SessionTabHelper::IdForTab(model_->GetResourceWebContents(row)); |
+ } |
+ return -1; |
+ } |
+ void Kill(int row) override { TaskManager::GetInstance()->KillProcess(row); } |
+ |
+ // TaskManagerModelObserver: |
+ void OnModelChanged() override { OnResourceChange(); } |
+ void OnItemsChanged(int start, int length) override { OnResourceChange(); } |
+ void OnItemsAdded(int start, int length) override { OnResourceChange(); } |
void OnItemsRemoved(int start, int length) override { OnResourceChange(); } |
+ private: |
+ void OnResourceChange() { |
+ if (!on_resource_change_.is_null()) |
+ on_resource_change_.Run(); |
+ } |
+ base::Closure on_resource_change_; |
+ TaskManagerModel* model_; |
+}; |
+ |
+// Helper class to run a message loop until a TaskManagerTester is in an |
+// expected state. If timeout occurs, an ASCII version of the task manager's |
+// contents, along with a summary of the expected state, are dumped to test |
+// output, to assist debugging. |
+class ResourceChangeObserver { |
+ public: |
+ ResourceChangeObserver(int required_count, |
+ const base::string16& title_pattern, |
+ ColumnSpecifier column_specifier, |
+ size_t min_column_value) |
+ : required_count_(required_count), |
+ title_pattern_(title_pattern), |
+ column_specifier_(column_specifier), |
+ min_column_value_(min_column_value) { |
+ base::Closure callback = base::Bind( |
+ &ResourceChangeObserver::OnResourceChange, base::Unretained(this)); |
+ |
+ if (IsNewTaskManagerViewEnabled()) |
+ task_manager_tester_.reset(new TaskManagerTesterImpl(callback)); |
+ else |
+ task_manager_tester_.reset(new LegacyTaskManagerTesterImpl(callback)); |
+ } |
+ |
void RunUntilSatisfied() { |
// See if the condition is satisfied without having to run the loop. This |
// check has to be placed after the installation of the |
@@ -58,9 +287,7 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
if (IsSatisfied()) |
return; |
- timer_.Start(FROM_HERE, |
- TestTimeouts::action_timeout(), |
- this, |
+ timer_.Start(FROM_HERE, TestTimeouts::action_timeout(), this, |
&ResourceChangeObserver::OnTimeout); |
run_loop_.Run(); |
@@ -91,8 +318,9 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
int CountMatches() { |
int match_count = 0; |
- for (int i = 0; i < model_->ResourceCount(); i++) { |
- if (!base::MatchPattern(model_->GetResourceTitle(i), title_pattern_)) |
+ for (int i = 0; i < task_manager_tester_->GetRowCount(); i++) { |
+ if (!base::MatchPattern(task_manager_tester_->GetRowTitle(i), |
+ title_pattern_)) |
continue; |
if (GetColumnValue(i) < min_column_value_) |
@@ -103,25 +331,8 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
return match_count; |
} |
- size_t GetColumnValue(int index) { |
- size_t value = 0; |
- bool success = false; |
- switch (column_specifier_) { |
- case COLUMN_NONE: |
- break; |
- case V8_MEMORY: |
- success = model_->GetV8Memory(index, &value); |
- break; |
- case V8_MEMORY_USED: |
- success = model_->GetV8MemoryUsed(index, &value); |
- break; |
- case SQLITE_MEMORY_USED: |
- success = model_->GetSqliteMemoryUsedBytes(index, &value); |
- break; |
- } |
- if (!success) |
- return 0; |
- return value; |
+ int64_t GetColumnValue(int index) { |
+ return task_manager_tester_->GetColumnValue(column_specifier_, index); |
} |
const char* GetColumnName() { |
@@ -156,10 +367,10 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
task_manager_state_dump << "\nCurrently there are " << CountMatches() |
<< " matches."; |
task_manager_state_dump << "\nCurrent Task Manager Model is:"; |
- for (int i = 0; i < model_->ResourceCount(); i++) { |
+ for (int i = 0; i < task_manager_tester_->GetRowCount(); i++) { |
task_manager_state_dump |
<< "\n > " << std::setw(40) << std::left |
- << base::UTF16ToASCII(model_->GetResourceTitle(i)); |
+ << base::UTF16ToASCII(task_manager_tester_->GetRowTitle(i)); |
if (min_column_value_ > 0) { |
task_manager_state_dump << " [" << GetColumnName() |
<< " == " << GetColumnValue(i) << "]"; |
@@ -168,45 +379,39 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
return task_manager_state_dump; |
} |
- const TaskManagerModel* model_; |
+ std::unique_ptr<TaskManagerTester> task_manager_tester_; |
const int required_count_; |
const base::string16 title_pattern_; |
const ColumnSpecifier column_specifier_; |
- const size_t min_column_value_; |
+ const int64_t min_column_value_; |
base::RunLoop run_loop_; |
base::OneShotTimer timer_; |
}; |
} // namespace |
-void EnableOldTaskManager() { |
- base::CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kDisableNewTaskManager); |
+std::unique_ptr<TaskManagerTester> GetTaskManagerTester() { |
+ if (IsNewTaskManagerViewEnabled()) |
+ return base::WrapUnique(new TaskManagerTesterImpl(base::Closure())); |
+ else |
+ return base::WrapUnique(new LegacyTaskManagerTesterImpl(base::Closure())); |
} |
void WaitForTaskManagerRows(int required_count, |
const base::string16& title_pattern) { |
- TaskManagerModel* model = TaskManager::GetInstance()->model(); |
- |
const int column_value_dont_care = 0; |
- ResourceChangeObserver observer(model, required_count, title_pattern, |
- COLUMN_NONE, column_value_dont_care); |
- model->AddObserver(&observer); |
+ ResourceChangeObserver observer(required_count, title_pattern, COLUMN_NONE, |
+ column_value_dont_care); |
observer.RunUntilSatisfied(); |
- model->RemoveObserver(&observer); |
} |
void WaitForTaskManagerStatToExceed(const base::string16& title_pattern, |
ColumnSpecifier column_getter, |
size_t min_column_value) { |
- TaskManagerModel* model = TaskManager::GetInstance()->model(); |
- |
const int wait_for_one_match = 1; |
- ResourceChangeObserver observer(model, wait_for_one_match, title_pattern, |
+ ResourceChangeObserver observer(wait_for_one_match, title_pattern, |
column_getter, min_column_value); |
- model->AddObserver(&observer); |
observer.RunUntilSatisfied(); |
- model->RemoveObserver(&observer); |
} |
base::string16 MatchTab(const char* title) { |
@@ -214,45 +419,58 @@ base::string16 MatchTab(const char* title) { |
base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyTab() { return MatchTab("*"); } |
+base::string16 MatchAnyTab() { |
+ return MatchTab("*"); |
+} |
-base::string16 MatchAboutBlankTab() { return MatchTab("about:blank"); } |
+base::string16 MatchAboutBlankTab() { |
+ return MatchTab("about:blank"); |
+} |
base::string16 MatchExtension(const char* title) { |
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX, |
base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyExtension() { return MatchExtension("*"); } |
+base::string16 MatchAnyExtension() { |
+ return MatchExtension("*"); |
+} |
base::string16 MatchApp(const char* title) { |
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX, |
base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyApp() { return MatchApp("*"); } |
+base::string16 MatchAnyApp() { |
+ return MatchApp("*"); |
+} |
base::string16 MatchWebView(const char* title) { |
return l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX, |
- base::ASCIIToUTF16(title)); |
+ IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX, base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyWebView() { return MatchWebView("*"); } |
+base::string16 MatchAnyWebView() { |
+ return MatchWebView("*"); |
+} |
base::string16 MatchBackground(const char* title) { |
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, |
base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyBackground() { return MatchBackground("*"); } |
+base::string16 MatchAnyBackground() { |
+ return MatchBackground("*"); |
+} |
base::string16 MatchPrint(const char* title) { |
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX, |
base::ASCIIToUTF16(title)); |
} |
-base::string16 MatchAnyPrint() { return MatchPrint("*"); } |
+base::string16 MatchAnyPrint() { |
+ return MatchPrint("*"); |
+} |
base::string16 MatchSubframe(const char* title) { |
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_SUBFRAME_PREFIX, |