1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/task_manager/task_manager.h"
6
7#include "base/files/file_path.h"
8#include "base/strings/stringprintf.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/chrome_notification_types.h"
11#include "chrome/browser/devtools/devtools_window_testing.h"
12#include "chrome/browser/extensions/extension_browsertest.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/infobars/infobar_service.h"
15#include "chrome/browser/notifications/desktop_notification_service.h"
16#include "chrome/browser/notifications/notification.h"
17#include "chrome/browser/notifications/notification_test_util.h"
18#include "chrome/browser/notifications/notification_ui_manager.h"
19#include "chrome/browser/profiles/profile.h"
20#include "chrome/browser/task_manager/resource_provider.h"
21#include "chrome/browser/task_manager/task_manager_browsertest_util.h"
22#include "chrome/browser/ui/browser.h"
23#include "chrome/browser/ui/browser_commands.h"
24#include "chrome/browser/ui/browser_dialogs.h"
25#include "chrome/browser/ui/browser_navigator.h"
26#include "chrome/browser/ui/browser_window.h"
27#include "chrome/browser/ui/panels/panel.h"
28#include "chrome/browser/ui/panels/panel_manager.h"
29#include "chrome/browser/ui/tabs/tab_strip_model.h"
30#include "chrome/browser/web_applications/web_app.h"
31#include "chrome/common/chrome_switches.h"
32#include "chrome/grit/generated_resources.h"
33#include "chrome/test/base/in_process_browser_test.h"
34#include "chrome/test/base/ui_test_utils.h"
35#include "components/infobars/core/confirm_infobar_delegate.h"
36#include "components/infobars/core/infobar.h"
37#include "content/public/browser/notification_service.h"
38#include "content/public/common/content_switches.h"
39#include "content/public/test/browser_test_utils.h"
40#include "extensions/browser/extension_system.h"
41#include "extensions/common/extension.h"
42#include "net/dns/mock_host_resolver.h"
43#include "net/test/embedded_test_server/embedded_test_server.h"
44#include "testing/gtest/include/gtest/gtest.h"
45#include "ui/base/l10n/l10n_util.h"
46#include "ui/base/page_transition_types.h"
47
48using content::WebContents;
49using task_manager::browsertest_util::MatchAboutBlankTab;
50using task_manager::browsertest_util::MatchAnyApp;
51using task_manager::browsertest_util::MatchAnyExtension;
52using task_manager::browsertest_util::MatchAnyTab;
53using task_manager::browsertest_util::MatchApp;
54using task_manager::browsertest_util::MatchExtension;
55using task_manager::browsertest_util::MatchTab;
56using task_manager::browsertest_util::WaitForTaskManagerRows;
57
58namespace {
59
60const base::FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
61
62}  // namespace
63
64class TaskManagerBrowserTest : public ExtensionBrowserTest {
65 public:
66  TaskManagerBrowserTest() {}
67  virtual ~TaskManagerBrowserTest() {}
68
69  TaskManagerModel* model() const {
70    return TaskManager::GetInstance()->model();
71  }
72
73  void ShowTaskManager() {
74    EXPECT_EQ(0, model()->ResourceCount());
75
76    // Show the task manager. This populates the model, and helps with debugging
77    // (you see the task manager).
78    chrome::ShowTaskManager(browser());
79  }
80
81  void Refresh() {
82    model()->Refresh();
83  }
84
85  int GetUpdateTimeMs() {
86    return TaskManagerModel::kUpdateTimeMs;
87  }
88
89  GURL GetTestURL() {
90    return ui_test_utils::GetTestUrl(
91        base::FilePath(base::FilePath::kCurrentDirectory),
92        base::FilePath(kTitle1File));
93  }
94
95  int FindResourceIndex(const base::string16& title) {
96    for (int i = 0; i < model()->ResourceCount(); ++i) {
97      if (title == model()->GetResourceTitle(i))
98        return i;
99    }
100    return -1;
101  }
102
103 protected:
104  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
105    ExtensionBrowserTest::SetUpCommandLine(command_line);
106
107    // Do not launch device discovery process.
108    command_line->AppendSwitch(switches::kDisableDeviceDiscoveryNotifications);
109  }
110
111 private:
112  DISALLOW_COPY_AND_ASSIGN(TaskManagerBrowserTest);
113};
114
115#if defined(OS_MACOSX) || defined(OS_LINUX)
116#define MAYBE_ShutdownWhileOpen DISABLED_ShutdownWhileOpen
117#else
118#define MAYBE_ShutdownWhileOpen ShutdownWhileOpen
119#endif
120
121// Regression test for http://crbug.com/13361
122IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_ShutdownWhileOpen) {
123  ShowTaskManager();
124}
125
126IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeTabContentsChanges) {
127  ShowTaskManager();
128  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
129  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
130  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchTab("title1.html")));
131
132  // Open a new tab and make sure the task manager notices it.
133  AddTabAtIndex(0, GetTestURL(), ui::PAGE_TRANSITION_TYPED);
134
135  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html")));
136  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
137
138  // Close the tab and verify that we notice.
139  browser()->tab_strip_model()->CloseWebContentsAt(0,
140                                                   TabStripModel::CLOSE_NONE);
141  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchTab("title1.html")));
142  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
143}
144
145IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillTab) {
146  ShowTaskManager();
147  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
148  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
149  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchTab("title1.html")));
150
151  // Open a new tab and make sure the task manager notices it.
152  AddTabAtIndex(0, GetTestURL(), ui::PAGE_TRANSITION_TYPED);
153
154  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html")));
155  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
156
157  // Killing the tab via task manager should remove the row.
158  int tab = FindResourceIndex(MatchTab("title1.html"));
159  ASSERT_NE(-1, tab);
160  ASSERT_TRUE(model()->GetResourceWebContents(tab) != NULL);
161  ASSERT_TRUE(model()->CanActivate(tab));
162  TaskManager::GetInstance()->KillProcess(tab);
163  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchTab("title1.html")));
164  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
165
166  // Tab should reappear in task manager upon reload.
167  chrome::Reload(browser(), CURRENT_TAB);
168  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html")));
169  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
170}
171
172IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticePanel) {
173  ASSERT_TRUE(LoadExtension(
174      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
175                    .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
176                    .AppendASCII("1.0.0.0")));
177
178  // Open a new panel to an extension url.
179  GURL url(
180    "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/french_sentence.html");
181  Panel* panel = PanelManager::GetInstance()->CreatePanel(
182      web_app::GenerateApplicationNameFromExtensionId(
183          last_loaded_extension_id()),
184      browser()->profile(),
185      url,
186      gfx::Rect(300, 400),
187      PanelManager::CREATE_AS_DOCKED);
188
189  // Make sure that a task manager model created after the panel shows the
190  // existence of the panel and the extension.
191  ShowTaskManager();
192  ASSERT_NO_FATAL_FAILURE(
193      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
194  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
195      1,
196      MatchExtension(
197          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
198          "french_sentence.html")));
199  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
200  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
201  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
202
203  // Close the panel and verify that we notice.
204  panel->Close();
205  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyExtension()));
206  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
207      0,
208      MatchExtension(
209          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
210          "french_sentence.html")));
211  ASSERT_NO_FATAL_FAILURE(
212      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
213}
214
215IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticePanelChanges) {
216  ShowTaskManager();
217  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
218  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
219
220  ASSERT_TRUE(LoadExtension(
221      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
222                    .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
223                    .AppendASCII("1.0.0.0")));
224
225  // Browser, the New Tab Page and Extension background page.
226  ASSERT_NO_FATAL_FAILURE(
227      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
228  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyExtension()));
229  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
230
231  // Open a new panel to an extension url and make sure we notice that.
232  GURL url(
233    "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/french_sentence.html");
234  Panel* panel = PanelManager::GetInstance()->CreatePanel(
235      web_app::GenerateApplicationNameFromExtensionId(
236          last_loaded_extension_id()),
237      browser()->profile(),
238      url,
239      gfx::Rect(300, 400),
240      PanelManager::CREATE_AS_DOCKED);
241  ASSERT_NO_FATAL_FAILURE(
242      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
243  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
244      1,
245      MatchExtension(
246          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
247          "french_sentence.html")));
248  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
249  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
250  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
251
252  // Close the panel and verify that we notice.
253  panel->Close();
254  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyExtension()));
255  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
256      0,
257      MatchExtension(
258          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
259          "french_sentence.html")));
260  ASSERT_NO_FATAL_FAILURE(
261      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
262
263  // Unload extension.
264  UnloadExtension(last_loaded_extension_id());
265  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
266  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
267}
268
269// Kills a process that has more than one task manager entry.
270IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillPanelViaExtensionResource) {
271  ShowTaskManager();
272  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("good")
273                                .AppendASCII("Extensions")
274                                .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
275                                .AppendASCII("1.0.0.0")));
276
277  // Open a new panel to an extension url.
278  GURL url(
279      "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
280      "french_sentence.html");
281  PanelManager::GetInstance()->CreatePanel(
282      web_app::GenerateApplicationNameFromExtensionId(
283          last_loaded_extension_id()),
284      browser()->profile(),
285      url,
286      gfx::Rect(300, 400),
287      PanelManager::CREATE_AS_DOCKED);
288
289  ASSERT_NO_FATAL_FAILURE(
290      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
291  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
292      1,
293      MatchExtension(
294          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
295          "french_sentence.html")));
296  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
297  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
298  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
299
300  // Kill the process via the BACKGROUND PAGE (not the panel). Verify that both
301  // the background page and the panel go away from the task manager.
302  int background_page = FindResourceIndex(MatchExtension("My extension 1"));
303  ASSERT_NE(-1, background_page);
304  ASSERT_TRUE(model()->GetResourceWebContents(background_page) == NULL);
305  ASSERT_FALSE(model()->CanActivate(background_page));
306  TaskManager::GetInstance()->KillProcess(background_page);
307  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
308  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
309}
310
311// Kills a process that has more than one task manager entry. This test is the
312// same as KillPanelViaExtensionResource except it does the kill via the other
313// entry.
314IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillPanelViaPanelResource) {
315  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("good")
316                                .AppendASCII("Extensions")
317                                .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
318                                .AppendASCII("1.0.0.0")));
319
320  // Open a new panel to an extension url.
321  GURL url(
322      "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
323      "french_sentence.html");
324  PanelManager::GetInstance()->CreatePanel(
325      web_app::GenerateApplicationNameFromExtensionId(
326          last_loaded_extension_id()),
327      browser()->profile(),
328      url,
329      gfx::Rect(300, 400),
330      PanelManager::CREATE_AS_DOCKED);
331
332  ShowTaskManager();
333  ASSERT_NO_FATAL_FAILURE(
334      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
335  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(
336      1,
337      MatchExtension(
338          "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
339          "french_sentence.html")));
340  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
341  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
342  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
343
344  int background_page = FindResourceIndex(MatchExtension("My extension 1"));
345  ASSERT_NE(-1, background_page);
346  ASSERT_TRUE(model()->GetResourceWebContents(background_page) == NULL);
347  ASSERT_FALSE(model()->CanActivate(background_page));
348
349  // Kill the process via the PANEL RESOURCE (not the background page). Verify
350  // that both the background page and the panel go away from the task manager.
351  int panel = FindResourceIndex(MatchExtension(
352      "chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/"
353      "french_sentence.html"));
354  ASSERT_NE(-1, panel);
355  ASSERT_TRUE(model()->GetResourceWebContents(panel) != NULL);
356  ASSERT_TRUE(model()->CanActivate(panel));
357  TaskManager::GetInstance()->KillProcess(panel);
358  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
359  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
360}
361
362IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionTabChanges) {
363  ShowTaskManager();
364  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
365  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
366
367  ASSERT_TRUE(LoadExtension(
368      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
369                    .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
370                    .AppendASCII("1.0.0.0")));
371
372  // Browser, Extension background page, and the New Tab Page.
373  ASSERT_NO_FATAL_FAILURE(
374      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
375  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyExtension()));
376  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
377
378  // Open a new tab to an extension URL. Afterwards, the third entry (background
379  // page) should be an extension resource whose title starts with "Extension:".
380  // The fourth entry (page.html) is also of type extension and has both a
381  // WebContents and an extension. The title should start with "Extension:".
382  GURL url("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/page.html");
383  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
384  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchExtension("Foobar")));
385  ASSERT_NO_FATAL_FAILURE(
386      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
387  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
388  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
389  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
390
391  int extension_tab = FindResourceIndex(MatchExtension("Foobar"));
392  ASSERT_NE(-1, extension_tab);
393  ASSERT_TRUE(model()->GetResourceWebContents(extension_tab) != NULL);
394  ASSERT_TRUE(model()->CanActivate(extension_tab));
395
396  int background_page = FindResourceIndex(MatchExtension("My extension 1"));
397  ASSERT_NE(-1, background_page);
398  ASSERT_TRUE(model()->GetResourceWebContents(background_page) == NULL);
399  ASSERT_FALSE(model()->CanActivate(background_page));
400}
401
402IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionTab) {
403  // With the task manager closed, open a new tab to an extension URL.
404  // Afterwards, when we open the task manager, the third entry (background
405  // page) should be an extension resource whose title starts with "Extension:".
406  // The fourth entry (page.html) is also of type extension and has both a
407  // WebContents and an extension. The title should start with "Extension:".
408  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("good")
409                                .AppendASCII("Extensions")
410                                .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
411                                .AppendASCII("1.0.0.0")));
412  GURL url("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/page.html");
413  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
414
415  ShowTaskManager();
416  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchExtension("Foobar")));
417  ASSERT_NO_FATAL_FAILURE(
418      WaitForTaskManagerRows(1, MatchExtension("My extension 1")));
419  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyExtension()));
420  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
421  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
422
423  int extension_tab = FindResourceIndex(MatchExtension("Foobar"));
424  ASSERT_NE(-1, extension_tab);
425  ASSERT_TRUE(model()->GetResourceWebContents(extension_tab) != NULL);
426  ASSERT_TRUE(model()->CanActivate(extension_tab));
427
428  int background_page = FindResourceIndex(MatchExtension("My extension 1"));
429  ASSERT_NE(-1, background_page);
430  ASSERT_TRUE(model()->GetResourceWebContents(background_page) == NULL);
431  ASSERT_FALSE(model()->CanActivate(background_page));
432}
433
434IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeAppTabChanges) {
435  ShowTaskManager();
436
437  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("packaged_app")));
438  ExtensionService* service = extensions::ExtensionSystem::Get(
439                                  browser()->profile())->extension_service();
440  const extensions::Extension* extension =
441      service->GetExtensionById(last_loaded_extension_id(), false);
442
443  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
444  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
445  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
446  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp()));
447
448  // Open a new tab to the app's launch URL and make sure we notice that.
449  GURL url(extension->GetResourceURL("main.html"));
450  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
451
452  // There should be 1 "App: " tab and the original new tab page.
453  ASSERT_NO_FATAL_FAILURE(
454      WaitForTaskManagerRows(1, MatchApp("Packaged App Test")));
455  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyApp()));
456  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
457  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
458  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
459
460  // Check that the third entry (main.html) is of type extension and has both
461  // a tab contents and an extension.
462  int app_tab = FindResourceIndex(MatchApp("Packaged App Test"));
463  ASSERT_NE(-1, app_tab);
464  ASSERT_TRUE(model()->GetResourceWebContents(app_tab) != NULL);
465  ASSERT_TRUE(model()->CanActivate(app_tab));
466  ASSERT_EQ(task_manager::Resource::EXTENSION,
467            model()->GetResourceType(app_tab));
468  ASSERT_EQ(2, browser()->tab_strip_model()->count());
469
470  // Unload extension to make sure the tab goes away.
471  UnloadExtension(last_loaded_extension_id());
472
473  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
474  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp()));
475  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
476  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
477  ASSERT_EQ(1, browser()->tab_strip_model()->count());
478}
479
480IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeAppTab) {
481  ASSERT_TRUE(LoadExtension(
482      test_data_dir_.AppendASCII("packaged_app")));
483  ExtensionService* service = extensions::ExtensionSystem::Get(
484      browser()->profile())->extension_service();
485  const extensions::Extension* extension =
486      service->GetExtensionById(last_loaded_extension_id(), false);
487
488  // Open a new tab to the app's launch URL and make sure we notice that.
489  GURL url(extension->GetResourceURL("main.html"));
490  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
491
492  ShowTaskManager();
493
494  ASSERT_NO_FATAL_FAILURE(
495      WaitForTaskManagerRows(1, MatchApp("Packaged App Test")));
496  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
497  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
498  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyApp()));
499
500  // Check that the third entry (main.html) is of type extension and has both
501  // a tab contents and an extension.
502  int app_tab = FindResourceIndex(MatchApp("Packaged App Test"));
503  ASSERT_NE(-1, app_tab);
504  ASSERT_TRUE(model()->GetResourceWebContents(app_tab) != NULL);
505  ASSERT_TRUE(model()->CanActivate(app_tab));
506  ASSERT_EQ(task_manager::Resource::EXTENSION,
507            model()->GetResourceType(app_tab));
508}
509
510IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeHostedAppTabChanges) {
511  ShowTaskManager();
512
513  // The app under test acts on URLs whose host is "localhost",
514  // so the URLs we navigate to must have host "localhost".
515  host_resolver()->AddRule("*", "127.0.0.1");
516  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
517  GURL::Replacements replace_host;
518  std::string host_str("localhost");  // must stay in scope with replace_host
519  replace_host.SetHostStr(host_str);
520  GURL base_url = embedded_test_server()->GetURL(
521      "/extensions/api_test/app_process/");
522  base_url = base_url.ReplaceComponents(replace_host);
523
524  // Open a new tab to an app URL before the app is loaded.
525  GURL url(base_url.Resolve("path1/empty.html"));
526  content::WindowedNotificationObserver observer(
527      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
528      content::NotificationService::AllSources());
529  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
530  observer.Wait();
531
532  // Check that the new entry's title starts with "Tab:".
533  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
534
535  // Load the hosted app and make sure it still starts with "Tab:",
536  // since it hasn't changed to an app process yet.
537  ASSERT_TRUE(LoadExtension(
538      test_data_dir_.AppendASCII("api_test").AppendASCII("app_process")));
539  // Force the TaskManager to query the title.
540  Refresh();
541  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
542  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
543  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("Unmodified")));
544  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
545
546  // Now reload and check that the last entry's title now starts with "App:".
547  ui_test_utils::NavigateToURL(browser(), url);
548
549  // Force the TaskManager to query the title.
550  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
551  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
552  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyApp()));
553  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchApp("Unmodified")));
554  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
555
556  // Disable extension.
557  DisableExtension(last_loaded_extension_id());
558
559  // The hosted app should now show up as a normal "Tab: ".
560  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
561  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
562  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("Unmodified")));
563  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
564  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp()));
565
566  // Reload the page.
567  ui_test_utils::NavigateToURL(browser(), url);
568
569  // No change expected.
570  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
571  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab()));
572  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("Unmodified")));
573  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
574  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp()));
575}
576
577IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeHostedAppTabAfterReload) {
578  // The app under test acts on URLs whose host is "localhost",
579  // so the URLs we navigate to must have host "localhost".
580  host_resolver()->AddRule("*", "127.0.0.1");
581  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
582  GURL::Replacements replace_host;
583  std::string host_str("localhost");  // must stay in scope with replace_host
584  replace_host.SetHostStr(host_str);
585  GURL base_url =
586      embedded_test_server()->GetURL("/extensions/api_test/app_process/");
587  base_url = base_url.ReplaceComponents(replace_host);
588
589  // Open a new tab to an app URL before the app is loaded.
590  GURL url(base_url.Resolve("path1/empty.html"));
591  content::WindowedNotificationObserver observer(
592      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
593      content::NotificationService::AllSources());
594  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
595  observer.Wait();
596
597  // Load the hosted app and make sure it still starts with "Tab:",
598  // since it hasn't changed to an app process yet.
599  ASSERT_TRUE(LoadExtension(
600      test_data_dir_.AppendASCII("api_test").AppendASCII("app_process")));
601
602  // Now reload, which should transition this tab to being an App.
603  ui_test_utils::NavigateToURL(browser(), url);
604
605  ShowTaskManager();
606
607  // The TaskManager should show this as an "App: "
608  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
609  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyApp()));
610  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
611}
612
613IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeHostedAppTabBeforeReload) {
614  // The app under test acts on URLs whose host is "localhost",
615  // so the URLs we navigate to must have host "localhost".
616  host_resolver()->AddRule("*", "127.0.0.1");
617  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
618  GURL::Replacements replace_host;
619  std::string host_str("localhost");  // must stay in scope with replace_host
620  replace_host.SetHostStr(host_str);
621  GURL base_url =
622      embedded_test_server()->GetURL("/extensions/api_test/app_process/");
623  base_url = base_url.ReplaceComponents(replace_host);
624
625  // Open a new tab to an app URL before the app is loaded.
626  GURL url(base_url.Resolve("path1/empty.html"));
627  content::WindowedNotificationObserver observer(
628      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
629      content::NotificationService::AllSources());
630  AddTabAtIndex(0, url, ui::PAGE_TRANSITION_TYPED);
631  observer.Wait();
632
633  // Load the hosted app and make sure it still starts with "Tab:",
634  // since it hasn't changed to an app process yet.
635  ASSERT_TRUE(LoadExtension(
636      test_data_dir_.AppendASCII("api_test").AppendASCII("app_process")));
637
638  ShowTaskManager();
639
640  // The TaskManager should show this as a "Tab: " because the page hasn't been
641  // reloaded since the hosted app was installed.
642  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
643  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp()));
644  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension()));
645}
646
647// Regression test for http://crbug.com/18693.
648IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ReloadExtension) {
649  ShowTaskManager();
650  ASSERT_TRUE(LoadExtension(
651      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
652
653  // Wait until we see the loaded extension in the task manager (the three
654  // resources are: the browser process, New Tab Page, and the extension).
655  ASSERT_NO_FATAL_FAILURE(
656      WaitForTaskManagerRows(1, MatchExtension("background_page")));
657
658  // Reload the extension a few times and make sure our resource count doesn't
659  // increase.
660  std::string extension_id = last_loaded_extension_id();
661  for (int i = 1; i <= 5; i++) {
662    SCOPED_TRACE(testing::Message() << "Reloading extension for the " << i
663                                    << "th time.");
664    ReloadExtension(extension_id);
665    ASSERT_NO_FATAL_FAILURE(
666        WaitForTaskManagerRows(1, MatchExtension("background_page")));
667  }
668}
669
670// Crashy, http://crbug.com/42301.
671IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
672                       DISABLED_PopulateWebCacheFields) {
673  ShowTaskManager();
674  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
675
676  int resource_count = TaskManager::GetInstance()->model()->ResourceCount();
677
678  // Open a new tab and make sure we notice that.
679  AddTabAtIndex(0, GetTestURL(), ui::PAGE_TRANSITION_TYPED);
680  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
681
682  // Check that we get some value for the cache columns.
683  DCHECK_NE(model()->GetResourceWebCoreImageCacheSize(resource_count),
684            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
685  DCHECK_NE(model()->GetResourceWebCoreScriptsCacheSize(resource_count),
686            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
687  DCHECK_NE(model()->GetResourceWebCoreCSSCacheSize(resource_count),
688            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
689}
690
691// Checks that task manager counts a worker thread JS heap size.
692// http://crbug.com/241066
693// Flaky, http://crbug.com/259368
694IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DISABLED_WebWorkerJSHeapMemory) {
695  ui_test_utils::NavigateToURL(browser(), GetTestURL());
696  const int extra_timeout_ms = 500;
697  size_t minimal_heap_size = 2 * 1024 * 1024 * sizeof(void*);
698  std::string test_js = base::StringPrintf(
699      "var blob = new Blob([\n"
700      "    'mem = new Array(%lu);',\n"
701      "    'for (var i = 0; i < mem.length; i += 16) mem[i] = i;',\n"
702      "    'postMessage();']);\n"
703      "blobURL = window.URL.createObjectURL(blob);\n"
704      "worker = new Worker(blobURL);\n"
705      "// Give the task manager few seconds to poll for JS heap sizes.\n"
706      "worker.onmessage = setTimeout.bind(\n"
707      "    this,\n"
708      "    function () { window.domAutomationController.send(true); },\n"
709      "    %d);\n"
710      "worker.postMessage();\n",
711      static_cast<unsigned long>(minimal_heap_size),
712      GetUpdateTimeMs() + extra_timeout_ms);
713  bool ok;
714  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
715      browser()->tab_strip_model()->GetActiveWebContents(), test_js, &ok));
716  ASSERT_TRUE(ok);
717
718  int resource_index = TaskManager::GetInstance()->model()->ResourceCount() - 1;
719  size_t result;
720
721  ASSERT_TRUE(model()->GetV8Memory(resource_index, &result));
722  LOG(INFO) << "Got V8 Heap Size " << result << " bytes";
723  EXPECT_GE(result, minimal_heap_size);
724
725  ASSERT_TRUE(model()->GetV8MemoryUsed(resource_index, &result));
726  LOG(INFO) << "Got V8 Used Heap Size " << result << " bytes";
727  EXPECT_GE(result, minimal_heap_size);
728}
729
730IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DevToolsNewDockedWindow) {
731  ShowTaskManager();  // Task manager shown BEFORE dev tools window.
732
733  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
734  DevToolsWindow* devtools =
735      DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), true);
736  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
737  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
738  DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
739}
740
741IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DevToolsNewUndockedWindow) {
742  ShowTaskManager();  // Task manager shown BEFORE dev tools window.
743  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab()));
744  DevToolsWindow* devtools =
745      DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), false);
746  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(3, MatchAnyTab()));
747  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(3, MatchAnyTab()));
748  DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
749}
750
751IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DevToolsOldDockedWindow) {
752  DevToolsWindow* devtools =
753      DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), true);
754  ShowTaskManager();  // Task manager shown AFTER dev tools window.
755  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
756  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(2, MatchAnyTab()));
757  DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
758}
759
760IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DevToolsOldUnockedWindow) {
761  DevToolsWindow* devtools =
762      DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), false);
763  ShowTaskManager();  // Task manager shown AFTER dev tools window.
764  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(3, MatchAnyTab()));
765  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(3, MatchAnyTab()));
766  DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
767}
768