Add C++ fixture for extension settings browser test

BUG=

Review URL: https://codereview.chromium.org/22791012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229959 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
index dbc714a..e17de51 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -191,7 +191,7 @@
   CheckContentSettingsSet();
 
   // The settings should not be reset when the extension is reloaded.
-  ReloadExtension(last_loaded_extension_id_);
+  ReloadExtension(last_loaded_extension_id());
   CheckContentSettingsSet();
 
   // Uninstalling and installing the extension (without running the test that
@@ -199,7 +199,7 @@
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
       content::NotificationService::AllSources());
-  UninstallExtension(last_loaded_extension_id_);
+  UninstallExtension(last_loaded_extension_id());
   observer.Wait();
   CheckContentSettingsDefault();
 
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index a6708db..6d4cdd3 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -179,7 +179,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   ASSERT_FALSE(PermissionsData::HasAPIPermissionForTab(
-      service->GetExtensionById(last_loaded_extension_id_, false),
+      service->GetExtensionById(last_loaded_extension_id(), false),
       SessionID::IdForTab(browser()->tab_strip_model()->GetActiveWebContents()),
       APIPermission::kTab));
 }
diff --git a/chrome/browser/extensions/api/management/management_apitest.cc b/chrome/browser/extensions/api/management/management_apitest.cc
index 0dc2545..3a0fccb 100644
--- a/chrome/browser/extensions/api/management/management_apitest.cc
+++ b/chrome/browser/extensions/api/management/management_apitest.cc
@@ -70,7 +70,7 @@
     ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path)));
 
     if (out_app_id)
-      *out_app_id = last_loaded_extension_id_;
+      *out_app_id = last_loaded_extension_id();
 
     ASSERT_TRUE(launched_app.WaitUntilSatisfied());
   }
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc
index bbb4cab..6e0bcb3 100644
--- a/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -111,7 +111,7 @@
   CheckPreferencesSet();
 
   // The settings should not be reset when the extension is reloaded.
-  ReloadExtension(last_loaded_extension_id_);
+  ReloadExtension(last_loaded_extension_id());
   CheckPreferencesSet();
 
   // Uninstalling and installing the extension (without running the test that
@@ -119,7 +119,7 @@
   content::WindowedNotificationObserver observer(
       chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
       content::NotificationService::AllSources());
-  UninstallExtension(last_loaded_extension_id_);
+  UninstallExtension(last_loaded_extension_id());
   observer.Wait();
   CheckPreferencesCleared();
 
diff --git a/chrome/browser/extensions/api/processes/processes_apitest.cc b/chrome/browser/extensions/api/processes/processes_apitest.cc
index f6e1f0a2..db840e1 100644
--- a/chrome/browser/extensions/api/processes/processes_apitest.cc
+++ b/chrome/browser/extensions/api/processes/processes_apitest.cc
@@ -50,7 +50,7 @@
   EXPECT_EQ(TaskManagerModel::TASK_PENDING, model->update_state_);
 
   // Unload the extension and check that listener count decreases
-  UnloadExtension(last_loaded_extension_id_);
+  UnloadExtension(last_loaded_extension_id());
   EXPECT_EQ(1, model->update_requests_);
 }
 
diff --git a/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc b/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc
index 616fad4..5b923ca 100644
--- a/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc
+++ b/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc
@@ -60,7 +60,7 @@
     // Lazy Background Page has been shut down.
     ExtensionProcessManager* pm =
         extensions::ExtensionSystem::Get(profile())->process_manager();
-    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
     EXPECT_TRUE(manager->SendClickEventToExtensionForTest(extension->id()));
     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index df18d25..fd11692 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -533,7 +533,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
   GURL url = extension->GetResourceURL("userAction/a.html");
 
   ui_test_utils::NavigateToURL(browser(), url);
@@ -575,7 +575,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
   GURL url = extension->GetResourceURL("requestOpenTab/a.html");
 
   ui_test_utils::NavigateToURL(browser(), url);
