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 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
131class 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.
164IN_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.
179IN_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)
203IN_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
231IN_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
261IN_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
301IN_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.
310IN_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
325IN_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
339IN_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
366IN_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.
402IN_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.
414IN_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.
436IN_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
473IN_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
500IN_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.
525IN_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}
562