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.
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/notifications/balloon.h"
10 #include "chrome/browser/notifications/balloon_collection.h"
11 #include "chrome/browser/notifications/balloon_host.h"
12 #include "chrome/browser/notifications/notification.h"
13 #include "chrome/browser/notifications/notification_delegate.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_commands.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/result_codes.h"
24 #include "extensions/browser/extension_registry.h"
25 #include "extensions/browser/extension_system.h"
26 #include "extensions/browser/process_manager.h"
27 #include "extensions/browser/process_map.h"
28 #include "ui/message_center/message_center.h"
29 #include "ui/message_center/message_center_switches.h"
30 #include "ui/message_center/message_center_util.h"
31 #include "ui/message_center/notification_list.h"
33 #if defined(OS_CHROMEOS)
34 #include "chrome/browser/notifications/notification_ui_manager.h"
36 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
39 using content::NavigationController
;
40 using content::WebContents
;
41 using extensions::Extension
;
42 using extensions::ExtensionRegistry
;
44 // Tests are timing out waiting for extension to crash.
45 // http://crbug.com/174705
46 #if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
47 #define MAYBE_ExtensionCrashRecoveryTest DISABLED_ExtensionCrashRecoveryTest
49 #define MAYBE_ExtensionCrashRecoveryTest ExtensionCrashRecoveryTest
50 #endif // defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
52 class ExtensionCrashRecoveryTestBase
: public ExtensionBrowserTest
{
54 virtual void AcceptNotification(size_t index
) = 0;
55 virtual void CancelNotification(size_t index
) = 0;
56 virtual size_t CountBalloons() = 0;
58 ExtensionService
* GetExtensionService() {
59 return browser()->profile()->GetExtensionService();
62 extensions::ProcessManager
* GetProcessManager() {
63 return extensions::ExtensionSystem::Get(browser()->profile())->
67 size_t GetEnabledExtensionCount() {
68 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
69 return registry
->enabled_extensions().size();
72 size_t GetTerminatedExtensionCount() {
73 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
74 return registry
->terminated_extensions().size();
77 void CrashExtension(std::string extension_id
) {
78 const Extension
* extension
=
79 GetExtensionService()->GetExtensionById(extension_id
, false);
80 ASSERT_TRUE(extension
);
81 extensions::ExtensionHost
* extension_host
= GetProcessManager()->
82 GetBackgroundHostForExtension(extension_id
);
83 ASSERT_TRUE(extension_host
);
85 base::KillProcess(extension_host
->render_process_host()->GetHandle(),
86 content::RESULT_CODE_KILLED
, false);
87 ASSERT_TRUE(WaitForExtensionCrash(extension_id
));
88 ASSERT_FALSE(GetProcessManager()->
89 GetBackgroundHostForExtension(extension_id
));
91 // Wait for extension crash balloon to appear.
92 base::MessageLoop::current()->RunUntilIdle();
95 void CheckExtensionConsistency(std::string extension_id
) {
96 const Extension
* extension
=
97 GetExtensionService()->extensions()->GetByID(extension_id
);
98 ASSERT_TRUE(extension
);
99 extensions::ExtensionHost
* extension_host
= GetProcessManager()->
100 GetBackgroundHostForExtension(extension_id
);
101 ASSERT_TRUE(extension_host
);
102 extensions::ProcessManager::ViewSet all_views
=
103 GetProcessManager()->GetAllViews();
104 extensions::ProcessManager::ViewSet::const_iterator it
=
105 all_views
.find(extension_host
->host_contents()->GetRenderViewHost());
106 ASSERT_FALSE(it
== all_views
.end());
107 ASSERT_TRUE(extension_host
->IsRenderViewLive());
108 extensions::ProcessMap
* process_map
=
109 extensions::ProcessMap::Get(browser()->profile());
110 ASSERT_TRUE(process_map
->Contains(
112 extension_host
->render_view_host()->GetProcess()->GetID()));
115 void LoadTestExtension() {
116 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
117 const Extension
* extension
= LoadExtension(
118 test_data_dir_
.AppendASCII("common").AppendASCII("background_page"));
119 ASSERT_TRUE(extension
);
120 first_extension_id_
= extension
->id();
121 CheckExtensionConsistency(first_extension_id_
);
124 void LoadSecondExtension() {
125 const Extension
* extension
= LoadExtension(
126 test_data_dir_
.AppendASCII("install").AppendASCII("install"));
127 ASSERT_TRUE(extension
);
128 second_extension_id_
= extension
->id();
129 CheckExtensionConsistency(second_extension_id_
);
132 std::string first_extension_id_
;
133 std::string second_extension_id_
;
136 class MAYBE_ExtensionCrashRecoveryTest
137 : public ExtensionCrashRecoveryTestBase
{
139 virtual void AcceptNotification(size_t index
) OVERRIDE
{
140 if (message_center::IsRichNotificationEnabled()) {
141 message_center::MessageCenter
* message_center
=
142 message_center::MessageCenter::Get();
143 ASSERT_GT(message_center
->NotificationCount(), index
);
144 message_center::NotificationList::Notifications::reverse_iterator it
=
145 message_center
->GetVisibleNotifications().rbegin();
146 for (size_t i
=0; i
< index
; ++i
)
148 std::string id
= (*it
)->id();
149 message_center
->ClickOnNotification(id
);
150 #if !defined(OS_CHROMEOS)
152 Balloon
* balloon
= GetNotificationDelegate(index
);
153 ASSERT_TRUE(balloon
);
157 WaitForExtensionLoad();
160 virtual void CancelNotification(size_t index
) OVERRIDE
{
161 if (message_center::IsRichNotificationEnabled()) {
162 message_center::MessageCenter
* message_center
=
163 message_center::MessageCenter::Get();
164 ASSERT_GT(message_center
->NotificationCount(), index
);
165 message_center::NotificationList::Notifications::reverse_iterator it
=
166 message_center
->GetVisibleNotifications().rbegin();
167 for (size_t i
=0; i
< index
; i
++) { it
++; }
168 ASSERT_TRUE(g_browser_process
->notification_ui_manager()->
169 CancelById((*it
)->id()));
170 #if !defined(OS_CHROMEOS)
172 Balloon
* balloon
= GetNotificationDelegate(index
);
173 ASSERT_TRUE(balloon
);
174 std::string id
= balloon
->notification().notification_id();
175 ASSERT_TRUE(g_browser_process
->notification_ui_manager()->CancelById(id
));
180 virtual size_t CountBalloons() OVERRIDE
{
181 if (message_center::IsRichNotificationEnabled())
182 return message_center::MessageCenter::Get()->NotificationCount();
184 #if defined(OS_CHROMEOS)
188 return BalloonNotificationUIManager::GetInstanceForTesting()->
189 balloon_collection()->GetActiveBalloons().size();
194 #if !defined(OS_CHROMEOS)
195 Balloon
* GetNotificationDelegate(size_t index
) {
196 BalloonNotificationUIManager
* manager
=
197 BalloonNotificationUIManager::GetInstanceForTesting();
198 BalloonCollection::Balloons balloons
=
199 manager
->balloon_collection()->GetActiveBalloons();
200 return index
< balloons
.size() ? balloons
.at(index
) : NULL
;
205 // Flaky: http://crbug.com/242167.
206 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
, DISABLED_Basic
) {
207 const size_t count_before
= GetEnabledExtensionCount();
208 const size_t crash_count_before
= GetTerminatedExtensionCount();
210 CrashExtension(first_extension_id_
);
211 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
212 ASSERT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
213 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
215 SCOPED_TRACE("after clicking the balloon");
216 CheckExtensionConsistency(first_extension_id_
);
217 ASSERT_EQ(crash_count_before
, GetTerminatedExtensionCount());
220 // Flaky, http://crbug.com/241191.
221 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
222 DISABLED_CloseAndReload
) {
223 const size_t count_before
= GetEnabledExtensionCount();
224 const size_t crash_count_before
= GetTerminatedExtensionCount();
226 CrashExtension(first_extension_id_
);
228 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
229 ASSERT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
231 ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
232 ReloadExtension(first_extension_id_
);
234 SCOPED_TRACE("after reloading");
235 CheckExtensionConsistency(first_extension_id_
);
236 ASSERT_EQ(crash_count_before
, GetTerminatedExtensionCount());
239 // Test is timing out on Windows http://crbug.com/174705.
241 #define MAYBE_ReloadIndependently DISABLED_ReloadIndependently
243 #define MAYBE_ReloadIndependently ReloadIndependently
244 #endif // defined(OS_WIN)
245 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
246 MAYBE_ReloadIndependently
) {
247 const size_t count_before
= GetEnabledExtensionCount();
249 CrashExtension(first_extension_id_
);
250 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
252 ReloadExtension(first_extension_id_
);
254 SCOPED_TRACE("after reloading");
255 CheckExtensionConsistency(first_extension_id_
);
257 WebContents
* current_tab
=
258 browser()->tab_strip_model()->GetActiveWebContents();
259 ASSERT_TRUE(current_tab
);
261 // The balloon should automatically hide after the extension is successfully
263 ASSERT_EQ(0U, CountBalloons());
266 // Test is timing out on Windows http://crbug.com/174705.
268 #define MAYBE_ReloadIndependentlyChangeTabs DISABLED_ReloadIndependentlyChangeTabs
270 #define MAYBE_ReloadIndependentlyChangeTabs ReloadIndependentlyChangeTabs
271 #endif // defined(OS_WIN)
273 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
274 MAYBE_ReloadIndependentlyChangeTabs
) {
275 const size_t count_before
= GetEnabledExtensionCount();
277 CrashExtension(first_extension_id_
);
278 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
280 WebContents
* original_tab
=
281 browser()->tab_strip_model()->GetActiveWebContents();
282 ASSERT_TRUE(original_tab
);
283 ASSERT_EQ(1U, CountBalloons());
285 // Open a new tab, but the balloon will still be there.
286 chrome::NewTab(browser());
287 WebContents
* new_current_tab
=
288 browser()->tab_strip_model()->GetActiveWebContents();
289 ASSERT_TRUE(new_current_tab
);
290 ASSERT_NE(new_current_tab
, original_tab
);
291 ASSERT_EQ(1U, CountBalloons());
293 ReloadExtension(first_extension_id_
);
295 SCOPED_TRACE("after reloading");
296 CheckExtensionConsistency(first_extension_id_
);
298 // The balloon should automatically hide after the extension is successfully
300 ASSERT_EQ(0U, CountBalloons());
303 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
304 DISABLED_ReloadIndependentlyNavigatePage
) {
305 const size_t count_before
= GetEnabledExtensionCount();
307 CrashExtension(first_extension_id_
);
308 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
310 WebContents
* current_tab
=
311 browser()->tab_strip_model()->GetActiveWebContents();
312 ASSERT_TRUE(current_tab
);
313 ASSERT_EQ(1U, CountBalloons());
315 // Navigate to another page.
316 ui_test_utils::NavigateToURL(
317 browser(), ui_test_utils::GetTestUrl(
318 base::FilePath(base::FilePath::kCurrentDirectory
),
319 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
320 ASSERT_EQ(1U, CountBalloons());
322 ReloadExtension(first_extension_id_
);
324 SCOPED_TRACE("after reloading");
325 CheckExtensionConsistency(first_extension_id_
);
327 // The balloon should automatically hide after the extension is successfully
329 ASSERT_EQ(0U, CountBalloons());
332 // Make sure that when we don't do anything about the crashed extension
333 // and close the browser, it doesn't crash. The browser is closed implicitly
334 // at the end of each browser test.
336 // http://crbug.com/84719
337 #if defined(OS_LINUX)
338 #define MAYBE_ShutdownWhileCrashed DISABLED_ShutdownWhileCrashed
340 #define MAYBE_ShutdownWhileCrashed ShutdownWhileCrashed
341 #endif // defined(OS_LINUX)
343 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
344 MAYBE_ShutdownWhileCrashed
) {
345 const size_t count_before
= GetEnabledExtensionCount();
347 CrashExtension(first_extension_id_
);
348 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
351 // Flaky, http://crbug.com/241245.
352 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
353 DISABLED_TwoExtensionsCrashFirst
) {
354 const size_t count_before
= GetEnabledExtensionCount();
356 LoadSecondExtension();
357 CrashExtension(first_extension_id_
);
358 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
359 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
361 SCOPED_TRACE("after clicking the balloon");
362 CheckExtensionConsistency(first_extension_id_
);
363 CheckExtensionConsistency(second_extension_id_
);
366 // Flaky: http://crbug.com/242196
367 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
368 DISABLED_TwoExtensionsCrashSecond
) {
369 const size_t count_before
= GetEnabledExtensionCount();
371 LoadSecondExtension();
372 CrashExtension(second_extension_id_
);
373 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
374 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
376 SCOPED_TRACE("after clicking the balloon");
377 CheckExtensionConsistency(first_extension_id_
);
378 CheckExtensionConsistency(second_extension_id_
);
381 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
382 TwoExtensionsCrashBothAtOnce
) {
383 const size_t count_before
= GetEnabledExtensionCount();
384 const size_t crash_count_before
= GetTerminatedExtensionCount();
386 LoadSecondExtension();
387 CrashExtension(first_extension_id_
);
388 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
389 ASSERT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
390 CrashExtension(second_extension_id_
);
391 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
392 ASSERT_EQ(crash_count_before
+ 2, GetTerminatedExtensionCount());
395 SCOPED_TRACE("first balloon");
396 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
397 CheckExtensionConsistency(first_extension_id_
);
401 SCOPED_TRACE("second balloon");
402 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
403 CheckExtensionConsistency(first_extension_id_
);
404 CheckExtensionConsistency(second_extension_id_
);
408 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
409 TwoExtensionsOneByOne
) {
410 const size_t count_before
= GetEnabledExtensionCount();
412 CrashExtension(first_extension_id_
);
413 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
414 LoadSecondExtension();
415 CrashExtension(second_extension_id_
);
416 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
419 SCOPED_TRACE("first balloon");
420 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
421 CheckExtensionConsistency(first_extension_id_
);
425 SCOPED_TRACE("second balloon");
426 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
427 CheckExtensionConsistency(first_extension_id_
);
428 CheckExtensionConsistency(second_extension_id_
);
432 // http://crbug.com/84719
433 #if defined(OS_LINUX)
434 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
435 DISABLED_TwoExtensionsShutdownWhileCrashed
437 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
438 TwoExtensionsShutdownWhileCrashed
439 #endif // defined(OS_LINUX)
441 // Make sure that when we don't do anything about the crashed extensions
442 // and close the browser, it doesn't crash. The browser is closed implicitly
443 // at the end of each browser test.
444 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
445 MAYBE_TwoExtensionsShutdownWhileCrashed
) {
446 const size_t count_before
= GetEnabledExtensionCount();
448 CrashExtension(first_extension_id_
);
449 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
450 LoadSecondExtension();
451 CrashExtension(second_extension_id_
);
452 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
455 // Flaky, http://crbug.com/241573.
456 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
457 DISABLED_TwoExtensionsIgnoreFirst
) {
458 const size_t count_before
= GetEnabledExtensionCount();
460 LoadSecondExtension();
461 CrashExtension(first_extension_id_
);
462 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
463 CrashExtension(second_extension_id_
);
464 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
466 // Accept notification 1 before canceling notification 0.
467 // Otherwise, on Linux and Windows, there is a race here, in which
468 // canceled notifications do not immediately go away.
469 ASSERT_NO_FATAL_FAILURE(AcceptNotification(1));
470 ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
472 SCOPED_TRACE("balloons done");
473 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
474 CheckExtensionConsistency(second_extension_id_
);
477 // Flaky, http://crbug.com/241164.
478 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
479 DISABLED_TwoExtensionsReloadIndependently
) {
480 const size_t count_before
= GetEnabledExtensionCount();
482 LoadSecondExtension();
483 CrashExtension(first_extension_id_
);
484 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
485 CrashExtension(second_extension_id_
);
486 ASSERT_EQ(count_before
, GetEnabledExtensionCount());
489 SCOPED_TRACE("first: reload");
490 WebContents
* current_tab
=
491 browser()->tab_strip_model()->GetActiveWebContents();
492 ASSERT_TRUE(current_tab
);
493 // At the beginning we should have one balloon displayed for each extension.
494 ASSERT_EQ(2U, CountBalloons());
495 ReloadExtension(first_extension_id_
);
496 // One of the balloons should hide after the extension is reloaded.
497 ASSERT_EQ(1U, CountBalloons());
498 CheckExtensionConsistency(first_extension_id_
);
502 SCOPED_TRACE("second: balloon");
503 ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
504 CheckExtensionConsistency(first_extension_id_
);
505 CheckExtensionConsistency(second_extension_id_
);
509 // http://crbug.com/243648
511 #define MAYBE_CrashAndUninstall DISABLED_CrashAndUninstall
513 #define MAYBE_CrashAndUninstall CrashAndUninstall
515 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
516 MAYBE_CrashAndUninstall
) {
517 const size_t count_before
= GetEnabledExtensionCount();
518 const size_t crash_count_before
= GetTerminatedExtensionCount();
520 LoadSecondExtension();
521 CrashExtension(first_extension_id_
);
522 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
523 ASSERT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
525 ASSERT_EQ(1U, CountBalloons());
526 UninstallExtension(first_extension_id_
);
527 base::MessageLoop::current()->RunUntilIdle();
529 SCOPED_TRACE("after uninstalling");
530 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
531 ASSERT_EQ(crash_count_before
, GetTerminatedExtensionCount());
532 ASSERT_EQ(0U, CountBalloons());
535 // http://crbug.com/84719
536 #if defined(OS_LINUX)
537 #define MAYBE_CrashAndUnloadAll DISABLED_CrashAndUnloadAll
539 #define MAYBE_CrashAndUnloadAll CrashAndUnloadAll
540 #endif // defined(OS_LINUX)
542 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
543 MAYBE_CrashAndUnloadAll
) {
544 const size_t count_before
= GetEnabledExtensionCount();
545 const size_t crash_count_before
= GetTerminatedExtensionCount();
547 LoadSecondExtension();
548 CrashExtension(first_extension_id_
);
549 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
550 ASSERT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
552 GetExtensionService()->UnloadAllExtensionsForTest();
553 ASSERT_EQ(crash_count_before
, GetTerminatedExtensionCount());
556 // Fails a DCHECK on Aura and Linux: http://crbug.com/169622
557 // Failing on Windows: http://crbug.com/232340
558 #if defined(USE_AURA) || defined(OS_WIN) || defined(OS_LINUX)
559 #define MAYBE_ReloadTabsWithBackgroundPage DISABLED_ReloadTabsWithBackgroundPage
561 #define MAYBE_ReloadTabsWithBackgroundPage ReloadTabsWithBackgroundPage
564 // Test that when an extension with a background page that has a tab open
565 // crashes, the tab stays open, and reloading it reloads the extension.
566 // Regression test for issue 71629.
567 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest
,
568 MAYBE_ReloadTabsWithBackgroundPage
) {
569 TabStripModel
* tab_strip
= browser()->tab_strip_model();
570 const size_t count_before
= GetEnabledExtensionCount();
571 const size_t crash_count_before
= GetTerminatedExtensionCount();
574 // Open a tab extension.
575 chrome::NewTab(browser());
576 ui_test_utils::NavigateToURL(
578 GURL("chrome-extension://" + first_extension_id_
+ "/background.html"));
580 const int tabs_before
= tab_strip
->count();
581 CrashExtension(first_extension_id_
);
583 // Tab should still be open, and extension should be crashed.
584 EXPECT_EQ(tabs_before
, tab_strip
->count());
585 EXPECT_EQ(count_before
, GetEnabledExtensionCount());
586 EXPECT_EQ(crash_count_before
+ 1, GetTerminatedExtensionCount());
589 content::WindowedNotificationObserver
observer(
590 content::NOTIFICATION_LOAD_STOP
,
591 content::Source
<NavigationController
>(
592 &browser()->tab_strip_model()->GetActiveWebContents()->
594 chrome::Reload(browser(), CURRENT_TAB
);
597 // Extension should now be loaded.
598 SCOPED_TRACE("after reloading the tab");
599 CheckExtensionConsistency(first_extension_id_
);
600 ASSERT_EQ(count_before
+ 1, GetEnabledExtensionCount());
601 ASSERT_EQ(0U, CountBalloons());