@@ -687,7 +687,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
 
   // See crossProcess/d.html.
   DelayLoadStartAndExecuteJavascript call_script(
@@ -709,7 +709,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
 
   // See crossProcess/f.html.
   DelayLoadStartAndExecuteJavascript call_script3(
@@ -742,7 +742,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
 
   // See crossProcess/e.html.
   DelayLoadStartAndExecuteJavascript call_script2(
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 05de8d8..67d8623 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -135,7 +135,7 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   const extensions::Extension* extension =
-      service->GetExtensionById(last_loaded_extension_id_, false);
+      service->GetExtensionById(last_loaded_extension_id(), false);
   GURL url = extension->GetResourceURL("newTab/a.html");
 
   ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index a916842..d9c7114c 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -365,7 +365,8 @@
     }
 
     crx_installer->InstallCrx(test_data_dir_.AppendASCII("good.crx"));
-    EXPECT_EQ(kTestData[i], WaitForExtensionInstall()) << kTestData[i];
+    EXPECT_EQ(kTestData[i],
+              WaitForExtensionInstall()) << kTestData[i];
     EXPECT_EQ(kTestData[i], mock_prompt->did_succeed());
     EXPECT_EQ(kTestData[i], mock_prompt->confirmation_requested()) <<
         kTestData[i];
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index f0b3914..0d6fd91e 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/omnibox/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -55,38 +54,19 @@
 using extensions::FeatureSwitch;
 using extensions::Manifest;
 
-namespace {
-
-bool HasExtensionPageActionCountReachedTarget(LocationBarTesting* location_bar,
-                                              int target_page_action_count) {
-  VLOG(1) << "Number of page actions: " << location_bar->PageActionCount();
-  return location_bar->PageActionCount() == target_page_action_count;
-}
-
-bool HasExtensionPageActionVisibilityReachedTarget(
-    LocationBarTesting* location_bar,
-    int target_visible_page_action_count) {
-  VLOG(1) << "Number of visible page actions: "
-          << location_bar->PageActionVisibleCount();
-  return location_bar->PageActionVisibleCount() ==
-         target_visible_page_action_count;
-}
-
-}  // namespace
-
 ExtensionBrowserTest::ExtensionBrowserTest()
     : loaded_(false),
       installed_(false),
-      extension_installs_observed_(0),
-      extension_load_errors_observed_(0),
       current_channel_(chrome::VersionInfo::CHANNEL_DEV),
       override_prompt_for_external_extensions_(
-          FeatureSwitch::prompt_for_external_extensions(), false),
+          FeatureSwitch::prompt_for_external_extensions(),
+          false),
       profile_(NULL) {
   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
 }
 
-ExtensionBrowserTest::~ExtensionBrowserTest() {}
+ExtensionBrowserTest::~ExtensionBrowserTest() {
+}
 
 Profile* ExtensionBrowserTest::profile() {
   if (!profile_) {
@@ -115,6 +95,7 @@
 void ExtensionBrowserTest::SetUpCommandLine(CommandLine* command_line) {
   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
   test_data_dir_ = test_data_dir_.AppendASCII("extensions");
+  observer_.reset(new ExtensionTestNotificationObserver(browser()));
 
 #if defined(OS_CHROMEOS)
   // This makes sure that we create the Default profile first, with no
@@ -128,6 +109,7 @@
 
 void ExtensionBrowserTest::SetUpOnMainThread() {
   InProcessBrowserTest::SetUpOnMainThread();
+  observer_.reset(new ExtensionTestNotificationObserver(browser()));
 }
 
 const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
@@ -135,23 +117,21 @@
   ExtensionService* service = extensions::ExtensionSystem::Get(
       profile())->extension_service();
   {
-    content::WindowedNotificationObserver observer(
-        chrome::NOTIFICATION_EXTENSION_LOADED,
-        content::NotificationService::AllSources());
-    content::NotificationRegistrar registrar;
-    registrar.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
-                  content::NotificationService::AllSources());
+    observer_->Watch(chrome::NOTIFICATION_EXTENSION_LOADED,
+                     content::NotificationService::AllSources());
+
     scoped_refptr<extensions::UnpackedInstaller> installer(
         extensions::UnpackedInstaller::Create(service));
     installer->set_prompt_for_plugins(false);
     installer->set_require_modern_manifest_version(
         (flags & kFlagAllowOldManifestVersions) == 0);
     installer->Load(path);
-    observer.Wait();
+
+    observer_->Wait();
   }
 
   // Find the loaded extension by its path. See crbug.com/59531 for why
-  // we cannot just use last_loaded_extension_id_.
+  // we cannot just use last_loaded_extension_id().
   const Extension* extension = GetExtensionByPath(service->extensions(), path);
   if (!extension)
     return NULL;
@@ -217,7 +197,7 @@
     }
   }
 
-  if (!WaitForExtensionViewsToLoad())
+  if (!observer_->WaitForExtensionViewsToLoad())
     return NULL;
 
   return extension;
@@ -249,7 +229,7 @@
   const Extension* extension = service->extensions()->GetByID(extension_id);
   if (!extension)
     return NULL;
-  last_loaded_extension_id_ = extension->id();
+  observer_->set_last_loaded_extension_id(extension->id());
   return extension;
 }
 
@@ -457,16 +437,13 @@
           extensions::CrxInstaller::OffStoreInstallAllowedInTest);
     }
 
-    content::WindowedNotificationObserver observer(
+    observer_->Watch(
         chrome::NOTIFICATION_CRX_INSTALLER_DONE,
         content::Source<extensions::CrxInstaller>(installer.get()));
-    content::NotificationRegistrar registrar;
-    registrar.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
-                  content::Source<extensions::CrxInstaller>(installer.get()));
 
     installer->InstallCrx(crx_path);
 
-    observer.Wait();
+    observer_->Wait();
   }
 
   size_t num_after = service->extensions()->size();
@@ -490,24 +467,21 @@
     return NULL;
   }
 
-  if (!WaitForExtensionViewsToLoad())
+  if (!observer_->WaitForExtensionViewsToLoad())
     return NULL;
-  return service->GetExtensionById(last_loaded_extension_id_, false);
+  return service->GetExtensionById(last_loaded_extension_id(), false);
 }
 
 void ExtensionBrowserTest::ReloadExtension(const std::string extension_id) {
-  content::WindowedNotificationObserver observer(
-      chrome::NOTIFICATION_EXTENSION_LOADED,
-      content::NotificationService::AllSources());
-  content::NotificationRegistrar registrar;
-  registrar.Add(this,
-                chrome::NOTIFICATION_EXTENSION_LOADED,
+  observer_->Watch(chrome::NOTIFICATION_EXTENSION_LOADED,
                 content::NotificationService::AllSources());
+
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile())->extension_service();
   service->ReloadExtension(extension_id);
-  observer.Wait();
-  WaitForExtensionViewsToLoad();
+
+  observer_->Wait();
+  observer_->WaitForExtensionViewsToLoad();
 }
 
 void ExtensionBrowserTest::UnloadExtension(const std::string& extension_id) {
@@ -534,126 +508,11 @@
   service->EnableExtension(extension_id);
 }
 
