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..fe809b20a65188bc4dba0cd09264f713f45f8f0c 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,265 @@ |
#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/task_manager/task_manager_table_model.h" |
afakhry
2016/04/28 00:03:13
I don't see you changed any DEPS. Does that mean y
ncarter (slow)
2016/05/02 18:33:28
It's ui/views (to get the view) that had the deps
afakhry
2016/05/02 18:58:17
Oh cool. Glad I moved there earlier! :)
|
#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" |
+ |
+// TODO(nick): Move everything here (except for LegacyTaskManagerTesterImpl) |
+// into the task_management namespace. |
+namespace task_management { |
+ |
+// Temporarily intercepts the calls between a TableModel and its Observer, |
+// running |callback| whenever anything happens. |
+class ScopedInterceptTableModelObserver : public ui::TableModelObserver { |
+ public: |
+ ScopedInterceptTableModelObserver( |
+ ui::TableModel* model, |
afakhry
2016/04/28 00:03:13
The naming of the variables can be confusing. Woul
ncarter (slow)
2016/05/02 18:33:28
Done.
|
+ ui::TableModelObserver* real_table_model_observer, |
+ const base::Closure& callback) |
+ : model_(model), |
+ real_table_model_observer_(real_table_model_observer), |
+ callback_(callback) { |
+ model_->SetObserver(this); |
+ } |
+ |
+ ~ScopedInterceptTableModelObserver() override { |
+ model_->SetObserver(real_table_model_observer_); |
+ } |
+ |
+ // 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(); |
+ } |
+ |
+ private: |
+ ui::TableModel* model_; |
+ ui::TableModelObserver* real_table_model_observer_; |
+ base::Closure callback_; |
+}; |
+ |
+class TaskManagerTesterImpl |
+ : public task_manager::browsertest_util::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( |
+ task_manager::browsertest_util::ColumnSpecifier column) override { |
+ int column_id = 0; |
+ switch (column) { |
+ case task_manager::browsertest_util::COLUMN_NONE: |
+ return; |
+ case task_manager::browsertest_util::SQLITE_MEMORY_USED: |
+ column_id = IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN; |
+ break; |
+ case task_manager::browsertest_util::V8_MEMORY_USED: |
+ case task_manager::browsertest_util::V8_MEMORY: |
+ column_id = IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN; |
+ break; |
+ } |
+ model_->ToggleColumnVisibility(column_id); |
+ } |
+ |
+ int64_t GetColumnValue(task_manager::browsertest_util::ColumnSpecifier column, |
+ int row) override { |
+ TaskId task_id = model_->tasks_[row]; |
+ int64_t value = 0; |
+ int64_t ignored = 0; |
+ bool success = false; |
+ |
+ switch (column) { |
+ case task_manager::browsertest_util::COLUMN_NONE: |
+ break; |
+ case task_manager::browsertest_util::V8_MEMORY: |
+ success = task_manager()->GetV8Memory(task_id, &value, &ignored); |
+ break; |
+ case task_manager::browsertest_util::V8_MEMORY_USED: |
+ success = task_manager()->GetV8Memory(task_id, &ignored, &value); |
+ break; |
+ case task_manager::browsertest_util::SQLITE_MEMORY_USED: |
+ value = task_manager()->GetSqliteMemoryUsed(task_id); |
+ success = true; |
+ break; |
+ } |
+ if (!success) |
+ return 0; |
+ return value; |
+ } |
+ |
+ int32_t GetTabId(int row) override { |
+ TaskId task_id = model_->tasks_[row]; |
+ return task_manager()->GetTabId(task_id); |
+ } |
+ |
+ void Kill(int row) override { model_->KillTask(row); } |
+ |
+ private: |
+ TaskManagerInterface* task_manager() { |
+ return model_->observed_task_manager(); |
+ } |
+ |
+ // Returns the TaskManagerTableModel for the the visible NewTaskManagerView. |
+ static TaskManagerTableModel* GetRealModel() { |
+ // TODO(nick): Solve the following ui/views layering/deps problem: |
+ // TaskManagerTableModel::GetInstanceForTesting() and its global variable |
+ // only exist so that we can call it here. That's kind of lame. If we were |
+ // allowed to #include ui/views here, we could befriend and call |
+ // NewTaskManagerView::GetInstanceForTesting() and get the model from that. |
+ TaskManagerTableModel* result = |
+ TaskManagerTableModel::GetInstanceForTesting(); |
+ CHECK(result) << "Task Manager must be visible to get the model."; |
+ return result; |
+ } |
+ |
+ TaskManagerTableModel* model_; |
+ std::unique_ptr<ScopedInterceptTableModelObserver> interceptor_; |
+}; |
+ |
+} // namespace task_management |
namespace task_manager { |
namespace browsertest_util { |
namespace { |
-class ResourceChangeObserver : public TaskManagerModelObserver { |
+class LegacyTaskManagerTesterImpl : public TaskManagerTester, |
+ public TaskManagerModelObserver { |
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) {} |
+ 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); |
+ } |
- void OnModelChanged() override { OnResourceChange(); } |
+ // TaskManagerTester: |
+ int GetRowCount() override { return model_->ResourceCount(); } |
- void OnItemsChanged(int start, int length) override { OnResourceChange(); } |
+ base::string16 GetRowTitle(int row) override { |
+ return model_->GetResourceTitle(row); |
+ } |
- void OnItemsAdded(int start, int length) override { OnResourceChange(); } |
+ 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 on_resource_change = base::Bind( |
+ &ResourceChangeObserver::OnResourceChange, base::Unretained(this)); |
+ |
+ if (switches::NewTaskManagerEnabled()) { |
+ model_.reset( |
afakhry
2016/04/28 00:03:13
There are too many things that are called |model_|
ncarter (slow)
2016/05/02 18:33:28
Done.
afakhry
2016/05/02 18:58:17
Mmmm, seems you missed that one?
ncarter (slow)
2016/05/02 23:09:57
Apparently I need to hit Ctrl+S before uploading.
|
+ new task_management::TaskManagerTesterImpl(on_resource_change)); |
+ } else { |
+ model_.reset(new LegacyTaskManagerTesterImpl(on_resource_change)); |
+ } |
+ } |
+ |
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 +285,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 +316,8 @@ 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 < model_->GetRowCount(); i++) { |
+ if (!base::MatchPattern(model_->GetRowTitle(i), title_pattern_)) |
continue; |
if (GetColumnValue(i) < min_column_value_) |
@@ -103,25 +328,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 model_->GetColumnValue(column_specifier_, index); |
} |
const char* GetColumnName() { |
@@ -156,10 +364,9 @@ 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++) { |
- task_manager_state_dump |
- << "\n > " << std::setw(40) << std::left |
- << base::UTF16ToASCII(model_->GetResourceTitle(i)); |
+ for (int i = 0; i < model_->GetRowCount(); i++) { |
+ task_manager_state_dump << "\n > " << std::setw(40) << std::left |
+ << base::UTF16ToASCII(model_->GetRowTitle(i)); |
if (min_column_value_ > 0) { |
task_manager_state_dump << " [" << GetColumnName() |
<< " == " << GetColumnValue(i) << "]"; |
@@ -168,45 +375,41 @@ class ResourceChangeObserver : public TaskManagerModelObserver { |
return task_manager_state_dump; |
} |
- const TaskManagerModel* model_; |
+ std::unique_ptr<TaskManagerTester> model_; |
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 (switches::NewTaskManagerEnabled()) { |
+ return base::WrapUnique( |
afakhry
2016/04/28 00:03:13
Are we not allowed to use std::make_unique()?
ncarter (slow)
2016/05/02 18:33:28
make_unique is not in C++11, it's C++14. Also, Wra
afakhry
2016/05/02 18:58:17
Yes, I know, but thanks for the explanation anyway
|
+ new task_management::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 +417,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, |