• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/background_contents_service_factory.h"
11 #include "chrome/browser/browser_process.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/test/in_process_browser_test.h"
26 #include "chrome/test/ui_test_utils.h"
27 #include "content/browser/tab_contents/tab_contents.h"
28 #include "content/common/page_transition_types.h"
29 #include "grit/generated_resources.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "ui/base/l10n/l10n_util.h"
32 
33 namespace {
34 
35 const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html");
36 
37 class ResourceChangeObserver : public TaskManagerModelObserver {
38  public:
ResourceChangeObserver(const TaskManagerModel * model,int target_resource_count)39   ResourceChangeObserver(const TaskManagerModel* model,
40                          int target_resource_count)
41       : model_(model),
42         target_resource_count_(target_resource_count) {
43   }
44 
OnModelChanged()45   virtual void OnModelChanged() {
46     OnResourceChange();
47   }
48 
OnItemsChanged(int start,int length)49   virtual void OnItemsChanged(int start, int length) {
50     OnResourceChange();
51   }
52 
OnItemsAdded(int start,int length)53   virtual void OnItemsAdded(int start, int length) {
54     OnResourceChange();
55   }
56 
OnItemsRemoved(int start,int length)57   virtual void OnItemsRemoved(int start, int length) {
58     OnResourceChange();
59   }
60 
61  private:
OnResourceChange()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.
72 class BackgroundContentsListener : public NotificationObserver {
73  public:
BackgroundContentsListener(Profile * profile)74   explicit BackgroundContentsListener(Profile* profile) {
75     registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
76                    Source<Profile>(profile));
77   }
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)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 
91 class TaskManagerBrowserTest : public ExtensionBrowserTest {
92  public:
model() const93   TaskManagerModel* model() const {
94     return TaskManager::GetInstance()->model();
95   }
96 
WaitForResourceChange(int target_count)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.
WaitForBackgroundContents()107   void WaitForBackgroundContents() {
108     BackgroundContentsListener listener(browser()->profile());
109     ui_test_utils::RunMessageLoop();
110   }
111 };
112 
113 // Regression test for http://crbug.com/13361
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,ShutdownWhileOpen)114 IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ShutdownWhileOpen) {
115   browser()->window()->ShowTaskManager();
116 }
117 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeTabContentsChanges)118 IN_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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeBGContentsChanges)148 IN_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       BackgroundContentsServiceFactory::GetForProfile(browser()->profile());
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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,KillBGContents)176 IN_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       BackgroundContentsServiceFactory::GetForProfile(browser()->profile());
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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeExtensionChanges)215 IN_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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeExtensionTabs)236 IN_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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeAppTabs)275 IN_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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,NoticeNotificationChanges)308 IN_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 
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,KillExtension)341 IN_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.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,DISABLED_KillExtensionAndReload)363 IN_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.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,DISABLED_ReloadExtension)399 IN_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.
IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest,DISABLED_PopulateWebCacheFields)440 IN_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