-bool ExtensionBrowserTest::WaitForPageActionCountChangeTo(int count) {
-  LocationBarTesting* location_bar =
-      browser()->window()->GetLocationBar()->GetLocationBarForTesting();
-  if (!HasExtensionPageActionCountReachedTarget(location_bar, count)) {
-    content::WindowedNotificationObserver(
-        chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
-        base::Bind(
-            &HasExtensionPageActionCountReachedTarget, location_bar, count))
-        .Wait();
-  }
-  return HasExtensionPageActionCountReachedTarget(location_bar, count);
-}
-
-bool ExtensionBrowserTest::WaitForPageActionVisibilityChangeTo(int count) {
-  LocationBarTesting* location_bar =
-      browser()->window()->GetLocationBar()->GetLocationBarForTesting();
-  if (!HasExtensionPageActionVisibilityReachedTarget(location_bar, count)) {
-    content::WindowedNotificationObserver(
-        chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
-        base::Bind(&HasExtensionPageActionVisibilityReachedTarget,
-                   location_bar,
-                   count))
-        .Wait();
-  }
-  return HasExtensionPageActionVisibilityReachedTarget(location_bar, count);
-}
-
-void ExtensionBrowserTest::WaitForNotification(int notification_type) {
-  // TODO(bauerb): Using a WindowedNotificationObserver like this can break
-  // easily, if the notification we're waiting for is sent before this method.
-  // Change it so that the WindowedNotificationObserver is constructed earlier.
-  content::NotificationRegistrar registrar;
-  registrar.Add(this, notification_type,
-                content::NotificationService::AllSources());
-  content::WindowedNotificationObserver(
-      notification_type, content::NotificationService::AllSources()).Wait();
-}
-
-bool ExtensionBrowserTest::WaitForExtensionViewsToLoad() {
-
-  ExtensionProcessManager* manager =
-      extensions::ExtensionSystem::Get(profile())->process_manager();
-  ExtensionProcessManager::ViewSet all_views = manager->GetAllViews();
-  for (ExtensionProcessManager::ViewSet::const_iterator iter =
-           all_views.begin();
-       iter != all_views.end();) {
-    if (!(*iter)->IsLoading()) {
-      ++iter;
-    } else {
-      // Wait for all the extension render view hosts that exist to finish
-      // loading.
-      content::WindowedNotificationObserver observer(
-          content::NOTIFICATION_LOAD_STOP,
-          content::NotificationService::AllSources());
-      observer.AddNotificationType(
-          content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
-          content::NotificationService::AllSources());
-      observer.Wait();
-
-      // Test activity may have modified the set of extension processes during
-      // message processing, so re-start the iteration to catch added/removed
-      // processes.
-      all_views = manager->GetAllViews();
-      iter = all_views.begin();
-    }
-  }
-  return true;
-}
-
-bool ExtensionBrowserTest::WaitForExtensionInstall() {
-  int before = extension_installs_observed_;
-  WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED);
-  return extension_installs_observed_ == (before + 1);
-}
-
-bool ExtensionBrowserTest::WaitForExtensionInstallError() {
-  int before = extension_installs_observed_;
-  content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
-      content::NotificationService::AllSources()).Wait();
-  return extension_installs_observed_ == before;
-}
-
-void ExtensionBrowserTest::WaitForExtensionLoad() {
-  WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOADED);
-  WaitForExtensionViewsToLoad();
-}
-
-bool ExtensionBrowserTest::WaitForExtensionLoadError() {
-  int before = extension_load_errors_observed_;
-  WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOAD_ERROR);
-  return extension_load_errors_observed_ != before;
-}
-
-bool ExtensionBrowserTest::WaitForExtensionCrash(
-    const std::string& extension_id) {
-  ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile())->extension_service();
-
-  if (!service->GetExtensionById(extension_id, true)) {
-    // The extension is already unloaded, presumably due to a crash.
-    return true;
-  }
-  content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
-      content::NotificationService::AllSources()).Wait();
-  return (service->GetExtensionById(extension_id, true) == NULL);
-}
-
-bool ExtensionBrowserTest::WaitForCrxInstallerDone() {
-  int before = crx_installers_done_observed_;
-  WaitForNotification(chrome::NOTIFICATION_CRX_INSTALLER_DONE);
-  return crx_installers_done_observed_ == (before + 1);
-}
-
 void ExtensionBrowserTest::OpenWindow(content::WebContents* contents,
                                       const GURL& url,
                                       bool newtab_process_should_equal_opener,
                                       content::WebContents** newtab_result) {
-  content::WindowedNotificationObserver observer(
+  content::WindowedNotificationObserver windowed_observer(
       content::NOTIFICATION_LOAD_STOP,
       content::NotificationService::AllSources());
   ASSERT_TRUE(content::ExecuteScript(contents,
@@ -662,9 +521,10 @@
   // The above window.open call is not user-initiated, so it will create
   // a popup window instead of a new tab in current window.
   // The stop notification will come from the new tab.
-  observer.Wait();
+  windowed_observer.Wait();
   content::NavigationController* controller =
-      content::Source<content::NavigationController>(observer.source()).ptr();
+      content::Source<content::NavigationController>(
+          windowed_observer.source()).ptr();
   content::WebContents* newtab = controller->GetWebContents();
   ASSERT_TRUE(newtab);
   EXPECT_EQ(url, controller->GetLastCommittedEntry()->GetURL());
@@ -680,7 +540,7 @@
 void ExtensionBrowserTest::NavigateInRenderer(content::WebContents* contents,
                                               const GURL& url) {
   bool result = false;
-  content::WindowedNotificationObserver observer(
+  content::WindowedNotificationObserver windowed_observer(
       content::NOTIFICATION_LOAD_STOP,
       content::NotificationService::AllSources());
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
@@ -691,7 +551,7 @@
       "window.location = '" + url.spec() + "';",
       &result));
   ASSERT_TRUE(result);
-  observer.Wait();
+  windowed_observer.Wait();
   EXPECT_EQ(url, contents->GetController().GetLastCommittedEntry()->GetURL());
 }
 
@@ -721,43 +581,3 @@
   return extensions::browsertest_util::ExecuteScriptInBackgroundPage(
       profile(), extension_id, script);
 }
-
-void ExtensionBrowserTest::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_EXTENSION_LOADED:
-      last_loaded_extension_id_ =
-          content::Details<const Extension>(details).ptr()->id();
-      VLOG(1) << "Got EXTENSION_LOADED notification.";
-      break;
-
-    case chrome::NOTIFICATION_CRX_INSTALLER_DONE:
-      VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
-      {
-        const Extension* extension =
-            content::Details<const Extension>(details).ptr();
-        if (extension)
-          last_loaded_extension_id_ = extension->id();
-        else
-          last_loaded_extension_id_.clear();
-      }
-      ++crx_installers_done_observed_;
-      break;
-
-    case chrome::NOTIFICATION_EXTENSION_INSTALLED:
-      VLOG(1) << "Got EXTENSION_INSTALLED notification.";
-      ++extension_installs_observed_;
-      break;
-
-    case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR:
-      VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
-      ++extension_load_errors_observed_;
-      break;
-
-    default:
-      NOTREACHED();
-      break;
-  }
-}
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 5e21e63..ff930ea 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -8,19 +8,17 @@
 #include <string>
 
 #include "base/command_line.h"
