extension_crash_recovery_browsertest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/browser_process.h"
6#include "chrome/browser/extensions/extension_browsertest.h"
7#include "chrome/browser/extensions/extension_service.h"
8#include "chrome/browser/notifications/notification.h"
9#include "chrome/browser/notifications/notification_delegate.h"
10#include "chrome/browser/notifications/notification_ui_manager.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_commands.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "chrome/test/base/ui_test_utils.h"
16#include "content/public/browser/navigation_controller.h"
17#include "content/public/browser/render_process_host.h"
18#include "content/public/browser/render_view_host.h"
19#include "content/public/browser/web_contents.h"
20#include "content/public/common/result_codes.h"
21#include "content/public/common/url_constants.h"
22#include "extensions/browser/extension_host.h"
23#include "extensions/browser/extension_registry.h"
24#include "extensions/browser/extension_system.h"
25#include "extensions/browser/process_manager.h"
26#include "extensions/browser/process_map.h"
27#include "extensions/common/constants.h"
28#include "ui/message_center/message_center.h"
29#include "ui/message_center/notification_list.h"
30
31using content::NavigationController;
32using content::WebContents;
33using extensions::Extension;
34using extensions::ExtensionRegistry;
35
36// Tests are timing out waiting for extension to crash.
37// http://crbug.com/174705
38#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
39#define MAYBE_ExtensionCrashRecoveryTest DISABLED_ExtensionCrashRecoveryTest
40#else
41#define MAYBE_ExtensionCrashRecoveryTest ExtensionCrashRecoveryTest
42#endif  // defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_LINUX)
43
44class ExtensionCrashRecoveryTestBase : public ExtensionBrowserTest {
45 protected:
46  virtual void AcceptNotification(size_t index) = 0;
47  virtual void CancelNotification(size_t index) = 0;
48  virtual size_t CountBalloons() = 0;
49
50  ExtensionService* GetExtensionService() {
51    return browser()->profile()->GetExtensionService();
52  }
53
54  extensions::ProcessManager* GetProcessManager() {
55    return extensions::ExtensionSystem::Get(browser()->profile())->
56        process_manager();
57  }
58
59  ExtensionRegistry* GetExtensionRegistry() {
60    return ExtensionRegistry::Get(browser()->profile());
61  }
62
63  size_t GetEnabledExtensionCount() {
64    return GetExtensionRegistry()->enabled_extensions().size();
65  }
66
67  size_t GetTerminatedExtensionCount() {
68    return GetExtensionRegistry()->terminated_extensions().size();
69  }
70
71  void CrashExtension(const std::string& extension_id) {
72    const Extension* extension = GetExtensionRegistry()->GetExtensionById(
73        extension_id, ExtensionRegistry::ENABLED);
74    ASSERT_TRUE(extension);
75    extensions::ExtensionHost* extension_host = GetProcessManager()->
76        GetBackgroundHostForExtension(extension_id);
77    ASSERT_TRUE(extension_host);
78
79    base::KillProcess(extension_host->render_process_host()->GetHandle(),
80                      content::RESULT_CODE_KILLED, false);
81    ASSERT_TRUE(WaitForExtensionCrash(extension_id));
82    ASSERT_FALSE(GetProcessManager()->
83                 GetBackgroundHostForExtension(extension_id));
84
85    // Wait for extension crash balloon to appear.
86    base::MessageLoop::current()->RunUntilIdle();
87  }
88
89  void CheckExtensionConsistency(const std::string& extension_id) {
90    const Extension* extension = GetExtensionRegistry()->GetExtensionById(
91        extension_id, ExtensionRegistry::ENABLED);
92    ASSERT_TRUE(extension);
93    extensions::ExtensionHost* extension_host = GetProcessManager()->
94        GetBackgroundHostForExtension(extension_id);
95    ASSERT_TRUE(extension_host);
96    extensions::ProcessManager::ViewSet all_views =
97        GetProcessManager()->GetAllViews();
98    extensions::ProcessManager::ViewSet::const_iterator it =
99        all_views.find(extension_host->host_contents()->GetRenderViewHost());
100    ASSERT_FALSE(it == all_views.end());
101    ASSERT_TRUE(extension_host->IsRenderViewLive());
102    extensions::ProcessMap* process_map =
103        extensions::ProcessMap::Get(browser()->profile());
104    ASSERT_TRUE(process_map->Contains(
105        extension_id,
106        extension_host->render_view_host()->GetProcess()->GetID()));
107  }
108
109  void LoadTestExtension() {
110    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
111    const Extension* extension = LoadExtension(
112        test_data_dir_.AppendASCII("common").AppendASCII("background_page"));
113    ASSERT_TRUE(extension);
114    first_extension_id_ = extension->id();
115    CheckExtensionConsistency(first_extension_id_);
116  }
117
118  void LoadSecondExtension() {
119    const Extension* extension = LoadExtension(
120        test_data_dir_.AppendASCII("install").AppendASCII("install"));
121    ASSERT_TRUE(extension);
122    second_extension_id_ = extension->id();
123    CheckExtensionConsistency(second_extension_id_);
124  }
125
126  std::string first_extension_id_;
127  std::string second_extension_id_;
128};
129
130class MAYBE_ExtensionCrashRecoveryTest
131    : 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++) { it++; }
153    ASSERT_TRUE(g_browser_process->notification_ui_manager()->
154        CancelById((*it)->id()));
155  }
156
157  virtual size_t CountBalloons() OVERRIDE {
158    return message_center::MessageCenter::Get()->NotificationCount();
159  }
160};
161
162// Flaky: http://crbug.com/242167.
163IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest, DISABLED_Basic) {
164  const size_t count_before = GetEnabledExtensionCount();
165  const size_t crash_count_before = GetTerminatedExtensionCount();
166  LoadTestExtension();
167  CrashExtension(first_extension_id_);
168  ASSERT_EQ(count_before, GetEnabledExtensionCount());
169  ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
170  ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
171
172  SCOPED_TRACE("after clicking the balloon");
173  CheckExtensionConsistency(first_extension_id_);
174  ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
175}
176
177// Flaky, http://crbug.com/241191.
178IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
179                       DISABLED_CloseAndReload) {
180  const size_t count_before = GetEnabledExtensionCount();
181  const size_t crash_count_before = GetTerminatedExtensionCount();
182  LoadTestExtension();
183  CrashExtension(first_extension_id_);
184
185  ASSERT_EQ(count_before, GetEnabledExtensionCount());
186  ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
187
188  ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
189  ReloadExtension(first_extension_id_);
190
191  SCOPED_TRACE("after reloading");
192  CheckExtensionConsistency(first_extension_id_);
193  ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
194}
195
196// Test is timing out on Windows http://crbug.com/174705.
197#if defined(OS_WIN)
198#define MAYBE_ReloadIndependently DISABLED_ReloadIndependently
199#else
200#define MAYBE_ReloadIndependently ReloadIndependently
201#endif  // defined(OS_WIN)
202IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
203                       MAYBE_ReloadIndependently) {
204  const size_t count_before = GetEnabledExtensionCount();
205  LoadTestExtension();
206  CrashExtension(first_extension_id_);
207  ASSERT_EQ(count_before, GetEnabledExtensionCount());
208
209  ReloadExtension(first_extension_id_);
210
211  SCOPED_TRACE("after reloading");
212  CheckExtensionConsistency(first_extension_id_);
213
214  WebContents* current_tab =
215      browser()->tab_strip_model()->GetActiveWebContents();
216  ASSERT_TRUE(current_tab);
217
218  // The balloon should automatically hide after the extension is successfully
219  // reloaded.
220  ASSERT_EQ(0U, CountBalloons());
221}
222
223// Test is timing out on Windows http://crbug.com/174705.
224#if defined(OS_WIN)
225#define MAYBE_ReloadIndependentlyChangeTabs DISABLED_ReloadIndependentlyChangeTabs
226#else
227#define MAYBE_ReloadIndependentlyChangeTabs ReloadIndependentlyChangeTabs
228#endif  // defined(OS_WIN)
229
230IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
231                       MAYBE_ReloadIndependentlyChangeTabs) {
232  const size_t count_before = GetEnabledExtensionCount();
233  LoadTestExtension();
234  CrashExtension(first_extension_id_);
235  ASSERT_EQ(count_before, GetEnabledExtensionCount());
236
237  WebContents* original_tab =
238      browser()->tab_strip_model()->GetActiveWebContents();
239  ASSERT_TRUE(original_tab);
240  ASSERT_EQ(1U, CountBalloons());
241
242  // Open a new tab, but the balloon will still be there.
243  chrome::NewTab(browser());
244  WebContents* new_current_tab =
245      browser()->tab_strip_model()->GetActiveWebContents();
246  ASSERT_TRUE(new_current_tab);
247  ASSERT_NE(new_current_tab, original_tab);
248  ASSERT_EQ(1U, CountBalloons());
249
250  ReloadExtension(first_extension_id_);
251
252  SCOPED_TRACE("after reloading");
253  CheckExtensionConsistency(first_extension_id_);
254
255  // The balloon should automatically hide after the extension is successfully
256  // reloaded.
257  ASSERT_EQ(0U, CountBalloons());
258}
259
260IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
261                       DISABLED_ReloadIndependentlyNavigatePage) {
262  const size_t count_before = GetEnabledExtensionCount();
263  LoadTestExtension();
264  CrashExtension(first_extension_id_);
265  ASSERT_EQ(count_before, GetEnabledExtensionCount());
266
267  WebContents* current_tab =
268      browser()->tab_strip_model()->GetActiveWebContents();
269  ASSERT_TRUE(current_tab);
270  ASSERT_EQ(1U, CountBalloons());
271
272  // Navigate to another page.
273  ui_test_utils::NavigateToURL(
274      browser(), ui_test_utils::GetTestUrl(
275                     base::FilePath(base::FilePath::kCurrentDirectory),
276                     base::FilePath(FILE_PATH_LITERAL("title1.html"))));
277  ASSERT_EQ(1U, CountBalloons());
278
279  ReloadExtension(first_extension_id_);
280
281  SCOPED_TRACE("after reloading");
282  CheckExtensionConsistency(first_extension_id_);
283
284  // The balloon should automatically hide after the extension is successfully
285  // reloaded.
286  ASSERT_EQ(0U, CountBalloons());
287}
288
289// Make sure that when we don't do anything about the crashed extension
290// and close the browser, it doesn't crash. The browser is closed implicitly
291// at the end of each browser test.
292//
293// http://crbug.com/84719
294#if defined(OS_LINUX)
295#define MAYBE_ShutdownWhileCrashed DISABLED_ShutdownWhileCrashed
296#else
297#define MAYBE_ShutdownWhileCrashed ShutdownWhileCrashed
298#endif  // defined(OS_LINUX)
299
300IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
301                       MAYBE_ShutdownWhileCrashed) {
302  const size_t count_before = GetEnabledExtensionCount();
303  LoadTestExtension();
304  CrashExtension(first_extension_id_);
305  ASSERT_EQ(count_before, GetEnabledExtensionCount());
306}
307
308// Flaky, http://crbug.com/241245.
309IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
310                       DISABLED_TwoExtensionsCrashFirst) {
311  const size_t count_before = GetEnabledExtensionCount();
312  LoadTestExtension();
313  LoadSecondExtension();
314  CrashExtension(first_extension_id_);
315  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
316  ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
317
318  SCOPED_TRACE("after clicking the balloon");
319  CheckExtensionConsistency(first_extension_id_);
320  CheckExtensionConsistency(second_extension_id_);
321}
322
323// Flaky: http://crbug.com/242196
324IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
325                       DISABLED_TwoExtensionsCrashSecond) {
326  const size_t count_before = GetEnabledExtensionCount();
327  LoadTestExtension();
328  LoadSecondExtension();
329  CrashExtension(second_extension_id_);
330  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
331  ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
332
333  SCOPED_TRACE("after clicking the balloon");
334  CheckExtensionConsistency(first_extension_id_);
335  CheckExtensionConsistency(second_extension_id_);
336}
337
338IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
339                       TwoExtensionsCrashBothAtOnce) {
340  const size_t count_before = GetEnabledExtensionCount();
341  const size_t crash_count_before = GetTerminatedExtensionCount();
342  LoadTestExtension();
343  LoadSecondExtension();
344  CrashExtension(first_extension_id_);
345  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
346  ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
347  CrashExtension(second_extension_id_);
348  ASSERT_EQ(count_before, GetEnabledExtensionCount());
349  ASSERT_EQ(crash_count_before + 2, GetTerminatedExtensionCount());
350
351  {
352    SCOPED_TRACE("first balloon");
353    ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
354    CheckExtensionConsistency(first_extension_id_);
355  }
356
357  {
358    SCOPED_TRACE("second balloon");
359    ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
360    CheckExtensionConsistency(first_extension_id_);
361    CheckExtensionConsistency(second_extension_id_);
362  }
363}
364
365IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
366                       TwoExtensionsOneByOne) {
367  const size_t count_before = GetEnabledExtensionCount();
368  LoadTestExtension();
369  CrashExtension(first_extension_id_);
370  ASSERT_EQ(count_before, GetEnabledExtensionCount());
371  LoadSecondExtension();
372  CrashExtension(second_extension_id_);
373  ASSERT_EQ(count_before, GetEnabledExtensionCount());
374
375  {
376    SCOPED_TRACE("first balloon");
377    ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
378    CheckExtensionConsistency(first_extension_id_);
379  }
380
381  {
382    SCOPED_TRACE("second balloon");
383    ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
384    CheckExtensionConsistency(first_extension_id_);
385    CheckExtensionConsistency(second_extension_id_);
386  }
387}
388
389// http://crbug.com/84719
390#if defined(OS_LINUX)
391#define MAYBE_TwoExtensionsShutdownWhileCrashed \
392    DISABLED_TwoExtensionsShutdownWhileCrashed
393#else
394#define MAYBE_TwoExtensionsShutdownWhileCrashed \
395    TwoExtensionsShutdownWhileCrashed
396#endif  // defined(OS_LINUX)
397
398// Make sure that when we don't do anything about the crashed extensions
399// and close the browser, it doesn't crash. The browser is closed implicitly
400// at the end of each browser test.
401IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
402                       MAYBE_TwoExtensionsShutdownWhileCrashed) {
403  const size_t count_before = GetEnabledExtensionCount();
404  LoadTestExtension();
405  CrashExtension(first_extension_id_);
406  ASSERT_EQ(count_before, GetEnabledExtensionCount());
407  LoadSecondExtension();
408  CrashExtension(second_extension_id_);
409  ASSERT_EQ(count_before, GetEnabledExtensionCount());
410}
411
412// Flaky, http://crbug.com/241573.
413IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
414                       DISABLED_TwoExtensionsIgnoreFirst) {
415  const size_t count_before = GetEnabledExtensionCount();
416  LoadTestExtension();
417  LoadSecondExtension();
418  CrashExtension(first_extension_id_);
419  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
420  CrashExtension(second_extension_id_);
421  ASSERT_EQ(count_before, GetEnabledExtensionCount());
422
423  // Accept notification 1 before canceling notification 0.
424  // Otherwise, on Linux and Windows, there is a race here, in which
425  // canceled notifications do not immediately go away.
426  ASSERT_NO_FATAL_FAILURE(AcceptNotification(1));
427  ASSERT_NO_FATAL_FAILURE(CancelNotification(0));
428
429  SCOPED_TRACE("balloons done");
430  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
431  CheckExtensionConsistency(second_extension_id_);
432}
433
434// Flaky, http://crbug.com/241164.
435IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
436                       DISABLED_TwoExtensionsReloadIndependently) {
437  const size_t count_before = GetEnabledExtensionCount();
438  LoadTestExtension();
439  LoadSecondExtension();
440  CrashExtension(first_extension_id_);
441  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
442  CrashExtension(second_extension_id_);
443  ASSERT_EQ(count_before, GetEnabledExtensionCount());
444
445  {
446    SCOPED_TRACE("first: reload");
447    WebContents* current_tab =
448        browser()->tab_strip_model()->GetActiveWebContents();
449    ASSERT_TRUE(current_tab);
450    // At the beginning we should have one balloon displayed for each extension.
451    ASSERT_EQ(2U, CountBalloons());
452    ReloadExtension(first_extension_id_);
453    // One of the balloons should hide after the extension is reloaded.
454    ASSERT_EQ(1U, CountBalloons());
455    CheckExtensionConsistency(first_extension_id_);
456  }
457
458  {
459    SCOPED_TRACE("second: balloon");
460    ASSERT_NO_FATAL_FAILURE(AcceptNotification(0));
461    CheckExtensionConsistency(first_extension_id_);
462    CheckExtensionConsistency(second_extension_id_);
463  }
464}
465
466// http://crbug.com/243648
467#if defined(OS_WIN)
468#define MAYBE_CrashAndUninstall DISABLED_CrashAndUninstall
469#else
470#define MAYBE_CrashAndUninstall CrashAndUninstall
471#endif
472IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
473                       MAYBE_CrashAndUninstall) {
474  const size_t count_before = GetEnabledExtensionCount();
475  const size_t crash_count_before = GetTerminatedExtensionCount();
476  LoadTestExtension();
477  LoadSecondExtension();
478  CrashExtension(first_extension_id_);
479  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
480  ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
481
482  ASSERT_EQ(1U, CountBalloons());
483  UninstallExtension(first_extension_id_);
484  base::MessageLoop::current()->RunUntilIdle();
485
486  SCOPED_TRACE("after uninstalling");
487  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
488  ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
489  ASSERT_EQ(0U, CountBalloons());
490}
491
492// http://crbug.com/84719
493#if defined(OS_LINUX)
494#define MAYBE_CrashAndUnloadAll DISABLED_CrashAndUnloadAll
495#else
496#define MAYBE_CrashAndUnloadAll CrashAndUnloadAll
497#endif  // defined(OS_LINUX)
498
499IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
500                       MAYBE_CrashAndUnloadAll) {
501  const size_t count_before = GetEnabledExtensionCount();
502  const size_t crash_count_before = GetTerminatedExtensionCount();
503  LoadTestExtension();
504  LoadSecondExtension();
505  CrashExtension(first_extension_id_);
506  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
507  ASSERT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
508
509  GetExtensionService()->UnloadAllExtensionsForTest();
510  ASSERT_EQ(crash_count_before, GetTerminatedExtensionCount());
511}
512
513// Fails a DCHECK on Aura and Linux: http://crbug.com/169622
514// Failing on Windows: http://crbug.com/232340
515#if defined(USE_AURA)
516#define MAYBE_ReloadTabsWithBackgroundPage DISABLED_ReloadTabsWithBackgroundPage
517#else
518#define MAYBE_ReloadTabsWithBackgroundPage ReloadTabsWithBackgroundPage
519#endif
520
521// Test that when an extension with a background page that has a tab open
522// crashes, the tab stays open, and reloading it reloads the extension.
523// Regression test for issue 71629.
524IN_PROC_BROWSER_TEST_F(MAYBE_ExtensionCrashRecoveryTest,
525                       MAYBE_ReloadTabsWithBackgroundPage) {
526  TabStripModel* tab_strip = browser()->tab_strip_model();
527  const size_t count_before = GetEnabledExtensionCount();
528  const size_t crash_count_before = GetTerminatedExtensionCount();
529  LoadTestExtension();
530
531  // Open a tab extension.
532  chrome::NewTab(browser());
533  ui_test_utils::NavigateToURL(browser(),
534                               GURL(std::string(extensions::kExtensionScheme) +
535                                   url::kStandardSchemeSeparator +
536                                   first_extension_id_ + "/background.html"));
537
538  const int tabs_before = tab_strip->count();
539  CrashExtension(first_extension_id_);
540
541  // Tab should still be open, and extension should be crashed.
542  EXPECT_EQ(tabs_before, tab_strip->count());
543  EXPECT_EQ(count_before, GetEnabledExtensionCount());
544  EXPECT_EQ(crash_count_before + 1, GetTerminatedExtensionCount());
545
546  {
547    content::WindowedNotificationObserver observer(
548        content::NOTIFICATION_LOAD_STOP,
549        content::Source<NavigationController>(
550            &browser()->tab_strip_model()->GetActiveWebContents()->
551                GetController()));
552    chrome::Reload(browser(), CURRENT_TAB);
553    observer.Wait();
554  }
555  // Extension should now be loaded.
556  SCOPED_TRACE("after reloading the tab");
557  CheckExtensionConsistency(first_extension_id_);
558  ASSERT_EQ(count_before + 1, GetEnabledExtensionCount());
559  ASSERT_EQ(0U, CountBalloons());
560}
561