task_manager_browsertest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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/file_path.h"
8#include "base/utf_string_conversions.h"
9#include "chrome/browser/background_contents_service.h"
10#include "chrome/browser/browser_process.h"
11#include "chrome/browser/extensions/crashed_extension_infobar.h"
12#include "chrome/browser/extensions/extension_browsertest.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/notifications/desktop_notification_service.h"
15#include "chrome/browser/notifications/notification.h"
16#include "chrome/browser/notifications/notification_test_util.h"
17#include "chrome/browser/notifications/notification_ui_manager.h"
18#include "chrome/browser/profiles/profile.h"
19#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
20#include "chrome/browser/tabs/tab_strip_model.h"
21#include "chrome/browser/ui/browser.h"
22#include "chrome/browser/ui/browser_navigator.h"
23#include "chrome/browser/ui/browser_window.h"
24#include "chrome/common/extensions/extension.h"
25#include "chrome/common/page_transition_types.h"
26#include "chrome/test/in_process_browser_test.h"
27#include "chrome/test/ui_test_utils.h"
28#include "content/browser/tab_contents/tab_contents.h"
29#include "grit/generated_resources.h"
30#include "testing/gtest/include/gtest/gtest.h"
31#include "ui/base/l10n/l10n_util.h"
32
33namespace {
34
35const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
36
37class ResourceChangeObserver : public TaskManagerModelObserver {
38 public:
39  ResourceChangeObserver(const TaskManagerModel* model,
40                         int target_resource_count)
41      : model_(model),
42        target_resource_count_(target_resource_count) {
43  }
44
45  virtual void OnModelChanged() {
46    OnResourceChange();
47  }
48
49  virtual void OnItemsChanged(int start, int length) {
50    OnResourceChange();
51  }
52
53  virtual void OnItemsAdded(int start, int length) {
54    OnResourceChange();
55  }
56
57  virtual void OnItemsRemoved(int start, int length) {
58    OnResourceChange();
59  }
60
61 private:
62  void OnResourceChange() {
63    if (model_->ResourceCount() == target_resource_count_)
64      MessageLoopForUI::current()->Quit();
65  }
66
67  const TaskManagerModel* model_;
68  const int target_resource_count_;
69};
70
71// Helper class used to wait for a BackgroundContents to finish loading.
72class BackgroundContentsListener : public NotificationObserver {
73 public:
74  explicit BackgroundContentsListener(Profile* profile) {
75    registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
76                   Source<Profile>(profile));
77  }
78  virtual void Observe(NotificationType type,
79                       const NotificationSource& source,
80                       const NotificationDetails& details) {
81    // Quit once the BackgroundContents has been loaded.
82    if (type.value == NotificationType::BACKGROUND_CONTENTS_NAVIGATED)
83      MessageLoopForUI::current()->Quit();
84  }
85 private:
86  NotificationRegistrar registrar_;
87};
88
89}  // namespace
90
91class TaskManagerBrowserTest : public ExtensionBrowserTest {
92 public:
93  TaskManagerModel* model() const {
94    return TaskManager::GetInstance()->model();
95  }
96
97  void WaitForResourceChange(int target_count) {
98    if (model()->ResourceCount() == target_count)
99      return;
100    ResourceChangeObserver observer(model(), target_count);
101    model()->AddObserver(&observer);
102    ui_test_utils::RunMessageLoop();
103    model()->RemoveObserver(&observer);
104  }
105
106  // Wait for any pending BackgroundContents to finish starting up.
107  void WaitForBackgroundContents() {
108    BackgroundContentsListener listener(browser()->profile());
109    ui_test_utils::RunMessageLoop();
110  }
111};
112
113// Regression test for http://crbug.com/13361
114IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ShutdownWhileOpen) {
115  browser()->window()->ShowTaskManager();
116}
117
118IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeTabContentsChanges) {
119  EXPECT_EQ(0, model()->ResourceCount());
120
121  // Show the task manager. This populates the model, and helps with debugging
122  // (you see the task manager).
123  browser()->window()->ShowTaskManager();
124
125  // Browser and the New Tab Page.
126  WaitForResourceChange(2);
127
128  // Open a new tab and make sure we notice that.
129  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
130                                     FilePath(kTitle1File)));
131  AddTabAtIndex(0, url, PageTransition::TYPED);
132  WaitForResourceChange(3);
133
134  // Check that the third entry is a tab contents resource whose title starts
135  // starts with "Tab:".
136  ASSERT_TRUE(model()->GetResourceTabContents(2) != NULL);
137  string16 prefix = l10n_util::GetStringFUTF16(
138      IDS_TASK_MANAGER_TAB_PREFIX, string16());
139  ASSERT_TRUE(StartsWith(model()->GetResourceTitle(2), prefix, true));
140
141  // Close the tab and verify that we notice.
142  TabContents* first_tab = browser()->GetTabContentsAt(0);
143  ASSERT_TRUE(first_tab);
144  browser()->CloseTabContents(first_tab);
145  WaitForResourceChange(2);
146}
147
148IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeBGContentsChanges) {
149  EXPECT_EQ(0, model()->ResourceCount());
150
151  // Show the task manager. This populates the model, and helps with debugging
152  // (you see the task manager).
153  browser()->window()->ShowTaskManager();
154
155  // Browser and the New Tab Page.
156  WaitForResourceChange(2);
157
158  // Open a new background contents and make sure we notice that.
159  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
160                                     FilePath(kTitle1File)));
161
162  BackgroundContentsService* service =
163      browser()->profile()->GetBackgroundContentsService();
164  string16 application_id(ASCIIToUTF16("test_app_id"));
165  service->LoadBackgroundContents(browser()->profile(),
166                                  url,
167                                  ASCIIToUTF16("background_page"),
168                                  application_id);
169  WaitForResourceChange(3);
170
171  // Close the background contents and verify that we notice.
172  service->ShutdownAssociatedBackgroundContents(application_id);
173  WaitForResourceChange(2);
174}
175
176IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillBGContents) {
177  EXPECT_EQ(0, model()->ResourceCount());
178
179  // Show the task manager. This populates the model, and helps with debugging
180  // (you see the task manager).
181  browser()->window()->ShowTaskManager();
182
183  // Browser and the New Tab Page.
184  WaitForResourceChange(2);
185
186  // Open a new background contents and make sure we notice that.
187  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
188                                     FilePath(kTitle1File)));
189
190  BackgroundContentsService* service =
191      browser()->profile()->GetBackgroundContentsService();
192  string16 application_id(ASCIIToUTF16("test_app_id"));
193  service->LoadBackgroundContents(browser()->profile(),
194                                  url,
195                                  ASCIIToUTF16("background_page"),
196                                  application_id);
197  // Wait for the background contents process to finish loading.
198  WaitForBackgroundContents();
199  EXPECT_EQ(3, model()->ResourceCount());
200
201  // Kill the background contents process and verify that it disappears from the
202  // model.
203  bool found = false;
204  for (int i = 0; i < model()->ResourceCount(); ++i) {
205    if (model()->IsBackgroundResource(i)) {
206      TaskManager::GetInstance()->KillProcess(i);
207      found = true;
208      break;
209    }
210  }
211  ASSERT_TRUE(found);
212  WaitForResourceChange(2);
213}
214
215IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionChanges) {
216  EXPECT_EQ(0, model()->ResourceCount());
217
218  // Show the task manager. This populates the model, and helps with debugging
219  // (you see the task manager).
220  browser()->window()->ShowTaskManager();
221
222  // Browser and the New Tab Page.
223  WaitForResourceChange(2);
224
225  // Loading an extension with a background page should result in a new
226  // resource being created for it.
227  ASSERT_TRUE(LoadExtension(
228      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
229  WaitForResourceChange(3);
230
231  // Unload extension to avoid crash on Windows (see http://crbug.com/31663).
232  UnloadExtension(last_loaded_extension_id_);
233  WaitForResourceChange(2);
234}
235
236IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeExtensionTabs) {
237  // Show the task manager. This populates the model, and helps with debugging
238  // (you see the task manager).
239  browser()->window()->ShowTaskManager();
240
241  ASSERT_TRUE(LoadExtension(
242      test_data_dir_.AppendASCII("good").AppendASCII("Extensions")
243                    .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
244                    .AppendASCII("1.0.0.0")));
245
246  // Browser, Extension background page, and the New Tab Page.
247  WaitForResourceChange(3);
248
249  // Open a new tab to an extension URL and make sure we notice that.
250  GURL url("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/page.html");
251  AddTabAtIndex(0, url, PageTransition::TYPED);
252  WaitForResourceChange(4);
253
254  // Check that the third entry (background) is an extension resource whose
255  // title starts with "Extension:".
256  ASSERT_EQ(TaskManager::Resource::EXTENSION, model()->GetResourceType(2));
257  ASSERT_TRUE(model()->GetResourceTabContents(2) == NULL);
258  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);
259  string16 prefix = l10n_util::GetStringFUTF16(
260      IDS_TASK_MANAGER_EXTENSION_PREFIX, string16());
261  ASSERT_TRUE(StartsWith(model()->GetResourceTitle(2), prefix, true));
262
263  // Check that the fourth entry (page.html) is of type extension and has both
264  // a tab contents and an extension. The title should start with "Extension:".
265  ASSERT_EQ(TaskManager::Resource::EXTENSION, model()->GetResourceType(3));
266  ASSERT_TRUE(model()->GetResourceTabContents(3) != NULL);
267  ASSERT_TRUE(model()->GetResourceExtension(3) != NULL);
268  ASSERT_TRUE(StartsWith(model()->GetResourceTitle(3), prefix, true));
269
270  // Unload extension to avoid crash on Windows.
271  UnloadExtension(last_loaded_extension_id_);
272  WaitForResourceChange(2);
273}
274
275IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeAppTabs) {
276  // Show the task manager. This populates the model, and helps with debugging
277  // (you see the task manager).
278  browser()->window()->ShowTaskManager();
279
280  ASSERT_TRUE(LoadExtension(
281      test_data_dir_.AppendASCII("packaged_app")));
282  ExtensionService* service = browser()->profile()->GetExtensionService();
283  const Extension* extension =
284      service->GetExtensionById(last_loaded_extension_id_, false);
285
286  // Browser and the New Tab Page.
287  WaitForResourceChange(2);
288
289  // Open a new tab to the app's launch URL and make sure we notice that.
290  GURL url(extension->GetResourceURL("main.html"));
291  AddTabAtIndex(0, url, PageTransition::TYPED);
292  WaitForResourceChange(3);
293
294  // Check that the third entry (main.html) is of type extension and has both
295  // a tab contents and an extension. The title should start with "App:".
296  ASSERT_EQ(TaskManager::Resource::EXTENSION, model()->GetResourceType(2));
297  ASSERT_TRUE(model()->GetResourceTabContents(2) != NULL);
298  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);
299  string16 prefix = l10n_util::GetStringFUTF16(
300      IDS_TASK_MANAGER_APP_PREFIX, string16());
301  ASSERT_TRUE(StartsWith(model()->GetResourceTitle(2), prefix, true));
302
303  // Unload extension to avoid crash on Windows.
304  UnloadExtension(last_loaded_extension_id_);
305  WaitForResourceChange(2);
306}
307
308IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeNotificationChanges) {
309  EXPECT_EQ(0, model()->ResourceCount());
310
311  // Show the task manager.
312  browser()->window()->ShowTaskManager();
313  // Expect to see the browser and the New Tab Page renderer.
314  WaitForResourceChange(2);
315
316  // Show a notification.
317  NotificationUIManager* notifications =
318      g_browser_process->notification_ui_manager();
319
320  string16 content = DesktopNotificationService::CreateDataUrl(
321      GURL(), ASCIIToUTF16("Hello World!"), string16(),
322      WebKit::WebTextDirectionDefault);
323
324  scoped_refptr<NotificationDelegate> del1(new MockNotificationDelegate("n1"));
325  Notification n1(
326      GURL(), GURL(content), ASCIIToUTF16("Test 1"), string16(), del1.get());
327  scoped_refptr<NotificationDelegate> del2(new MockNotificationDelegate("n2"));
328  Notification n2(
329      GURL(), GURL(content), ASCIIToUTF16("Test 2"), string16(), del2.get());
330
331  notifications->Add(n1, browser()->profile());
332  WaitForResourceChange(3);
333  notifications->Add(n2, browser()->profile());
334  WaitForResourceChange(4);
335  notifications->CancelById(n1.notification_id());
336  WaitForResourceChange(3);
337  notifications->CancelById(n2.notification_id());
338  WaitForResourceChange(2);
339}
340
341IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, KillExtension) {
342  // Show the task manager. This populates the model, and helps with debugging
343  // (you see the task manager).
344  browser()->window()->ShowTaskManager();
345
346  ASSERT_TRUE(LoadExtension(
347      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
348
349  // Wait until we see the loaded extension in the task manager (the three
350  // resources are: the browser process, New Tab Page, and the extension).
351  WaitForResourceChange(3);
352
353  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
354  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
355  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);
356
357  // Kill the extension process and make sure we notice it.
358  TaskManager::GetInstance()->KillProcess(2);
359  WaitForResourceChange(2);
360}
361
362// Disabled, http://crbug.com/66957.
363IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
364                       DISABLED_KillExtensionAndReload) {
365  // Show the task manager. This populates the model, and helps with debugging
366  // (you see the task manager).
367  browser()->window()->ShowTaskManager();
368
369  ASSERT_TRUE(LoadExtension(
370      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
371
372  // Wait until we see the loaded extension in the task manager (the three
373  // resources are: the browser process, New Tab Page, and the extension).
374  WaitForResourceChange(3);
375
376  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
377  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
378  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);
379
380  // Kill the extension process and make sure we notice it.
381  TaskManager::GetInstance()->KillProcess(2);
382  WaitForResourceChange(2);
383
384  // Reload the extension using the "crashed extension" infobar while the task
385  // manager is still visible. Make sure we don't crash and the extension
386  // gets reloaded and noticed in the task manager.
387  TabContents* current_tab = browser()->GetSelectedTabContents();
388  ASSERT_EQ(1U, current_tab->infobar_count());
389  ConfirmInfoBarDelegate* delegate =
390      current_tab->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate();
391  ASSERT_TRUE(delegate);
392  delegate->Accept();
393  WaitForResourceChange(3);
394}
395
396// Regression test for http://crbug.com/18693.
397//
398// This test is crashy. See http://crbug.com/42315.
399IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, DISABLED_ReloadExtension) {
400  // Show the task manager. This populates the model, and helps with debugging
401  // (you see the task manager).
402  browser()->window()->ShowTaskManager();
403
404  LOG(INFO) << "loading extension";
405  ASSERT_TRUE(LoadExtension(
406      test_data_dir_.AppendASCII("common").AppendASCII("background_page")));
407
408  // Wait until we see the loaded extension in the task manager (the three
409  // resources are: the browser process, New Tab Page, and the extension).
410  LOG(INFO) << "waiting for resource change";
411  WaitForResourceChange(3);
412
413  EXPECT_TRUE(model()->GetResourceExtension(0) == NULL);
414  EXPECT_TRUE(model()->GetResourceExtension(1) == NULL);
415  ASSERT_TRUE(model()->GetResourceExtension(2) != NULL);
416
417  const Extension* extension = model()->GetResourceExtension(2);
418  ASSERT_TRUE(extension != NULL);
419
420  // Reload the extension a few times and make sure our resource count
421  // doesn't increase.
422  LOG(INFO) << "First extension reload";
423  ReloadExtension(extension->id());
424  WaitForResourceChange(3);
425  extension = model()->GetResourceExtension(2);
426  ASSERT_TRUE(extension != NULL);
427
428  LOG(INFO) << "Second extension reload";
429  ReloadExtension(extension->id());
430  WaitForResourceChange(3);
431  extension = model()->GetResourceExtension(2);
432  ASSERT_TRUE(extension != NULL);
433
434  LOG(INFO) << "Third extension reload";
435  ReloadExtension(extension->id());
436  WaitForResourceChange(3);
437}
438
439// Crashy, http://crbug.com/42301.
440IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,
441                       DISABLED_PopulateWebCacheFields) {
442  EXPECT_EQ(0, model()->ResourceCount());
443
444  // Show the task manager. This populates the model, and helps with debugging
445  // (you see the task manager).
446  browser()->window()->ShowTaskManager();
447
448  // Browser and the New Tab Page.
449  WaitForResourceChange(2);
450
451  // Open a new tab and make sure we notice that.
452  GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory),
453                                     FilePath(kTitle1File)));
454  AddTabAtIndex(0, url, PageTransition::TYPED);
455  WaitForResourceChange(3);
456
457  // Check that we get some value for the cache columns.
458  DCHECK_NE(model()->GetResourceWebCoreImageCacheSize(2),
459            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
460  DCHECK_NE(model()->GetResourceWebCoreScriptsCacheSize(2),
461            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
462  DCHECK_NE(model()->GetResourceWebCoreCSSCacheSize(2),
463            l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT));
464}
465