-#include "base/compiler_specific.h"
+
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_test_notification_observer.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/feature_switch.h"
 #include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/manifest.h"
 
@@ -31,8 +29,7 @@
 
 // Base class for extension browser tests. Provides utilities for loading,
 // unloading, and installing extensions.
-class ExtensionBrowserTest : virtual public InProcessBrowserTest,
-                             public content::NotificationObserver {
+class ExtensionBrowserTest : virtual public InProcessBrowserTest {
  protected:
   // Flags used to configure how the tests are run.
   enum Flags {
@@ -61,6 +58,10 @@
     return extensions::ExtensionSystem::Get(profile())->extension_service();
   }
 
+  const std::string& last_loaded_extension_id() {
+    return observer_->last_loaded_extension_id();
+  }
+
   // Get the profile to use.
   Profile* profile();
 
@@ -194,35 +195,58 @@
   void EnableExtension(const std::string& extension_id);
 
   // Wait for the total number of page actions to change to |count|.
-  bool WaitForPageActionCountChangeTo(int count);
+  bool WaitForPageActionCountChangeTo(int count) {
+    return observer_->WaitForPageActionCountChangeTo(count);
+  }
 
   // Wait for the number of visible page actions to change to |count|.
-  bool WaitForPageActionVisibilityChangeTo(int count);
+  bool WaitForPageActionVisibilityChangeTo(int count) {
+    return observer_->WaitForPageActionVisibilityChangeTo(count);
+  }
 
   // Waits until an extension is installed and loaded. Returns true if an
   // install happened before timeout.
-  bool WaitForExtensionInstall();
+  bool WaitForExtensionInstall() {
+    return observer_->WaitForExtensionInstall();
+  }
 
   // Wait for an extension install error to be raised. Returns true if an
   // error was raised.
-  bool WaitForExtensionInstallError();
+  bool WaitForExtensionInstallError() {
+    return observer_->WaitForExtensionInstallError();
+  }
+
+  // Waits until an extension is loaded and all view have loaded.
+  void WaitForExtensionAndViewLoad() {
+    return observer_->WaitForExtensionAndViewLoad();
+  }
 
   // Waits until an extension is loaded.
-  void WaitForExtensionLoad();
+  void WaitForExtensionLoad() {
+    return observer_->WaitForExtensionLoad();
+  }
 
   // Waits for an extension load error. Returns true if the error really
   // happened.
-  bool WaitForExtensionLoadError();
+  bool WaitForExtensionLoadError() {
+    return observer_->WaitForExtensionLoadError();
+  }
 
   // Wait for the specified extension to crash. Returns true if it really
   // crashed.
-  bool WaitForExtensionCrash(const std::string& extension_id);
+  bool WaitForExtensionCrash(const std::string& extension_id) {
+    return observer_->WaitForExtensionCrash(extension_id);
+  }
 
   // Wait for the crx installer to be done. Returns true if it really is done.
-  bool WaitForCrxInstallerDone();
+  bool WaitForCrxInstallerDone() {
+    return observer_->WaitForCrxInstallerDone();
+  }
 
   // Wait for all extension views to load.
-  bool WaitForExtensionViewsToLoad();
+  bool WaitForExtensionViewsToLoad() {
+    return observer_->WaitForExtensionViewsToLoad();
+  }
 
   // Simulates a page calling window.open on an URL and waits for the
   // navigation.
@@ -241,27 +265,19 @@
   extensions::ExtensionHost* FindHostWithPath(ExtensionProcessManager* manager,
                                               const std::string& path,
                                               int expected_hosts);
-
   // Returns
   // extensions::browsertest_util::ExecuteScriptInBackgroundPage(profile(),
   // extension_id, script).
   std::string ExecuteScriptInBackgroundPage(const std::string& extension_id,
                                             const std::string& script);
 
-  // content::NotificationObserver
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
   bool loaded_;
   bool installed_;
 
   // test_data/extensions.
   base::FilePath test_data_dir_;
-  std::string last_loaded_extension_id_;
-  int extension_installs_observed_;
-  int extension_load_errors_observed_;
-  int crx_installers_done_observed_;
+
+  scoped_ptr<ExtensionTestNotificationObserver> observer_;
 
  private:
   // Temporary directory for testing.
@@ -304,10 +320,6 @@
       extensions::Extension::InitFromValueFlags creation_flags,
       bool wait_for_idle);
 
-  // Wait for a notification of the specified type to be sent.
-  // |notification_type| must be a type that this class handles in Observe().
-  void WaitForNotification(int notification_type);
-
   // Make the current channel "dev" for the duration of the test.
   extensions::ScopedCurrentChannel current_channel_;
 
diff --git a/chrome/browser/extensions/extension_functional_browsertest.cc b/chrome/browser/extensions/extension_functional_browsertest.cc
index 78bc098..cf43c56 100644
--- a/chrome/browser/extensions/extension_functional_browsertest.cc
+++ b/chrome/browser/extensions/extension_functional_browsertest.cc
@@ -35,22 +35,19 @@
     installer->set_off_store_install_allow_reason(
         extensions::CrxInstaller::OffStoreInstallAllowedInTest);
 
-    content::WindowedNotificationObserver observer(
+    observer_->Watch(
         chrome::NOTIFICATION_CRX_INSTALLER_DONE,
         content::Source<extensions::CrxInstaller>(installer.get()));
-    content::NotificationRegistrar registrar;
-    registrar.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
-                  content::Source<extensions::CrxInstaller>(installer.get()));
 
     installer->InstallCrx(path);
-    observer.Wait();
+    observer_->Wait();
 
     size_t num_after = service->extensions()->size();
     EXPECT_EQ(num_before + 1, num_after);
 
     extension_loaded_observer.Wait();
     const Extension* extension = service->GetExtensionById(
-        last_loaded_extension_id_, false);
+        last_loaded_extension_id(), false);
     EXPECT_TRUE(extension != NULL);
   }
 };
