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