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