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