@@ -65,9 +62,9 @@
   ExtensionService* service = profile()->GetExtensionService();
   // Verify that the extension is enabled and allowed in incognito
   // is disabled.
-  EXPECT_TRUE(service->IsExtensionEnabled(last_loaded_extension_id_));
-  EXPECT_FALSE(extension_util::IsIncognitoEnabled(last_loaded_extension_id_,
-                                                  service));
+  EXPECT_TRUE(service->IsExtensionEnabled(last_loaded_extension_id()));
+  EXPECT_FALSE(
+      extension_util::IsIncognitoEnabled(last_loaded_extension_id(), service));
 }
 
 IN_PROC_BROWSER_TEST_F(ExtensionFunctionalTest, TestSetExtensionsState) {
@@ -76,29 +73,29 @@
 
   // Disable the extension and verify.
   extension_util::SetIsIncognitoEnabled(
-      last_loaded_extension_id_, service, false);
-  service->DisableExtension(last_loaded_extension_id_,
+      last_loaded_extension_id(), service, false);
+  service->DisableExtension(last_loaded_extension_id(),
                             Extension::DISABLE_USER_ACTION);
-  EXPECT_FALSE(service->IsExtensionEnabled(last_loaded_extension_id_));
+  EXPECT_FALSE(service->IsExtensionEnabled(last_loaded_extension_id()));
 
   // Enable the extension and verify.
   extension_util::SetIsIncognitoEnabled(
-      last_loaded_extension_id_, service, false);
-  service->EnableExtension(last_loaded_extension_id_);
-  EXPECT_TRUE(service->IsExtensionEnabled(last_loaded_extension_id_));
+      last_loaded_extension_id(), service, false);
+  service->EnableExtension(last_loaded_extension_id());
+  EXPECT_TRUE(service->IsExtensionEnabled(last_loaded_extension_id()));
 
   // Allow extension in incognito mode and verify.
-  service->EnableExtension(last_loaded_extension_id_);
+  service->EnableExtension(last_loaded_extension_id());
   extension_util::SetIsIncognitoEnabled(
-      last_loaded_extension_id_, service, true);
-  EXPECT_TRUE(extension_util::IsIncognitoEnabled(last_loaded_extension_id_,
-                                                 service));
+      last_loaded_extension_id(), service, true);
+  EXPECT_TRUE(
+      extension_util::IsIncognitoEnabled(last_loaded_extension_id(), service));
 
   // Disallow extension in incognito mode and verify.
-  service->EnableExtension(last_loaded_extension_id_);
+  service->EnableExtension(last_loaded_extension_id());
   extension_util::SetIsIncognitoEnabled(
-      last_loaded_extension_id_, service, false);
-  EXPECT_FALSE(extension_util::IsIncognitoEnabled(last_loaded_extension_id_,
-                                                  service));
+      last_loaded_extension_id(), service, false);
+  EXPECT_FALSE(
+      extension_util::IsIncognitoEnabled(last_loaded_extension_id(), service));
 }
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_install_ui_browsertest.cc b/chrome/browser/extensions/extension_install_ui_browsertest.cc
index 6a1aac87..615584e 100644
--- a/chrome/browser/extensions/extension_install_ui_browsertest.cc
+++ b/chrome/browser/extensions/extension_install_ui_browsertest.cc
@@ -186,7 +186,8 @@
   }
 }
 
