- add sources.
[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_host.h"
8 #include "chrome/browser/extensions/extension_process_manager.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_system.h"
11 #include "chrome/browser/notifications/balloon.h"
12 #include "chrome/browser/notifications/balloon_collection.h"
13 #include "chrome/browser/notifications/balloon_host.h"
14 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
15 #include "chrome/browser/notifications/notification.h"
16 #include "chrome/browser/notifications/notification_delegate.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/browser/navigation_controller.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/common/result_codes.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   ExtensionProcessManager* GetExtensionProcessManager() {
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 = GetExtensionProcessManager()->
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(GetExtensionProcessManager()->
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 = GetExtensionProcessManager()->
82         GetBackgroundHostForExtension(extension_id);
83     ASSERT_TRUE(extension_host);
84     ExtensionProcessManager::ViewSet all_views =
85         GetExtensionProcessManager()->GetAllViews();
86     ExtensionProcessManager::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 }