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