-class NewTabUISortingBrowserTest : public ExtensionInstallUIBrowserTest {
+class NewTabUISortingBrowserTest : public ExtensionInstallUIBrowserTest,
+                                   public content::NotificationObserver {
  public:
   NewTabUISortingBrowserTest() {}
 
@@ -194,7 +195,7 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE {
     if (type != chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED) {
-      ExtensionInstallUIBrowserTest::Observe(type, source, details);
+      observer_->Observe(type, source, details);
       return;
     }
     const std::string* id = content::Details<const std::string>(details).ptr();
diff --git a/chrome/browser/extensions/extension_nacl_browsertest.cc b/chrome/browser/extensions/extension_nacl_browsertest.cc
index df151de..ba724d5 100644
--- a/chrome/browser/extensions/extension_nacl_browsertest.cc
+++ b/chrome/browser/extensions/extension_nacl_browsertest.cc
@@ -77,7 +77,7 @@
       case INSTALL_TYPE_FROM_WEBSTORE:
         // Install native_client.crx from the webstore.
         if (InstallExtensionFromWebstore(file_path, 1)) {
-          extension = service->GetExtensionById(last_loaded_extension_id_,
+          extension = service->GetExtensionById(last_loaded_extension_id(),
                                                 false);
         }
         break;
@@ -85,7 +85,7 @@
       case INSTALL_TYPE_NON_WEBSTORE:
         // Install native_client.crx but not from the webstore.
         if (ExtensionBrowserTest::InstallExtension(file_path, 1)) {
-          extension = service->GetExtensionById(last_loaded_extension_id_,
+          extension = service->GetExtensionById(last_loaded_extension_id(),
                                                 false);
         }
         break;
diff --git a/chrome/browser/extensions/extension_test_notification_observer.cc b/chrome/browser/extensions/extension_test_notification_observer.cc
new file mode 100644
index 0000000..f8b7a6d4
--- /dev/null
+++ b/chrome/browser/extensions/extension_test_notification_observer.cc
@@ -0,0 +1,234 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_test_notification_observer.h"
+
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/test/test_utils.h"
+
+using extensions::Extension;
+
+namespace {
+
+bool HasExtensionPageActionCountReachedTarget(LocationBarTesting* location_bar,
+                                              int target_page_action_count) {
+  VLOG(1) << "Number of page actions: " << location_bar->PageActionCount();
+  return location_bar->PageActionCount() == target_page_action_count;
+}
+
+bool HasExtensionPageActionVisibilityReachedTarget(
+    LocationBarTesting* location_bar,
+    int target_visible_page_action_count) {
+  VLOG(1) << "Number of visible page actions: "
+          << location_bar->PageActionVisibleCount();
+  return location_bar->PageActionVisibleCount() ==
+         target_visible_page_action_count;
+}
+
+}  // namespace
+
+ExtensionTestNotificationObserver::ExtensionTestNotificationObserver(
+    Browser* browser)
+    : browser_(browser),
+      profile_(NULL),
+      extension_installs_observed_(0),
+      extension_load_errors_observed_(0),
+      crx_installers_done_observed_(0) {
+}
+
+ExtensionTestNotificationObserver::~ExtensionTestNotificationObserver() {}
+
+Profile* ExtensionTestNotificationObserver::GetProfile() {
+  if (!profile_) {
+    if (browser_)
+      profile_ = browser_->profile();
+    else
+      profile_ = ProfileManager::GetDefaultProfile();
+  }
+  return profile_;
+}
+
+void ExtensionTestNotificationObserver::WaitForNotification(
+    int notification_type) {
+  // TODO(bauerb): Using a WindowedNotificationObserver like this can break
+  // easily, if the notification we're waiting for is sent before this method.
+  // Change it so that the WindowedNotificationObserver is constructed earlier.
+  content::NotificationRegistrar registrar;
+  registrar.Add(
+      this, notification_type, content::NotificationService::AllSources());
+  content::WindowedNotificationObserver(
+      notification_type, content::NotificationService::AllSources()).Wait();
+}
+
+bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo(
+    int count) {
+  LocationBarTesting* location_bar =
+      browser_->window()->GetLocationBar()->GetLocationBarForTesting();
+  if (!HasExtensionPageActionCountReachedTarget(location_bar, count)) {
+    content::WindowedNotificationObserver(
+        chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED,
+        base::Bind(
+            &HasExtensionPageActionCountReachedTarget, location_bar, count))
+        .Wait();
+  }
+  return HasExtensionPageActionCountReachedTarget(location_bar, count);
+}
+
+bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo(
+    int count) {
+  LocationBarTesting* location_bar =
+      browser_->window()->GetLocationBar()->GetLocationBarForTesting();
+  if (!HasExtensionPageActionVisibilityReachedTarget(location_bar, count)) {
+    content::WindowedNotificationObserver(
+        chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED,
+        base::Bind(&HasExtensionPageActionVisibilityReachedTarget,
+                   location_bar,
+                   count)).Wait();
+  }
+  return HasExtensionPageActionVisibilityReachedTarget(location_bar, count);
+}
+
+bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() {
+  ExtensionProcessManager* manager =
+    extensions::ExtensionSystem::Get(GetProfile())->process_manager();
+  ExtensionProcessManager::ViewSet all_views = manager->GetAllViews();
+  for (ExtensionProcessManager::ViewSet::const_iterator iter =
+         all_views.begin();
+       iter != all_views.end();) {
+    if (!(*iter)->IsLoading()) {
+      ++iter;
+    } else {
+      // Wait for all the extension render view hosts that exist to finish
+      // loading.
+      content::WindowedNotificationObserver observer(
+          content::NOTIFICATION_LOAD_STOP,
+          content::NotificationService::AllSources());
+      observer.AddNotificationType(
+                                   content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+                                   content::NotificationService::AllSources());
+      observer.Wait();
+
+      // Test activity may have modified the set of extension processes during
+      // message processing, so re-start the iteration to catch added/removed
+      // processes.
+      all_views = manager->GetAllViews();
+      iter = all_views.begin();
+    }
+  }
+  return true;
+}
+
+bool ExtensionTestNotificationObserver::WaitForExtensionInstall() {
+  int before = extension_installs_observed_;
+  WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED);
+  return extension_installs_observed_ == (before + 1);
+}
+
+bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() {
+  int before = extension_installs_observed_;
+  content::WindowedNotificationObserver(
+      chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+      content::NotificationService::AllSources()).Wait();
+  return extension_installs_observed_ == before;
+}
+
+void ExtensionTestNotificationObserver::WaitForExtensionLoad() {
+  WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOADED);
+}
+
+void ExtensionTestNotificationObserver::WaitForExtensionAndViewLoad() {
+  this->WaitForExtensionLoad();
+  WaitForExtensionViewsToLoad();
+}
+
+bool ExtensionTestNotificationObserver::WaitForExtensionLoadError() {
+  int before = extension_load_errors_observed_;
+  WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOAD_ERROR);
+  return extension_load_errors_observed_ != before;
+}
+
+bool ExtensionTestNotificationObserver::WaitForExtensionCrash(
+    const std::string& extension_id) {
+  ExtensionService* service = extensions::ExtensionSystem::Get(
+      GetProfile())->extension_service();
+
+  if (!service->GetExtensionById(extension_id, true)) {
+    // The extension is already unloaded, presumably due to a crash.
+    return true;
+  }
+  content::WindowedNotificationObserver(
+      chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
+      content::NotificationService::AllSources()).Wait();
+  return (service->GetExtensionById(extension_id, true) == NULL);
+}
+
+bool ExtensionTestNotificationObserver::WaitForCrxInstallerDone() {
+  int before = crx_installers_done_observed_;
+  WaitForNotification(chrome::NOTIFICATION_CRX_INSTALLER_DONE);
+  return crx_installers_done_observed_ == (before + 1);
+}
+
+void ExtensionTestNotificationObserver::Watch(
+    int type,
+    const content::NotificationSource& source) {
+  CHECK(!observer_);
+  observer_.reset(new content::WindowedNotificationObserver(type, source));
+  registrar_.Add(this, type, source);
+}
+
+void ExtensionTestNotificationObserver::Wait() {
+  observer_->Wait();
+
+  registrar_.RemoveAll();
+  observer_.reset();
+}
+
+void ExtensionTestNotificationObserver::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  switch (type) {
+  case chrome::NOTIFICATION_EXTENSION_LOADED:
+      last_loaded_extension_id_ =
+        content::Details<const Extension>(details).ptr()->id();
+      VLOG(1) << "Got EXTENSION_LOADED notification.";
+      break;
+
+  case chrome::NOTIFICATION_CRX_INSTALLER_DONE:
+    VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
+    {
+        const Extension* extension =
+          content::Details<const Extension>(details).ptr();
+        if (extension)
+          last_loaded_extension_id_ = extension->id();
+        else
+          last_loaded_extension_id_.clear();
+    }
+    ++crx_installers_done_observed_;
+    break;
+
+  case chrome::NOTIFICATION_EXTENSION_INSTALLED:
+    VLOG(1) << "Got EXTENSION_INSTALLED notification.";
+    ++extension_installs_observed_;
+    break;
+
+  case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR:
+    VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
+    ++extension_load_errors_observed_;
+    break;
+
+  default:
+    NOTREACHED();
+    break;
+  }
+}
diff --git a/chrome/browser/extensions/extension_test_notification_observer.h b/chrome/browser/extensions/extension_test_notification_observer.h
new file mode 100644
index 0000000..14636b6
--- /dev/null
+++ b/chrome/browser/extensions/extension_test_notification_observer.h
@@ -0,0 +1,100 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_NOTIFICATION_OBSERVER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_NOTIFICATION_OBSERVER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/omnibox/location_bar.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_types.h"
+
+namespace content {
+class WindowedNotificationObserver;
+}
+
+// Test helper class for observing extension-related events.
+class ExtensionTestNotificationObserver : public content::NotificationObserver {
+ public:
+  explicit ExtensionTestNotificationObserver(Browser* browser);
+  virtual ~ExtensionTestNotificationObserver();
+
+  // Wait for the total number of page actions to change to |count|.
+  bool WaitForPageActionCountChangeTo(int count);
+
+  // Wait for the number of visible page actions to change to |count|.
+  bool WaitForPageActionVisibilityChangeTo(int count);
+
+  // Waits until an extension is installed and loaded. Returns true if an
+  // install happened before timeout.
+  bool WaitForExtensionInstall();
+
+  // Wait for an extension install error to be raised. Returns true if an
+  // error was raised.
+  bool WaitForExtensionInstallError();
+
+  // Waits until an extension is loaded and all view have loaded.
+  void WaitForExtensionAndViewLoad();
+
+  // Waits until an extension is loaded.
+  void WaitForExtensionLoad();
+
+  // Waits for an extension load error. Returns true if the error really
+  // happened.
+  bool WaitForExtensionLoadError();
+
+  // Wait for the specified extension to crash. Returns true if it really
+  // crashed.
+  bool WaitForExtensionCrash(const std::string& extension_id);
+
+  // Wait for the crx installer to be done. Returns true if it really is done.
+  bool WaitForCrxInstallerDone();
+
+  // Wait for all extension views to load.
+  bool WaitForExtensionViewsToLoad();
+
+  // Watch for the given event type from the given source.
+  // After calling this method, call Wait() to ensure that RunMessageLoop() is
+  // called appropriately and cleanup is performed.
+  void Watch(int type, const content::NotificationSource& source);
+
+  // After registering one or more event types with Watch(), call
+  // this method to run the message loop and perform cleanup.
+  void Wait();
+
+  const std::string& last_loaded_extension_id() {
+    return last_loaded_extension_id_;
+  }
+  void set_last_loaded_extension_id(std::string last_loaded_extension_id) {
+    last_loaded_extension_id_ = last_loaded_extension_id;
+  }
+
+  // content::NotificationObserver
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+  Profile* GetProfile();
+
+  void WaitForNotification(int notification_type);
+
+  Browser* browser_;
+  Profile* profile_;
+
+  content::NotificationRegistrar registrar_;
+  scoped_ptr<content::WindowedNotificationObserver> observer_;
+
+  std::string last_loaded_extension_id_;
+  int extension_installs_observed_;
+  int extension_load_errors_observed_;
+  int crx_installers_done_observed_;
+};
+
+#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_NOTIFICATION_OBSERVER_H_
diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc
index 7bd8ac9..df1bf3d 100644
--- a/chrome/browser/extensions/lazy_background_page_apitest.cc
+++ b/chrome/browser/extensions/lazy_background_page_apitest.cc
@@ -104,7 +104,7 @@
   // Lazy Background Page doesn't exist yet.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   int num_tabs_before = browser()->tab_strip_model()->count();
 
   // Observe background page being created and closed after
@@ -114,7 +114,7 @@
   page_complete.Wait();
 
   // Background page created a new tab before it closed.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count());
   EXPECT_EQ(std::string(chrome::kChromeUIExtensionsURL),
             browser()->tab_strip_model()->GetActiveWebContents()->
@@ -128,7 +128,7 @@
   // Lazy Background Page doesn't exist yet.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   int num_tabs_before = browser()->tab_strip_model()->count();
 
   // Observe background page being created and closed after
@@ -138,7 +138,7 @@
   page_complete.Wait();
 
   // Background page is closed after creating a new tab.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count());
 }
 
@@ -151,7 +151,7 @@
   // Lazy Background Page doesn't exist yet.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   int num_page_actions = browser()->window()->GetLocationBar()->
       GetLocationBarForTesting()->PageActionVisibleCount();
 
@@ -164,7 +164,7 @@
       browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
   page_complete.Wait();
 
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Page action is shown.
   page_action_changed.Wait();
@@ -182,7 +182,7 @@
   // Lazy Background Page doesn't exist yet.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Open a tab to a URL that will fire a webNavigation event.
   LazyBackgroundObserver page_complete;
@@ -201,7 +201,7 @@
   // Lazy Background Page has been shut down.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
 
 // Tests that the lazy background page stays alive until all visible views are
@@ -224,7 +224,7 @@
   // to an extension page.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Close the new tab.
   browser()->tab_strip_model()->CloseWebContentsAt(
@@ -232,7 +232,7 @@
   page_complete.Wait();
 
   // Lazy Background Page has been shut down.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
 
 // Tests that the lazy background page stays alive until all network requests
@@ -253,7 +253,7 @@
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
   extensions::ExtensionHost* host =
-      pm->GetBackgroundHostForExtension(last_loaded_extension_id_);
+      pm->GetBackgroundHostForExtension(last_loaded_extension_id());
   ASSERT_TRUE(host);
 
   // Abort the request.
@@ -264,7 +264,7 @@
   page_complete.Wait();
 
   // Lazy Background Page has been shut down.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
 
 // Tests that the lazy background page stays alive until all visible views are
@@ -293,14 +293,14 @@
   // to an extension page.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Navigate away from the NTP, which should close the event page.
   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
   lazybg.Wait();
 
   // Lazy Background Page has been shut down.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
 
 // See crbug.com/248437
@@ -332,8 +332,8 @@
   ExtensionProcessManager* pmi =
       extensions::ExtensionSystem::Get(incognito_browser->profile())->
           process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
-  EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
+  EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Trigger a browserAction event in the original profile and ensure only
   // the original event page received it (since the event is scoped to the
@@ -347,8 +347,9 @@
     page_complete.Wait();
 
     // Only the original event page received the message.
-    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
-    EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id_));
+    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
+    EXPECT_FALSE(
+        pmi->GetBackgroundHostForExtension(last_loaded_extension_id()));
     EXPECT_TRUE(listener.was_satisfied());
     EXPECT_FALSE(listener_incognito.was_satisfied());
   }
