Upstream version 9.38.198.0
[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/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
31 using content::NavigationController;
32 using content::WebContents;
33 using extensions::Extension;
34 using 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
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 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
131 class 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.
164 IN_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.
179 IN_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)
203 IN_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
231 IN_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
261 IN_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
301 IN_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.
310 IN_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
325 IN_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
339 IN_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
366 IN_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.
402 IN_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.
414 IN_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.
436 IN_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
473 IN_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
500 IN_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.
525 IN_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 }