29d8f84485173c2ba2688a7cf06cf1393d8fb083
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / extension_crash_recovery_browsertest.cc
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/balloon.h"
9 #include "chrome/browser/notifications/balloon_collection.h"
10 #include "chrome/browser/notifications/balloon_host.h"
11 #include "chrome/browser/notifications/notification.h"
12 #include "chrome/browser/notifications/notification_delegate.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "content/public/browser/navigation_controller.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/result_codes.h"
23 #include "extensions/browser/extension_host.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"
32
33 #if defined(OS_CHROMEOS)
34 #include "chrome/browser/notifications/notification_ui_manager.h"
35 #else
36 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
37 #endif
38
39 using content::NavigationController;
40 using content::WebContents;
41 using extensions::Extension;
42 using extensions::ExtensionRegistry;
43
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
48 #else
49 #define MAYBE_ExtensionCrashRecoveryTest ExtensionCrashRecoveryTest
50 #endif  // defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
51
52 class ExtensionCrashRecoveryTestBase : public ExtensionBrowserTest {
53  protected:
54   virtual void AcceptNotification(size_t index) = 0;
55   virtual void CancelNotification(size_t index) = 0;
56   virtual size_t CountBalloons() = 0;
57
58   ExtensionService* GetExtensionService() {
59     return browser()->profile()->GetExtensionService();
60   }
61
62   extensions::ProcessManager* GetProcessManager() {
63     return extensions::ExtensionSystem::Get(browser()->profile())->
64         process_manager();
65   }
66
67   size_t GetEnabledExtensionCount() {
68     ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
69     return registry->enabled_extensions().size();
70   }
71
72   size_t GetTerminatedExtensionCount() {
73     ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
74     return registry->terminated_extensions().size();
75   }
76
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);
84
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));
90
91     // Wait for extension crash balloon to appear.
92     base::MessageLoop::current()->RunUntilIdle();
93   }
94
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(
111         extension_id,
112         extension_host->render_view_host()->GetProcess()->GetID()));
113   }
114
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_);
122   }
123
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_);
130   }
131
132   std::string first_extension_id_;
133   std::string second_extension_id_;
134 };
135
136 class MAYBE_ExtensionCrashRecoveryTest
137     : public ExtensionCrashRecoveryTestBase {
138  protected:
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)
147         it++;
148       std::string id = (*it)->id();
149       message_center->ClickOnNotification(id);
150 #if !defined(OS_CHROMEOS)
151     } else {
152       Balloon* balloon = GetNotificationDelegate(index);
153       ASSERT_TRUE(balloon);
154       balloon->OnClick();
155 #endif
156     }
157     WaitForExtensionLoad();
158   }
159
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)
171     } else {
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));
176 #endif
177     }
178   }
179
180   virtual size_t CountBalloons() OVERRIDE {
181     if (message_center::IsRichNotificationEnabled())
182       return message_center::MessageCenter::Get()->NotificationCount();
183
184 #if defined(OS_CHROMEOS)
185     CHECK(false);
186     return 0;
187 #else
188     return BalloonNotificationUIManager::GetInstanceForTesting()->
189         balloon_collection()->GetActiveBalloons().size();
190 #endif
191   }
192
193  private:
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;
201   }
202 #endif
203 };
204
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();
209   LoadTestExtension();
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));
214
215   SCOPED_TRACE("after clicking the balloon");
216   CheckExtensionConsistency(first_extension_id_);
217   ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
218 }
219
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();
225   LoadTestExtension();
226   CrashExtension(first_extension_id_);
227
228   ASSERT_EQ(count_before, GetEnabledExtensionCount());
229   ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
230
231   ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
232   ReloadExtension(first_extension_id_);
233
234   SCOPED_TRACE("after reloading");
235   CheckExtensionConsistency(first_extension_id_);
236   ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
237 }
238
239 // Test is timing out on Windows http://crbug.com/174705.
240 #if defined(OS_WIN)
241 #define MAYBE_ReloadIndependently DISABLED_ReloadIndependently
242 #else
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();
248   LoadTestExtension();
249   CrashExtension(first_extension_id_);
250   ASSERT_EQ(count_before, GetEnabledExtensionCount());
251
252   ReloadExtension(first_extension_id_);
253
254   SCOPED_TRACE("after reloading");
255   CheckExtensionConsistency(first_extension_id_);
256
257   WebContents* current_tab =
258       browser()->tab_strip_model()->GetActiveWebContents();
259   ASSERT_TRUE(current_tab);
260
261   // The balloon should automatically hide after the extension is successfully
262   // reloaded.
263   ASSERT_EQ(0U, CountBalloons());
264 }
265
266 // Test is timing out on Windows http://crbug.com/174705.
267 #if defined(OS_WIN)
268 #define MAYBE_ReloadIndependentlyChangeTabs DISABLED_ReloadIndependentlyChangeTabs
269 #else
270 #define MAYBE_ReloadIndependentlyChangeTabs ReloadIndependentlyChangeTabs
271 #endif  // defined(OS_WIN)
272
273 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
274                        MAYBE_ReloadIndependentlyChangeTabs) {
275   const size_t count_before = GetEnabledExtensionCount();
276   LoadTestExtension();
277   CrashExtension(first_extension_id_);
278   ASSERT_EQ(count_before, GetEnabledExtensionCount());
279
280   WebContents* original_tab =
281       browser()->tab_strip_model()->GetActiveWebContents();
282   ASSERT_TRUE(original_tab);
283   ASSERT_EQ(1U, CountBalloons());
284
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());
292
293   ReloadExtension(first_extension_id_);
294
295   SCOPED_TRACE("after reloading");
296   CheckExtensionConsistency(first_extension_id_);
297
298   // The balloon should automatically hide after the extension is successfully
299   // reloaded.
300   ASSERT_EQ(0U, CountBalloons());
301 }
302
303 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
304                        DISABLED_ReloadIndependentlyNavigatePage) {
305   const size_t count_before = GetEnabledExtensionCount();
306   LoadTestExtension();
307   CrashExtension(first_extension_id_);
308   ASSERT_EQ(count_before, GetEnabledExtensionCount());
309
310   WebContents* current_tab =
311       browser()->tab_strip_model()->GetActiveWebContents();
312   ASSERT_TRUE(current_tab);
313   ASSERT_EQ(1U, CountBalloons());
314
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());
321
322   ReloadExtension(first_extension_id_);
323
324   SCOPED_TRACE("after reloading");
325   CheckExtensionConsistency(first_extension_id_);
326
327   // The balloon should automatically hide after the extension is successfully
328   // reloaded.
329   ASSERT_EQ(0U, CountBalloons());
330 }
331
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.
335 //
336 // http://crbug.com/84719
337 #if defined(OS_LINUX)
338 #define MAYBE_ShutdownWhileCrashed DISABLED_ShutdownWhileCrashed
339 #else
340 #define MAYBE_ShutdownWhileCrashed ShutdownWhileCrashed
341 #endif  // defined(OS_LINUX)
342
343 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
344                        MAYBE_ShutdownWhileCrashed) {
345   const size_t count_before = GetEnabledExtensionCount();
346   LoadTestExtension();
347   CrashExtension(first_extension_id_);
348   ASSERT_EQ(count_before, GetEnabledExtensionCount());
349 }
350
351 // Flaky, http://crbug.com/241245.
352 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
353                        DISABLED_TwoExtensionsCrashFirst) {
354   const size_t count_before = GetEnabledExtensionCount();
355   LoadTestExtension();
356   LoadSecondExtension();
357   CrashExtension(first_extension_id_);
358   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
359   ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
360
361   SCOPED_TRACE("after clicking the balloon");
362   CheckExtensionConsistency(first_extension_id_);
363   CheckExtensionConsistency(second_extension_id_);
364 }
365
366 // Flaky: http://crbug.com/242196
367 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
368                        DISABLED_TwoExtensionsCrashSecond) {
369   const size_t count_before = GetEnabledExtensionCount();
370   LoadTestExtension();
371   LoadSecondExtension();
372   CrashExtension(second_extension_id_);
373   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
374   ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
375
376   SCOPED_TRACE("after clicking the balloon");
377   CheckExtensionConsistency(first_extension_id_);
378   CheckExtensionConsistency(second_extension_id_);
379 }
380
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();
385   LoadTestExtension();
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());
393
394   {
395     SCOPED_TRACE("first balloon");
396     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
397     CheckExtensionConsistency(first_extension_id_);
398   }
399
400   {
401     SCOPED_TRACE("second balloon");
402     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
403     CheckExtensionConsistency(first_extension_id_);
404     CheckExtensionConsistency(second_extension_id_);
405   }
406 }
407
408 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
409                        TwoExtensionsOneByOne) {
410   const size_t count_before = GetEnabledExtensionCount();
411   LoadTestExtension();
412   CrashExtension(first_extension_id_);
413   ASSERT_EQ(count_before, GetEnabledExtensionCount());
414   LoadSecondExtension();
415   CrashExtension(second_extension_id_);
416   ASSERT_EQ(count_before, GetEnabledExtensionCount());
417
418   {
419     SCOPED_TRACE("first balloon");
420     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
421     CheckExtensionConsistency(first_extension_id_);
422   }
423
424   {
425     SCOPED_TRACE("second balloon");
426     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
427     CheckExtensionConsistency(first_extension_id_);
428     CheckExtensionConsistency(second_extension_id_);
429   }
430 }
431
432 // http://crbug.com/84719
433 #if defined(OS_LINUX)
434 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
435     DISABLED_TwoExtensionsShutdownWhileCrashed
436 #else
437 #define MAYBE_TwoExtensionsShutdownWhileCrashed \
438     TwoExtensionsShutdownWhileCrashed
439 #endif  // defined(OS_LINUX)
440
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();
447   LoadTestExtension();
448   CrashExtension(first_extension_id_);
449   ASSERT_EQ(count_before, GetEnabledExtensionCount());
450   LoadSecondExtension();
451   CrashExtension(second_extension_id_);
452   ASSERT_EQ(count_before, GetEnabledExtensionCount());
453 }
454
455 // Flaky, http://crbug.com/241573.
456 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
457                        DISABLED_TwoExtensionsIgnoreFirst) {
458   const size_t count_before = GetEnabledExtensionCount();
459   LoadTestExtension();
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());
465
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));
471
472   SCOPED_TRACE("balloons done");
473   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
474   CheckExtensionConsistency(second_extension_id_);
475 }
476
477 // Flaky, http://crbug.com/241164.
478 IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
479                        DISABLED_TwoExtensionsReloadIndependently) {
480   const size_t count_before = GetEnabledExtensionCount();
481   LoadTestExtension();
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());
487
488   {
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_);
499   }
500
501   {
502     SCOPED_TRACE("second: balloon");
503     ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
504     CheckExtensionConsistency(first_extension_id_);
505     CheckExtensionConsistency(second_extension_id_);
506   }
507 }
508
509 // http://crbug.com/243648
510 #if defined(OS_WIN)
511 #define MAYBE_CrashAndUninstall DISABLED_CrashAndUninstall
512 #else
513 #define MAYBE_CrashAndUninstall CrashAndUninstall
514 #endif
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();
519   LoadTestExtension();
520   LoadSecondExtension();
521   CrashExtension(first_extension_id_);
522   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
523   ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
524
525   ASSERT_EQ(1U, CountBalloons());
526   UninstallExtension(first_extension_id_);
527   base::MessageLoop::current()->RunUntilIdle();
528
529   SCOPED_TRACE("after uninstalling");
530   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
531   ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
532   ASSERT_EQ(0U, CountBalloons());
533 }
534
535 // http://crbug.com/84719
536 #if defined(OS_LINUX)
537 #define MAYBE_CrashAndUnloadAll DISABLED_CrashAndUnloadAll
538 #else
539 #define MAYBE_CrashAndUnloadAll CrashAndUnloadAll
540 #endif  // defined(OS_LINUX)
541
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();
546   LoadTestExtension();
547   LoadSecondExtension();
548   CrashExtension(first_extension_id_);
549   ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
550   ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
551
552   GetExtensionService()->UnloadAllExtensionsForTest();
553   ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
554 }
555
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
560 #else
561 #define MAYBE_ReloadTabsWithBackgroundPage ReloadTabsWithBackgroundPage
562 #endif
563
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();
572   LoadTestExtension();
573
574   // Open a tab extension.
575   chrome::NewTab(browser());
576   ui_test_utils::NavigateToURL(
577       browser(),
578       GURL("chrome-extension://" + first_extension_id_ + "/background.html"));
579
580   const int tabs_before = tab_strip->count();
581   CrashExtension(first_extension_id_);
582
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());
587
588   {
589     content::WindowedNotificationObserver observer(
590         content::NOTIFICATION_LOAD_STOP,
591         content::Source<NavigationController>(
592             &browser()->tab_strip_model()->GetActiveWebContents()->
593                 GetController()));
594     chrome::Reload(browser(), CURRENT_TAB);
595     observer.Wait();
596   }
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());
602 }