Home | History | Annotate | Download | only in task_manager
      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:
     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.
     72 class 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 
     91 class 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
    114 IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, ShutdownWhileOpen) {
    115   browser()->window()->ShowTaskManager();
    116 }
    117 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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.
    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