@@ -370,8 +371,9 @@
     page2_complete.Wait();
 
     // Both pages received the message.
-    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
-    EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id_));
+    EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
+    EXPECT_FALSE(
+        pmi->GetBackgroundHostForExtension(last_loaded_extension_id()));
     EXPECT_TRUE(listener.was_satisfied());
     EXPECT_TRUE(listener_incognito.was_satisfied());
   }
@@ -386,7 +388,7 @@
   // Lazy Background Page doesn't exist yet.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
 
   // Navigate to a page that opens a message channel to the background page.
@@ -399,14 +401,14 @@
   // Background page got the content script's message and is still loaded
   // until we close the channel.
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
-  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Navigate away, closing the message channel and therefore the background
   // page.
   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
   lazybg.WaitUntilClosed();
 
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
 
 // Tests that the lazy background page receives the unload event when we
@@ -418,7 +420,7 @@
   // Lazy Background Page has been shut down.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // The browser action has a new title.
   BrowserActionTestUtil browser_action(browser());
@@ -481,7 +483,7 @@
   // to an extension page.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(browser()->profile())->process_manager();
-  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_TRUE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Close the new tab.
   LazyBackgroundObserver page_complete;
@@ -490,7 +492,7 @@
   page_complete.WaitUntilClosed();
 
   // Lazy Background Page has been shut down.
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 
   // Verify that extensions page shows that the lazy background page is
   // inactive.
