Home | History | Annotate | Download | only in extensions
      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/browser_process.h"
      6 #include "chrome/browser/extensions/extension_browsertest.h"
      7 #include "chrome/browser/extensions/extension_host.h"
      8 #include "chrome/browser/extensions/extension_service.h"
      9 #include "chrome/browser/extensions/extension_system.h"
     10 #include "chrome/browser/notifications/balloon.h"
     11 #include "chrome/browser/notifications/balloon_collection.h"
     12 #include "chrome/browser/notifications/balloon_host.h"
     13 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
     14 #include "chrome/browser/notifications/notification.h"
     15 #include "chrome/browser/notifications/notification_delegate.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/browser/ui/browser_commands.h"
     19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     20 #include "chrome/test/base/ui_test_utils.h"
     21 #include "content/public/browser/navigation_controller.h"
     22 #include "content/public/browser/render_process_host.h"
     23 #include "content/public/browser/render_view_host.h"
     24 #include "content/public/browser/web_contents.h"
     25 #include "content/public/common/result_codes.h"
     26 #include "extensions/browser/process_manager.h"
     27 #include "ui/message_center/message_center.h"
     28 #include "ui/message_center/message_center_switches.h"
     29 #include "ui/message_center/message_center_util.h"
     30 #include "ui/message_center/notification_list.h"
     31 
     32 using content::NavigationController;
     33 using content::WebContents;
     34 using extensions::Extension;
     35 
     36 // Tests are timing out waiting for extension to crash.
     37 // http://crbug.com/174705
     38 #if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
     39 #define MAYBE_ExtensionCrashRecoveryTest DISABLED_ExtensionCrashRecoveryTest
     40 #else
     41 #define MAYBE_ExtensionCrashRecoveryTest ExtensionCrashRecoveryTest
     42 #endif  // defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
     43 
     44 class ExtensionCrashRecoveryTestBase : public ExtensionBrowserTest {
     45  protected:
     46   virtual void AcceptNotification(size_t index) = 0;
     47   virtual void CancelNotification(size_t index) = 0;
     48   virtual size_t CountBalloons() = 0;
     49 
     50   ExtensionService* GetExtensionService() {
     51     return browser()->profile()->GetExtensionService();
     52   }
     53 
     54   extensions::ProcessManager* GetProcessManager() {
     55     return extensions::ExtensionSystem::Get(browser()->profile())->
     56         process_manager();
     57   }
     58 
     59   void CrashExtension(std::string extension_id) {
     60     const Extension* extension =
     61         GetExtensionService()->GetExtensionById(extension_id, false);
     62     ASSERT_TRUE(extension);
     63     extensions::ExtensionHost* extension_host = GetProcessManager()->
     64         GetBackgroundHostForExtension(extension_id);
     65     ASSERT_TRUE(extension_host);
     66 
     67     base::KillProcess(extension_host->render_process_host()->GetHandle(),
     68                       content::RESULT_CODE_KILLED, false);
     69     ASSERT_TRUE(WaitForExtensionCrash(extension_id));
     70     ASSERT_FALSE(GetProcessManager()->
     71                  GetBackgroundHostForExtension(extension_id));
     72 
     73     // Wait for extension crash balloon to appear.
     74     base::MessageLoop::current()->RunUntilIdle();
     75   }
     76 
     77   void CheckExtensionConsistency(std::string extension_id) {
     78     const Extension* extension =
     79         GetExtensionService()->extensions()->GetByID(extension_id);
     80     ASSERT_TRUE(extension);
     81     extensions::ExtensionHost* extension_host = GetProcessManager()->
     82         GetBackgroundHostForExtension(extension_id);
     83     ASSERT_TRUE(extension_host);
     84     extensions::ProcessManager::ViewSet all_views =
     85         GetProcessManager()->GetAllViews();
     86     extensions::ProcessManager::ViewSet::const_iterator it =
     87         all_views.find(extension_host->host_contents()->GetRenderViewHost());
     88     ASSERT_FALSE(it == all_views.end());
     89     ASSERT_TRUE(extension_host->IsRenderViewLive());
     90     extensions::ProcessMap* process_map =
     91         browser()->profile()->GetExtensionService()->process_map();
     92     ASSERT_TRUE(process_map->Contains(
     93         extension_id,
     94         extension_host->render_view_host()->GetProcess()->GetID()));
     95   }
     96 
     97   void LoadTestExtension() {
     98     ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
     99     const Extension* extension = LoadExtension(
    100         test_data_dir_.AppendASCII("common").AppendASCII("background_page"));
    101     ASSERT_TRUE(extension);
    102     first_extension_id_ = extension->id();
    103     CheckExtensionConsistency(first_extension_id_);
    104   }
    105 
    106   void LoadSecondExtension() {
    107     const Extension* extension = LoadExtension(
    108         test_data_dir_.AppendASCII("install").AppendASCII("install"));
    109     ASSERT_TRUE(extension);
    110     second_extension_id_ = extension->id();
    111     CheckExtensionConsistency(second_extension_id_);
    112   }
    113 
    114   std::string first_extension_id_;
    115   std::string second_extension_id_;
    116 };
    117 
    118 class MAYBE_ExtensionCrashRecoveryTest
    119     : public ExtensionCrashRecoveryTestBase {
    120  protected:
    121   virtual void AcceptNotification(size_t index) OVERRIDE {
    122     if (message_center::IsRichNotificationEnabled()) {
    123       message_center::MessageCenter* message_center =
    124           message_center::MessageCenter::Get();
    125       ASSERT_GT(message_center->NotificationCount(), index);
    126       message_center::NotificationList::Notifications::reverse_iterator it =
    127           message_center->GetVisibleNotifications().rbegin();
    128       for (size_t i=0; i < index; ++i)
    129         it++;
    130       std::string id = (*it)->id();
    131       message_center->ClickOnNotification(id);
    132     } else {
    133       Balloon* balloon = GetNotificationDelegate(index);
    134       ASSERT_TRUE(balloon);
    135       balloon->OnClick();
    136     }
    137     WaitForExtensionLoad();
    138   }
    139 
    140   virtual void CancelNotification(size_t index) OVERRIDE {
    141     if (message_center::IsRichNotificationEnabled()) {
    142       message_center::MessageCenter* message_center =
    143           message_center::MessageCenter::Get();
    144       ASSERT_GT(message_center->NotificationCount(), index);
    145       message_center::NotificationList::Notifications::reverse_iterator it =
    146           message_center->GetVisibleNotifications().rbegin();
    147       for (size_t i=0; i < index; i++) { it++; }
    148       ASSERT_TRUE(g_browser_process->notification_ui_manager()->
    149           CancelById((*it)->id()));
    150     } else {
    151       Balloon* balloon = GetNotificationDelegate(index);
    152       ASSERT_TRUE(balloon);
    153       std::string id = balloon->notification().notification_id();
    154       ASSERT_TRUE(g_browser_process->notification_ui_manager()->CancelById(id));
    155     }
    156   }
    157 
    158   virtual size_t CountBalloons() OVERRIDE {
    159     if (message_center::IsRichNotificationEnabled())
    160       return message_center::MessageCenter::Get()->NotificationCount();
    161 
    162     return BalloonNotificationUIManager::GetInstanceForTesting()->
    163         balloon_collection()->GetActiveBalloons().size();
    164   }
    165 
    166 private:
    167      Balloon* GetNotificationDelegate(size_t index) {
    168        BalloonNotificationUIManager* manager =
    169            BalloonNotificationUIManager::GetInstanceForTesting();
    170        BalloonCollection::Balloons balloons =
    171            manager->balloon_collection()->GetActiveBalloons();
    172        return index < balloons.size() ? balloons.at(index) : NULL;
    173      }
    174 };
    175 
    176 // Flaky: http://crbug.com/242167.
    177 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest, DISABLED_Basic) {
    178   const size_t size_before = GetExtensionService()->extensions()->size();
    179   const size_t crash_size_before =
    180       GetExtensionService()->terminated_extensions()->size();
    181   LoadTestExtension();
    182   CrashExtension(first_extension_id_);
    183   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    184   ASSERT_EQ(crash_size_before + 1,
    185             GetExtensionService()->terminated_extensions()->size());
    186   ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    187 
    188   SCOPED_TRACE("after clicking the balloon");
    189   CheckExtensionConsistency(first_extension_id_);
    190   ASSERT_EQ(crash_size_before,
    191             GetExtensionService()->terminated_extensions()->size());
    192 }
    193 
    194 // Flaky, http://crbug.com/241191.
    195 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    196                        DISABLED_CloseAndReload) {
    197   const size_t size_before = GetExtensionService()->extensions()->size();
    198   const size_t crash_size_before =
    199       GetExtensionService()->terminated_extensions()->size();
    200   LoadTestExtension();
    201   CrashExtension(first_extension_id_);
    202 
    203   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    204   ASSERT_EQ(crash_size_before + 1,
    205             GetExtensionService()->terminated_extensions()->size());
    206 
    207   ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
    208   ReloadExtension(first_extension_id_);
    209 
    210   SCOPED_TRACE("after reloading");
    211   CheckExtensionConsistency(first_extension_id_);
    212   ASSERT_EQ(crash_size_before,
    213             GetExtensionService()->terminated_extensions()->size());
    214 }
    215 
    216 // Test is timing out on Windows http://crbug.com/174705.
    217 #if defined(OS_WIN)
    218 #define MAYBE_ReloadIndependently DISABLED_ReloadIndependently
    219 #else
    220 #define MAYBE_ReloadIndependently ReloadIndependently
    221 #endif  // defined(OS_WIN)
    222 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    223                        MAYBE_ReloadIndependently) {
    224   const size_t size_before = GetExtensionService()->extensions()->size();
    225   LoadTestExtension();
    226   CrashExtension(first_extension_id_);
    227   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    228 
    229   ReloadExtension(first_extension_id_);
    230 
    231   SCOPED_TRACE("after reloading");
    232   CheckExtensionConsistency(first_extension_id_);
    233 
    234   WebContents* current_tab =
    235       browser()->tab_strip_model()->GetActiveWebContents();
    236   ASSERT_TRUE(current_tab);
    237 
    238   // The balloon should automatically hide after the extension is successfully
    239   // reloaded.
    240   ASSERT_EQ(0U, CountBalloons());
    241 }
    242 
    243 // Test is timing out on Windows http://crbug.com/174705.
    244 #if defined(OS_WIN)
    245 #define MAYBE_ReloadIndependentlyChangeTabs DISABLED_ReloadIndependentlyChangeTabs
    246 #else
    247 #define MAYBE_ReloadIndependentlyChangeTabs ReloadIndependentlyChangeTabs
    248 #endif  // defined(OS_WIN)
    249 
    250 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    251                        MAYBE_ReloadIndependentlyChangeTabs) {
    252   const size_t size_before = GetExtensionService()->extensions()->size();
    253   LoadTestExtension();
    254   CrashExtension(first_extension_id_);
    255   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    256 
    257   WebContents* original_tab =
    258       browser()->tab_strip_model()->GetActiveWebContents();
    259   ASSERT_TRUE(original_tab);
    260   ASSERT_EQ(1U, CountBalloons());
    261 
    262   // Open a new tab, but the balloon will still be there.
    263   chrome::NewTab(browser());
    264   WebContents* new_current_tab =
    265       browser()->tab_strip_model()->GetActiveWebContents();
    266   ASSERT_TRUE(new_current_tab);
    267   ASSERT_NE(new_current_tab, original_tab);
    268   ASSERT_EQ(1U, CountBalloons());
    269 
    270   ReloadExtension(first_extension_id_);
    271 
    272   SCOPED_TRACE("after reloading");
    273   CheckExtensionConsistency(first_extension_id_);
    274 
    275   // The balloon should automatically hide after the extension is successfully
    276   // reloaded.
    277   ASSERT_EQ(0U, CountBalloons());
    278 }
    279 
    280 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    281                        DISABLED_ReloadIndependentlyNavigatePage) {
    282   const size_t size_before = GetExtensionService()->extensions()->size();
    283   LoadTestExtension();
    284   CrashExtension(first_extension_id_);
    285   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    286 
    287   WebContents* current_tab =
    288       browser()->tab_strip_model()->GetActiveWebContents();
    289   ASSERT_TRUE(current_tab);
    290   ASSERT_EQ(1U, CountBalloons());
    291 
    292   // Navigate to another page.
    293   ui_test_utils::NavigateToURL(
    294       browser(), ui_test_utils::GetTestUrl(
    295                      base::FilePath(base::FilePath::kCurrentDirectory),
    296                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
    297   ASSERT_EQ(1U, CountBalloons());
    298 
    299   ReloadExtension(first_extension_id_);
    300 
    301   SCOPED_TRACE("after reloading");
    302   CheckExtensionConsistency(first_extension_id_);
    303 
    304   // The balloon should automatically hide after the extension is successfully
    305   // reloaded.
    306   ASSERT_EQ(0U, CountBalloons());
    307 }
    308 
    309 // Make sure that when we don't do anything about the crashed extension
    310 // and close the browser, it doesn't crash. The browser is closed implicitly
    311 // at the end of each browser test.
    312 //
    313 // http://crbug.com/84719
    314 #if defined(OS_LINUX)
    315 #define MAYBE_ShutdownWhileCrashed DISABLED_ShutdownWhileCrashed
    316 #else
    317 #define MAYBE_ShutdownWhileCrashed ShutdownWhileCrashed
    318 #endif  // defined(OS_LINUX)
    319 
    320 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    321                        MAYBE_ShutdownWhileCrashed) {
    322   const size_t size_before = GetExtensionService()->extensions()->size();
    323   LoadTestExtension();
    324   CrashExtension(first_extension_id_);
    325   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    326 }
    327 
    328 // Flaky, http://crbug.com/241245.
    329 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    330                        DISABLED_TwoExtensionsCrashFirst) {
    331   const size_t size_before = GetExtensionService()->extensions()->size();
    332   LoadTestExtension();
    333   LoadSecondExtension();
    334   CrashExtension(first_extension_id_);
    335   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    336   ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    337 
    338   SCOPED_TRACE("after clicking the balloon");
    339   CheckExtensionConsistency(first_extension_id_);
    340   CheckExtensionConsistency(second_extension_id_);
    341 }
    342 
    343 // Flaky: http://crbug.com/242196
    344 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    345                        DISABLED_TwoExtensionsCrashSecond) {
    346   const size_t size_before = GetExtensionService()->extensions()->size();
    347   LoadTestExtension();
    348   LoadSecondExtension();
    349   CrashExtension(second_extension_id_);
    350   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    351   ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    352 
    353   SCOPED_TRACE("after clicking the balloon");
    354   CheckExtensionConsistency(first_extension_id_);
    355   CheckExtensionConsistency(second_extension_id_);
    356 }
    357 
    358 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    359                        TwoExtensionsCrashBothAtOnce) {
    360   const size_t size_before = GetExtensionService()->extensions()->size();
    361   const size_t crash_size_before =
    362       GetExtensionService()->terminated_extensions()->size();
    363   LoadTestExtension();
    364   LoadSecondExtension();
    365   CrashExtension(first_extension_id_);
    366   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    367   ASSERT_EQ(crash_size_before + 1,
    368             GetExtensionService()->terminated_extensions()->size());
    369   CrashExtension(second_extension_id_);
    370   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    371   ASSERT_EQ(crash_size_before + 2,
    372             GetExtensionService()->terminated_extensions()->size());
    373 
    374   {
    375     SCOPED_TRACE("first balloon");
    376     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    377     CheckExtensionConsistency(first_extension_id_);
    378   }
    379 
    380   {
    381     SCOPED_TRACE("second balloon");
    382     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    383     CheckExtensionConsistency(first_extension_id_);
    384     CheckExtensionConsistency(second_extension_id_);
    385   }
    386 }
    387 
    388 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    389                        TwoExtensionsOneByOne) {
    390   const size_t size_before = GetExtensionService()->extensions()->size();
    391   LoadTestExtension();
    392   CrashExtension(first_extension_id_);
    393   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    394   LoadSecondExtension();
    395   CrashExtension(second_extension_id_);
    396   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    397 
    398   {
    399     SCOPED_TRACE("first balloon");
    400     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    401     CheckExtensionConsistency(first_extension_id_);
    402   }
    403 
    404   {
    405     SCOPED_TRACE("second balloon");
    406     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    407     CheckExtensionConsistency(first_extension_id_);
    408     CheckExtensionConsistency(second_extension_id_);
    409   }
    410 }
    411 
    412 // http://crbug.com/84719
    413 #if defined(OS_LINUX)
    414 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
    415     DISABLED_TwoExtensionsShutdownWhileCrashed
    416 #else
    417 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
    418     TwoExtensionsShutdownWhileCrashed
    419 #endif  // defined(OS_LINUX)
    420 
    421 // Make sure that when we don't do anything about the crashed extensions
    422 // and close the browser, it doesn't crash. The browser is closed implicitly
    423 // at the end of each browser test.
    424 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    425                        MAYBE_TwoExtensionsShutdownWhileCrashed) {
    426   const size_t size_before = GetExtensionService()->extensions()->size();
    427   LoadTestExtension();
    428   CrashExtension(first_extension_id_);
    429   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    430   LoadSecondExtension();
    431   CrashExtension(second_extension_id_);
    432   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    433 }
    434 
    435 // Flaky, http://crbug.com/241573.
    436 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    437                        DISABLED_TwoExtensionsIgnoreFirst) {
    438   const size_t size_before = GetExtensionService()->extensions()->size();
    439   LoadTestExtension();
    440   LoadSecondExtension();
    441   CrashExtension(first_extension_id_);
    442   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    443   CrashExtension(second_extension_id_);
    444   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    445 
    446   // Accept notification 1 before canceling notification 0.
    447   // Otherwise, on Linux and Windows, there is a race here, in which
    448   // canceled notifications do not immediately go away.
    449   ASSERT_NO_FATAL_FAILURE(AcceptNotification(1));
    450   ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
    451 
    452   SCOPED_TRACE("balloons done");
    453   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    454   CheckExtensionConsistency(second_extension_id_);
    455 }
    456 
    457 // Flaky, http://crbug.com/241164.
    458 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    459                        DISABLED_TwoExtensionsReloadIndependently) {
    460   const size_t size_before = GetExtensionService()->extensions()->size();
    461   LoadTestExtension();
    462   LoadSecondExtension();
    463   CrashExtension(first_extension_id_);
    464   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    465   CrashExtension(second_extension_id_);
    466   ASSERT_EQ(size_before, GetExtensionService()->extensions()->size());
    467 
    468   {
    469     SCOPED_TRACE("first: reload");
    470     WebContents* current_tab =
    471         browser()->tab_strip_model()->GetActiveWebContents();
    472     ASSERT_TRUE(current_tab);
    473     // At the beginning we should have one balloon displayed for each extension.
    474     ASSERT_EQ(2U, CountBalloons());
    475     ReloadExtension(first_extension_id_);
    476     // One of the balloons should hide after the extension is reloaded.
    477     ASSERT_EQ(1U, CountBalloons());
    478     CheckExtensionConsistency(first_extension_id_);
    479   }
    480 
    481   {
    482     SCOPED_TRACE("second: balloon");
    483     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
    484     CheckExtensionConsistency(first_extension_id_);
    485     CheckExtensionConsistency(second_extension_id_);
    486   }
    487 }
    488 
    489 // http://crbug.com/243648
    490 #if defined(OS_WIN)
    491 #define MAYBE_CrashAndUninstall DISABLED_CrashAndUninstall
    492 #else
    493 #define MAYBE_CrashAndUninstall CrashAndUninstall
    494 #endif
    495 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    496                        MAYBE_CrashAndUninstall) {
    497   const size_t size_before = GetExtensionService()->extensions()->size();
    498   const size_t crash_size_before =
    499       GetExtensionService()->terminated_extensions()->size();
    500   LoadTestExtension();
    501   LoadSecondExtension();
    502   CrashExtension(first_extension_id_);
    503   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    504   ASSERT_EQ(crash_size_before + 1,
    505             GetExtensionService()->terminated_extensions()->size());
    506 
    507   ASSERT_EQ(1U, CountBalloons());
    508   UninstallExtension(first_extension_id_);
    509   base::MessageLoop::current()->RunUntilIdle();
    510 
    511   SCOPED_TRACE("after uninstalling");
    512   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    513   ASSERT_EQ(crash_size_before,
    514             GetExtensionService()->terminated_extensions()->size());
    515   ASSERT_EQ(0U, CountBalloons());
    516 }
    517 
    518 // http://crbug.com/84719
    519 #if defined(OS_LINUX)
    520 #define MAYBE_CrashAndUnloadAll DISABLED_CrashAndUnloadAll
    521 #else
    522 #define MAYBE_CrashAndUnloadAll CrashAndUnloadAll
    523 #endif  // defined(OS_LINUX)
    524 
    525 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    526                        MAYBE_CrashAndUnloadAll) {
    527   const size_t size_before = GetExtensionService()->extensions()->size();
    528   const size_t crash_size_before =
    529       GetExtensionService()->terminated_extensions()->size();
    530   LoadTestExtension();
    531   LoadSecondExtension();
    532   CrashExtension(first_extension_id_);
    533   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    534   ASSERT_EQ(crash_size_before + 1,
    535             GetExtensionService()->terminated_extensions()->size());
    536 
    537   GetExtensionService()->UnloadAllExtensions();
    538   ASSERT_EQ(crash_size_before,
    539             GetExtensionService()->terminated_extensions()->size());
    540 }
    541 
    542 // Fails a DCHECK on Aura and Linux: http://crbug.com/169622
    543 // Failing on Windows: http://crbug.com/232340
    544 #if defined(USE_AURA) || defined(OS_WIN) || defined(OS_LINUX)
    545 #define MAYBE_ReloadTabsWithBackgroundPage DISABLED_ReloadTabsWithBackgroundPage
    546 #else
    547 #define MAYBE_ReloadTabsWithBackgroundPage ReloadTabsWithBackgroundPage
    548 #endif
    549 
    550 // Test that when an extension with a background page that has a tab open
    551 // crashes, the tab stays open, and reloading it reloads the extension.
    552 // Regression test for issue 71629.
    553 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
    554                        MAYBE_ReloadTabsWithBackgroundPage) {
    555   TabStripModel* tab_strip = browser()->tab_strip_model();
    556   const size_t size_before = GetExtensionService()->extensions()->size();
    557   const size_t crash_size_before =
    558       GetExtensionService()->terminated_extensions()->size();
    559   LoadTestExtension();
    560 
    561   // Open a tab extension.
    562   chrome::NewTab(browser());
    563   ui_test_utils::NavigateToURL(
    564       browser(),
    565       GURL("chrome-extension://" + first_extension_id_ + "/background.html"));
    566 
    567   const int tabs_before = tab_strip->count();
    568   CrashExtension(first_extension_id_);
    569 
    570   // Tab should still be open, and extension should be crashed.
    571   EXPECT_EQ(tabs_before, tab_strip->count());
    572   EXPECT_EQ(size_before, GetExtensionService()->extensions()->size());
    573   EXPECT_EQ(crash_size_before + 1,
    574             GetExtensionService()->terminated_extensions()->size());
    575 
    576   {
    577     content::WindowedNotificationObserver observer(
    578         content::NOTIFICATION_LOAD_STOP,
    579         content::Source<NavigationController>(
    580             &browser()->tab_strip_model()->GetActiveWebContents()->
    581                 GetController()));
    582     chrome::Reload(browser(), CURRENT_TAB);
    583     observer.Wait();
    584   }
    585   // Extension should now be loaded.
    586   SCOPED_TRACE("after reloading the tab");
    587   CheckExtensionConsistency(first_extension_id_);
    588   ASSERT_EQ(size_before + 1, GetExtensionService()->extensions()->size());
    589   ASSERT_EQ(0U, CountBalloons());
    590 }
    591