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 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 131class 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. 164IN_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. 179IN_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) 203IN_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 231IN_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 261IN_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 301IN_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. 310IN_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 325IN_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 339IN_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 366IN_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. 402IN_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. 414IN_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. 436IN_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 473IN_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 500IN_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. 525IN_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