diff --git a/chrome/browser/extensions/notifications_apitest.cc b/chrome/browser/extensions/notifications_apitest.cc
index 0fd5812..b1299cf 100644
--- a/chrome/browser/extensions/notifications_apitest.cc
+++ b/chrome/browser/extensions/notifications_apitest.cc
@@ -74,5 +74,5 @@
   // Lazy Background Page has been shut down.
   ExtensionProcessManager* pm =
       extensions::ExtensionSystem::Get(profile())->process_manager();
-  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id_));
+  EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
 }
diff --git a/chrome/browser/extensions/page_action_browsertest.cc b/chrome/browser/extensions/page_action_browsertest.cc
index 52a0dd4f..921b333 100644
--- a/chrome/browser/extensions/page_action_browsertest.cc
+++ b/chrome/browser/extensions/page_action_browsertest.cc
@@ -108,7 +108,7 @@
   ui_test_utils::NavigateToURL(browser(), feed_url);
   ASSERT_TRUE(WaitForPageActionCountChangeTo(1));
 
-  UnloadExtension(last_loaded_extension_id_);
+  UnloadExtension(last_loaded_extension_id());
 
   // Make sure the page action goes away when it's unloaded.
   ASSERT_TRUE(WaitForPageActionCountChangeTo(0));
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 1a2c619..5cee30ed 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -442,7 +442,7 @@
       test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
 
   GURL start_url(std::string("chrome-extension://") +
-      last_loaded_extension_id_ + "/test.html");
+      last_loaded_extension_id() + "/test.html");
   ui_test_utils::NavigateToURL(browser(), start_url);
   WebContents* newtab = NULL;
   ASSERT_NO_FATAL_FAILURE(
@@ -462,7 +462,7 @@
       test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
 
   GURL start_url(std::string("chrome-extension://") +
-      last_loaded_extension_id_ + "/test.html");
+      last_loaded_extension_id() + "/test.html");
   ui_test_utils::NavigateToURL(browser(), start_url);
   ASSERT_NO_FATAL_FAILURE(
       OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(),
@@ -484,7 +484,7 @@
   WebContents* newtab = NULL;
   ASSERT_NO_FATAL_FAILURE(
       OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(),
-      GURL(std::string("chrome-extension://") + last_loaded_extension_id_ +
+      GURL(std::string("chrome-extension://") + last_loaded_extension_id() +
           "/newtab.html"), false, &newtab));
 
   // Extension API should succeed.