Home | History | Annotate | Download | only in background
      1 // Copyright (c) 2011 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 "base/command_line.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/browser/background/background_mode_manager.h"
     10 #include "chrome/browser/browser_shutdown.h"
     11 #include "chrome/browser/extensions/extension_function_test_utils.h"
     12 #include "chrome/browser/extensions/extension_service.h"
     13 #include "chrome/browser/extensions/test_extension_system.h"
     14 #include "chrome/browser/lifetime/application_lifetime.h"
     15 #include "chrome/browser/profiles/profile_info_cache.h"
     16 #include "chrome/browser/status_icons/status_icon_menu_model.h"
     17 #include "chrome/common/chrome_switches.h"
     18 #include "chrome/test/base/testing_browser_process.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "chrome/test/base/testing_profile_manager.h"
     21 #include "content/public/test/test_browser_thread_bundle.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "ui/gfx/image/image.h"
     24 #include "ui/gfx/image/image_unittest_util.h"
     25 #include "ui/message_center/message_center.h"
     26 
     27 #if defined(OS_CHROMEOS)
     28 #include "chrome/browser/chromeos/login/users/user_manager.h"
     29 #include "chrome/browser/chromeos/settings/cros_settings.h"
     30 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     31 #endif
     32 
     33 class BackgroundModeManagerTest : public testing::Test {
     34  public:
     35   BackgroundModeManagerTest() {}
     36   virtual ~BackgroundModeManagerTest() {}
     37   virtual void SetUp() {
     38     command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
     39   }
     40   scoped_ptr<CommandLine> command_line_;
     41 
     42  protected:
     43   scoped_refptr<extensions::Extension> CreateExtension(
     44       extensions::Manifest::Location location,
     45       const std::string& data,
     46       const std::string& id) {
     47     scoped_ptr<base::DictionaryValue> parsed_manifest(
     48         extension_function_test_utils::ParseDictionary(data));
     49     return extension_function_test_utils::CreateExtension(
     50         location,
     51         parsed_manifest.get(),
     52         id);
     53   }
     54 
     55   scoped_ptr<TestingProfileManager> CreateTestingProfileManager() {
     56     scoped_ptr<TestingProfileManager> profile_manager
     57         (new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     58     EXPECT_TRUE(profile_manager->SetUp());
     59     return profile_manager.Pass();
     60   }
     61 
     62   // From views::MenuModelAdapter::IsCommandEnabled with modification.
     63   bool IsCommandEnabled(ui::MenuModel* model, int id) const {
     64     int index = 0;
     65     if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
     66       return model->IsEnabledAt(index);
     67 
     68     return false;
     69   }
     70 
     71  private:
     72   DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest);
     73 };
     74 
     75 class TestBackgroundModeManager : public BackgroundModeManager {
     76  public:
     77   TestBackgroundModeManager(
     78       CommandLine* command_line, ProfileInfoCache* cache, bool enabled)
     79       : BackgroundModeManager(command_line, cache),
     80         enabled_(enabled),
     81         app_count_(0),
     82         profile_app_count_(0),
     83         have_status_tray_(false),
     84         launch_on_startup_(false) {
     85     ResumeBackgroundMode();
     86   }
     87   virtual void EnableLaunchOnStartup(bool launch) OVERRIDE {
     88     launch_on_startup_ = launch;
     89   }
     90   virtual void DisplayAppInstalledNotification(
     91       const extensions::Extension* extension) OVERRIDE {}
     92   virtual void CreateStatusTrayIcon() OVERRIDE { have_status_tray_ = true; }
     93   virtual void RemoveStatusTrayIcon() OVERRIDE { have_status_tray_ = false; }
     94   virtual int GetBackgroundAppCount() const OVERRIDE { return app_count_; }
     95   virtual int GetBackgroundAppCountForProfile(
     96       Profile* const profile) const OVERRIDE {
     97     return profile_app_count_;
     98   }
     99   virtual bool IsBackgroundModePrefEnabled() const OVERRIDE { return enabled_; }
    100   void SetBackgroundAppCount(int count) { app_count_ = count; }
    101   void SetBackgroundAppCountForProfile(int count) {
    102     profile_app_count_ = count;
    103   }
    104   void SetEnabled(bool enabled) {
    105     enabled_ = enabled;
    106     OnBackgroundModeEnabledPrefChanged();
    107   }
    108   bool HaveStatusTray() const { return have_status_tray_; }
    109   bool IsLaunchOnStartup() const { return launch_on_startup_; }
    110  private:
    111   bool enabled_;
    112   int app_count_;
    113   int profile_app_count_;
    114 
    115   // Flags to track whether we are launching on startup/have a status tray.
    116   bool have_status_tray_;
    117   bool launch_on_startup_;
    118 };
    119 
    120 class TestStatusIcon : public StatusIcon {
    121   virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE {}
    122   virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE {}
    123   virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE {}
    124   virtual void DisplayBalloon(const gfx::ImageSkia& icon,
    125                               const base::string16& title,
    126                               const base::string16& contents) OVERRIDE {}
    127   virtual void UpdatePlatformContextMenu(
    128       StatusIconMenuModel* menu) OVERRIDE {}
    129 };
    130 
    131 static void AssertBackgroundModeActive(
    132     const TestBackgroundModeManager& manager) {
    133   EXPECT_TRUE(chrome::WillKeepAlive());
    134   EXPECT_TRUE(manager.HaveStatusTray());
    135   EXPECT_TRUE(manager.IsLaunchOnStartup());
    136 }
    137 
    138 static void AssertBackgroundModeInactive(
    139     const TestBackgroundModeManager& manager) {
    140   EXPECT_FALSE(chrome::WillKeepAlive());
    141   EXPECT_FALSE(manager.HaveStatusTray());
    142   EXPECT_FALSE(manager.IsLaunchOnStartup());
    143 }
    144 
    145 static void AssertBackgroundModeSuspended(
    146     const TestBackgroundModeManager& manager) {
    147   EXPECT_FALSE(chrome::WillKeepAlive());
    148   EXPECT_FALSE(manager.HaveStatusTray());
    149   EXPECT_TRUE(manager.IsLaunchOnStartup());
    150 }
    151 
    152 TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) {
    153   scoped_ptr<TestingProfileManager> profile_manager =
    154       CreateTestingProfileManager();
    155   TestingProfile* profile = profile_manager->CreateTestingProfile("p1");
    156   TestBackgroundModeManager manager(
    157       command_line_.get(), profile_manager->profile_info_cache(), true);
    158   manager.RegisterProfile(profile);
    159   EXPECT_FALSE(chrome::WillKeepAlive());
    160 
    161   // Mimic app load.
    162   manager.OnBackgroundAppInstalled(NULL);
    163   manager.SetBackgroundAppCount(1);
    164   manager.OnApplicationListChanged(profile);
    165   AssertBackgroundModeActive(manager);
    166 
    167   manager.SuspendBackgroundMode();
    168   AssertBackgroundModeSuspended(manager);
    169   manager.ResumeBackgroundMode();
    170 
    171   // Mimic app unload.
    172   manager.SetBackgroundAppCount(0);
    173   manager.OnApplicationListChanged(profile);
    174   AssertBackgroundModeInactive(manager);
    175 
    176   manager.SuspendBackgroundMode();
    177   AssertBackgroundModeInactive(manager);
    178 
    179   // Mimic app load while suspended, e.g. from sync. This should enable and
    180   // resume background mode.
    181   manager.OnBackgroundAppInstalled(NULL);
    182   manager.SetBackgroundAppCount(1);
    183   manager.OnApplicationListChanged(profile);
    184   AssertBackgroundModeActive(manager);
    185 }
    186 
    187 // App installs while background mode is disabled should do nothing.
    188 TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) {
    189   scoped_ptr<TestingProfileManager> profile_manager =
    190       CreateTestingProfileManager();
    191   TestingProfile* profile = profile_manager->CreateTestingProfile("p1");
    192   TestBackgroundModeManager manager(
    193       command_line_.get(), profile_manager->profile_info_cache(), true);
    194   manager.RegisterProfile(profile);
    195   // Turn off background mode.
    196   manager.SetEnabled(false);
    197   manager.DisableBackgroundMode();
    198   AssertBackgroundModeInactive(manager);
    199 
    200   // Status tray icons will not be created, launch on startup status will not
    201   // be modified.
    202   manager.OnBackgroundAppInstalled(NULL);
    203   manager.SetBackgroundAppCount(1);
    204   manager.OnApplicationListChanged(profile);
    205   AssertBackgroundModeInactive(manager);
    206 
    207   manager.SetBackgroundAppCount(0);
    208   manager.OnApplicationListChanged(profile);
    209   AssertBackgroundModeInactive(manager);
    210 
    211   // Re-enable background mode.
    212   manager.SetEnabled(true);
    213   manager.EnableBackgroundMode();
    214   AssertBackgroundModeInactive(manager);
    215 }
    216 
    217 
    218 // App installs while disabled should do nothing until background mode is
    219 // enabled..
    220 TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) {
    221   scoped_ptr<TestingProfileManager> profile_manager =
    222       CreateTestingProfileManager();
    223   TestingProfile* profile = profile_manager->CreateTestingProfile("p1");
    224   TestBackgroundModeManager manager(
    225       command_line_.get(), profile_manager->profile_info_cache(), true);
    226   manager.RegisterProfile(profile);
    227 
    228   // Install app, should show status tray icon.
    229   manager.OnBackgroundAppInstalled(NULL);
    230   // OnBackgroundAppInstalled does not actually add an app to the
    231   // BackgroundApplicationListModel which would result in another
    232   // call to CreateStatusTray.
    233   manager.SetBackgroundAppCount(1);
    234   manager.OnApplicationListChanged(profile);
    235   AssertBackgroundModeActive(manager);
    236 
    237   // Turn off background mode - should hide status tray icon.
    238   manager.SetEnabled(false);
    239   manager.DisableBackgroundMode();
    240   AssertBackgroundModeInactive(manager);
    241 
    242   // Turn back on background mode - again, no status tray icon
    243   // will show up since we didn't actually add anything to the list.
    244   manager.SetEnabled(true);
    245   manager.EnableBackgroundMode();
    246   AssertBackgroundModeActive(manager);
    247 
    248   // Uninstall app, should hide status tray icon again.
    249   manager.SetBackgroundAppCount(0);
    250   manager.OnApplicationListChanged(profile);
    251   AssertBackgroundModeInactive(manager);
    252 }
    253 
    254 TEST_F(BackgroundModeManagerTest, MultiProfile) {
    255   scoped_ptr<TestingProfileManager> profile_manager =
    256       CreateTestingProfileManager();
    257   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    258   TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2");
    259   TestBackgroundModeManager manager(
    260       command_line_.get(), profile_manager->profile_info_cache(), true);
    261   manager.RegisterProfile(profile1);
    262   manager.RegisterProfile(profile2);
    263   EXPECT_FALSE(chrome::WillKeepAlive());
    264 
    265   // Install app, should show status tray icon.
    266   manager.OnBackgroundAppInstalled(NULL);
    267   manager.SetBackgroundAppCount(1);
    268   manager.OnApplicationListChanged(profile1);
    269   AssertBackgroundModeActive(manager);
    270 
    271   // Install app for other profile, hsould show other status tray icon.
    272   manager.OnBackgroundAppInstalled(NULL);
    273   manager.SetBackgroundAppCount(2);
    274   manager.OnApplicationListChanged(profile2);
    275   AssertBackgroundModeActive(manager);
    276 
    277   // Should hide both status tray icons.
    278   manager.SetEnabled(false);
    279   manager.DisableBackgroundMode();
    280   AssertBackgroundModeInactive(manager);
    281 
    282   // Turn back on background mode - should show both status tray icons.
    283   manager.SetEnabled(true);
    284   manager.EnableBackgroundMode();
    285   AssertBackgroundModeActive(manager);
    286 
    287   manager.SetBackgroundAppCount(1);
    288   manager.OnApplicationListChanged(profile2);
    289   // There is still one background app alive
    290   AssertBackgroundModeActive(manager);
    291 
    292   manager.SetBackgroundAppCount(0);
    293   manager.OnApplicationListChanged(profile1);
    294   AssertBackgroundModeInactive(manager);
    295 }
    296 
    297 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheStorage) {
    298   scoped_ptr<TestingProfileManager> profile_manager =
    299       CreateTestingProfileManager();
    300   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    301   TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2");
    302   TestBackgroundModeManager manager(
    303       command_line_.get(), profile_manager->profile_info_cache(), true);
    304   manager.RegisterProfile(profile1);
    305   manager.RegisterProfile(profile2);
    306   EXPECT_FALSE(chrome::WillKeepAlive());
    307 
    308   ProfileInfoCache* cache = profile_manager->profile_info_cache();
    309   EXPECT_EQ(2u, cache->GetNumberOfProfiles());
    310 
    311   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(0));
    312   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(1));
    313 
    314   // Install app, should show status tray icon.
    315   manager.OnBackgroundAppInstalled(NULL);
    316   manager.SetBackgroundAppCount(1);
    317   manager.SetBackgroundAppCountForProfile(1);
    318   manager.OnApplicationListChanged(profile1);
    319 
    320   // Install app for other profile.
    321   manager.OnBackgroundAppInstalled(NULL);
    322   manager.SetBackgroundAppCount(1);
    323   manager.SetBackgroundAppCountForProfile(1);
    324   manager.OnApplicationListChanged(profile2);
    325 
    326   EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(0));
    327   EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(1));
    328 
    329   manager.SetBackgroundAppCountForProfile(0);
    330   manager.OnApplicationListChanged(profile1);
    331 
    332   size_t p1_index = cache->GetIndexOfProfileWithPath(profile1->GetPath());
    333   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p1_index));
    334 
    335   manager.SetBackgroundAppCountForProfile(0);
    336   manager.OnApplicationListChanged(profile2);
    337 
    338   size_t p2_index = cache->GetIndexOfProfileWithPath(profile1->GetPath());
    339   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p2_index));
    340 
    341   // Even though neither has background status on, there should still be two
    342   // profiles in the cache.
    343   EXPECT_EQ(2u, cache->GetNumberOfProfiles());
    344 }
    345 
    346 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheObserver) {
    347   scoped_ptr<TestingProfileManager> profile_manager =
    348       CreateTestingProfileManager();
    349   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    350   TestBackgroundModeManager manager(
    351       command_line_.get(), profile_manager->profile_info_cache(), true);
    352   manager.RegisterProfile(profile1);
    353   EXPECT_FALSE(chrome::WillKeepAlive());
    354 
    355   // Install app, should show status tray icon.
    356   manager.OnBackgroundAppInstalled(NULL);
    357   manager.SetBackgroundAppCount(1);
    358   manager.SetBackgroundAppCountForProfile(1);
    359   manager.OnApplicationListChanged(profile1);
    360 
    361   manager.OnProfileNameChanged(
    362       profile1->GetPath(),
    363       manager.GetBackgroundModeData(profile1)->name());
    364 
    365   EXPECT_EQ(base::UTF8ToUTF16("p1"),
    366             manager.GetBackgroundModeData(profile1)->name());
    367 
    368   EXPECT_TRUE(chrome::WillKeepAlive());
    369   TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2");
    370   manager.RegisterProfile(profile2);
    371   EXPECT_EQ(2, manager.NumberOfBackgroundModeData());
    372 
    373   manager.OnProfileAdded(profile2->GetPath());
    374   EXPECT_EQ(base::UTF8ToUTF16("p2"),
    375             manager.GetBackgroundModeData(profile2)->name());
    376 
    377   manager.OnProfileWillBeRemoved(profile2->GetPath());
    378   // Should still be in background mode after deleting profile.
    379   EXPECT_TRUE(chrome::WillKeepAlive());
    380   EXPECT_EQ(1, manager.NumberOfBackgroundModeData());
    381 
    382   // Check that the background mode data we think is in the map actually is.
    383   EXPECT_EQ(base::UTF8ToUTF16("p1"),
    384             manager.GetBackgroundModeData(profile1)->name());
    385 }
    386 
    387 TEST_F(BackgroundModeManagerTest, DeleteBackgroundProfile) {
    388   // Tests whether deleting the only profile when it is a BG profile works
    389   // or not (http://crbug.com/346214).
    390   scoped_ptr<TestingProfileManager> profile_manager =
    391       CreateTestingProfileManager();
    392   TestingProfile* profile = profile_manager->CreateTestingProfile("p1");
    393   TestBackgroundModeManager manager(
    394       command_line_.get(), profile_manager->profile_info_cache(), true);
    395   manager.RegisterProfile(profile);
    396   EXPECT_FALSE(chrome::WillKeepAlive());
    397 
    398   // Install app, should show status tray icon.
    399   manager.OnBackgroundAppInstalled(NULL);
    400   manager.SetBackgroundAppCount(1);
    401   manager.SetBackgroundAppCountForProfile(1);
    402   manager.OnApplicationListChanged(profile);
    403 
    404   manager.OnProfileNameChanged(
    405       profile->GetPath(),
    406       manager.GetBackgroundModeData(profile)->name());
    407 
    408   EXPECT_TRUE(chrome::WillKeepAlive());
    409   manager.SetBackgroundAppCount(0);
    410   manager.SetBackgroundAppCountForProfile(0);
    411   manager.OnProfileWillBeRemoved(profile->GetPath());
    412   EXPECT_FALSE(chrome::WillKeepAlive());
    413 }
    414 
    415 TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) {
    416   scoped_ptr<TestingProfileManager> profile_manager =
    417       CreateTestingProfileManager();
    418   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    419   command_line_->AppendSwitch(switches::kKeepAliveForTest);
    420   TestBackgroundModeManager manager(
    421       command_line_.get(), profile_manager->profile_info_cache(), true);
    422   manager.RegisterProfile(profile1);
    423   EXPECT_TRUE(manager.ShouldBeInBackgroundMode());
    424   manager.SetEnabled(false);
    425   EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
    426 }
    427 
    428 TEST_F(BackgroundModeManagerTest,
    429        BackgroundModeDisabledPreventsKeepAliveOnStartup) {
    430   scoped_ptr<TestingProfileManager> profile_manager =
    431       CreateTestingProfileManager();
    432   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    433   command_line_->AppendSwitch(switches::kKeepAliveForTest);
    434   TestBackgroundModeManager manager(
    435       command_line_.get(), profile_manager->profile_info_cache(), false);
    436   manager.RegisterProfile(profile1);
    437   EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
    438 }
    439 
    440 TEST_F(BackgroundModeManagerTest, BackgroundMenuGeneration) {
    441   // Aura clears notifications from the message center at shutdown.
    442   message_center::MessageCenter::Initialize();
    443 
    444   // Required for extension service.
    445   content::TestBrowserThreadBundle thread_bundle;
    446 
    447   scoped_ptr<TestingProfileManager> profile_manager =
    448       CreateTestingProfileManager();
    449 
    450   // BackgroundModeManager actually affects Chrome start/stop state,
    451   // tearing down our thread bundle before we've had chance to clean
    452   // everything up. Keeping Chrome alive prevents this.
    453   // We aren't interested in if the keep alive works correctly in this test.
    454   chrome::IncrementKeepAliveCount();
    455   TestingProfile* profile = profile_manager->CreateTestingProfile("p");
    456 
    457 #if defined(OS_CHROMEOS)
    458   // ChromeOS needs extra services to run in the following order.
    459   chromeos::ScopedTestDeviceSettingsService test_device_settings_service;
    460   chromeos::ScopedTestCrosSettings test_cros_settings;
    461   chromeos::ScopedTestUserManager test_user_manager;
    462 
    463   // On ChromeOS shutdown, HandleAppExitingForPlatform will call
    464   // chrome::DecrementKeepAliveCount because it assumes the aura shell
    465   // called chrome::IncrementKeepAliveCount. Simulate the call here.
    466   chrome::IncrementKeepAliveCount();
    467 #endif
    468 
    469   scoped_refptr<extensions::Extension> component_extension(
    470     CreateExtension(
    471         extensions::Manifest::COMPONENT,
    472         "{\"name\": \"Component Extension\","
    473         "\"version\": \"1.0\","
    474         "\"manifest_version\": 2,"
    475         "\"permissions\": [\"background\"]}",
    476         "ID-1"));
    477 
    478   scoped_refptr<extensions::Extension> component_extension_with_options(
    479     CreateExtension(
    480         extensions::Manifest::COMPONENT,
    481         "{\"name\": \"Component Extension with Options\","
    482         "\"version\": \"1.0\","
    483         "\"manifest_version\": 2,"
    484         "\"permissions\": [\"background\"],"
    485         "\"options_page\": \"test.html\"}",
    486         "ID-2"));
    487 
    488   scoped_refptr<extensions::Extension> regular_extension(
    489     CreateExtension(
    490         extensions::Manifest::COMMAND_LINE,
    491         "{\"name\": \"Regular Extension\", "
    492         "\"version\": \"1.0\","
    493         "\"manifest_version\": 2,"
    494         "\"permissions\": [\"background\"]}",
    495         "ID-3"));
    496 
    497   scoped_refptr<extensions::Extension> regular_extension_with_options(
    498     CreateExtension(
    499         extensions::Manifest::COMMAND_LINE,
    500         "{\"name\": \"Regular Extension with Options\","
    501         "\"version\": \"1.0\","
    502         "\"manifest_version\": 2,"
    503         "\"permissions\": [\"background\"],"
    504         "\"options_page\": \"test.html\"}",
    505         "ID-4"));
    506 
    507   static_cast<extensions::TestExtensionSystem*>(
    508       extensions::ExtensionSystem::Get(profile))->CreateExtensionService(
    509           CommandLine::ForCurrentProcess(),
    510           base::FilePath(),
    511           false);
    512   ExtensionService* service = profile->GetExtensionService();
    513   service->Init();
    514 
    515   service->AddComponentExtension(component_extension);
    516   service->AddComponentExtension(component_extension_with_options);
    517   service->AddExtension(regular_extension);
    518   service->AddExtension(regular_extension_with_options);
    519 
    520   scoped_ptr<TestBackgroundModeManager> manager(new TestBackgroundModeManager(
    521       command_line_.get(), profile_manager->profile_info_cache(), true));
    522   manager->RegisterProfile(profile);
    523 
    524   scoped_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(NULL));
    525   scoped_ptr<StatusIconMenuModel> submenu(new StatusIconMenuModel(NULL));
    526   BackgroundModeManager::BackgroundModeData* bmd =
    527       manager->GetBackgroundModeData(profile);
    528   bmd->BuildProfileMenu(submenu.get(), menu.get());
    529   EXPECT_TRUE(
    530       submenu->GetLabelAt(0) ==
    531           base::UTF8ToUTF16("Component Extension"));
    532   EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0)));
    533   EXPECT_TRUE(
    534       submenu->GetLabelAt(1) ==
    535           base::UTF8ToUTF16("Component Extension with Options"));
    536   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1)));
    537   EXPECT_TRUE(
    538       submenu->GetLabelAt(2) ==
    539           base::UTF8ToUTF16("Regular Extension"));
    540   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2)));
    541   EXPECT_TRUE(
    542       submenu->GetLabelAt(3) ==
    543           base::UTF8ToUTF16("Regular Extension with Options"));
    544   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3)));
    545 
    546   // We have to destroy the profile now because we created it with real thread
    547   // state. This causes a lot of machinery to spin up that stops working
    548   // when we tear down our thread state at the end of the test.
    549   profile_manager->DeleteTestingProfile("p");
    550 
    551   // We're getting ready to shutdown the message loop. Clear everything out!
    552   base::MessageLoop::current()->RunUntilIdle();
    553   chrome::DecrementKeepAliveCount();  // Matching the above
    554                                       // chrome::IncrementKeepAliveCount().
    555 
    556   // TestBackgroundModeManager has dependencies on the infrastructure.
    557   // It should get cleared first.
    558   manager.reset();
    559 
    560   // The Profile Manager references the Browser Process.
    561   // The Browser Process references the Notification UI Manager.
    562   // The Notification UI Manager references the Message Center.
    563   // As a result, we have to clear the browser process state here
    564   // before tearing down the Message Center.
    565   profile_manager.reset();
    566 
    567   // Message Center shutdown must occur after the DecrementKeepAliveCount
    568   // because DecrementKeepAliveCount will end up referencing the message
    569   // center during cleanup.
    570   message_center::MessageCenter::Shutdown();
    571 
    572   // Clear the shutdown flag to isolate the remaining effect of this test.
    573   browser_shutdown::SetTryingToQuit(false);
    574 }
    575 
    576 TEST_F(BackgroundModeManagerTest, BackgroundMenuGenerationMultipleProfile) {
    577   // Aura clears notifications from the message center at shutdown.
    578   message_center::MessageCenter::Initialize();
    579 
    580   // Required for extension service.
    581   content::TestBrowserThreadBundle thread_bundle;
    582 
    583   scoped_ptr<TestingProfileManager> profile_manager =
    584       CreateTestingProfileManager();
    585 
    586   // BackgroundModeManager actually affects Chrome start/stop state,
    587   // tearing down our thread bundle before we've had chance to clean
    588   // everything up. Keeping Chrome alive prevents this.
    589   // We aren't interested in if the keep alive works correctly in this test.
    590   chrome::IncrementKeepAliveCount();
    591   TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1");
    592   TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2");
    593 
    594 #if defined(OS_CHROMEOS)
    595   // ChromeOS needs extensionsra services to run in the following order.
    596   chromeos::ScopedTestDeviceSettingsService test_device_settings_service;
    597   chromeos::ScopedTestCrosSettings test_cros_settings;
    598   chromeos::ScopedTestUserManager test_user_manager;
    599 
    600   // On ChromeOS shutdown, HandleAppExitingForPlatform will call
    601   // chrome::DecrementKeepAliveCount because it assumes the aura shell
    602   // called chrome::IncrementKeepAliveCount. Simulate the call here.
    603   chrome::IncrementKeepAliveCount();
    604 #endif
    605 
    606   scoped_refptr<extensions::Extension> component_extension(
    607     CreateExtension(
    608         extensions::Manifest::COMPONENT,
    609         "{\"name\": \"Component Extension\","
    610         "\"version\": \"1.0\","
    611         "\"manifest_version\": 2,"
    612         "\"permissions\": [\"background\"]}",
    613         "ID-1"));
    614 
    615   scoped_refptr<extensions::Extension> component_extension_with_options(
    616     CreateExtension(
    617         extensions::Manifest::COMPONENT,
    618         "{\"name\": \"Component Extension with Options\","
    619         "\"version\": \"1.0\","
    620         "\"manifest_version\": 2,"
    621         "\"permissions\": [\"background\"],"
    622         "\"options_page\": \"test.html\"}",
    623         "ID-2"));
    624 
    625   scoped_refptr<extensions::Extension> regular_extension(
    626     CreateExtension(
    627         extensions::Manifest::COMMAND_LINE,
    628         "{\"name\": \"Regular Extension\", "
    629         "\"version\": \"1.0\","
    630         "\"manifest_version\": 2,"
    631         "\"permissions\": [\"background\"]}",
    632         "ID-3"));
    633 
    634   scoped_refptr<extensions::Extension> regular_extension_with_options(
    635     CreateExtension(
    636         extensions::Manifest::COMMAND_LINE,
    637         "{\"name\": \"Regular Extension with Options\","
    638         "\"version\": \"1.0\","
    639         "\"manifest_version\": 2,"
    640         "\"permissions\": [\"background\"],"
    641         "\"options_page\": \"test.html\"}",
    642         "ID-4"));
    643 
    644   static_cast<extensions::TestExtensionSystem*>(
    645       extensions::ExtensionSystem::Get(profile1))->CreateExtensionService(
    646           CommandLine::ForCurrentProcess(),
    647           base::FilePath(),
    648           false);
    649   ExtensionService* service1 = profile1->GetExtensionService();
    650   service1->Init();
    651 
    652   service1->AddComponentExtension(component_extension);
    653   service1->AddComponentExtension(component_extension_with_options);
    654   service1->AddExtension(regular_extension);
    655   service1->AddExtension(regular_extension_with_options);
    656 
    657   static_cast<extensions::TestExtensionSystem*>(
    658       extensions::ExtensionSystem::Get(profile2))->CreateExtensionService(
    659           CommandLine::ForCurrentProcess(),
    660           base::FilePath(),
    661           false);
    662   ExtensionService* service2 = profile2->GetExtensionService();
    663   service2->Init();
    664 
    665   service2->AddComponentExtension(component_extension);
    666   service2->AddExtension(regular_extension);
    667   service2->AddExtension(regular_extension_with_options);
    668 
    669   scoped_ptr<TestBackgroundModeManager> manager(new TestBackgroundModeManager(
    670       command_line_.get(), profile_manager->profile_info_cache(), true));
    671   manager->RegisterProfile(profile1);
    672   manager->RegisterProfile(profile2);
    673 
    674   manager->status_icon_ = new TestStatusIcon();
    675   manager->UpdateStatusTrayIconContextMenu();
    676   StatusIconMenuModel* context_menu = manager->context_menu_;
    677   EXPECT_TRUE(context_menu != NULL);
    678 
    679   // Background Profile Enable Checks
    680   EXPECT_TRUE(context_menu->GetLabelAt(3) == base::UTF8ToUTF16("p1"));
    681   EXPECT_TRUE(
    682       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3)));
    683   EXPECT_TRUE(context_menu->GetCommandIdAt(3) == 4);
    684 
    685   EXPECT_TRUE(context_menu->GetLabelAt(4) == base::UTF8ToUTF16("p2"));
    686   EXPECT_TRUE(
    687       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4)));
    688   EXPECT_TRUE(context_menu->GetCommandIdAt(4) == 8);
    689 
    690   // Profile 1 Submenu Checks
    691   StatusIconMenuModel* profile1_submenu =
    692       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(3));
    693   EXPECT_TRUE(
    694       profile1_submenu->GetLabelAt(0) ==
    695           base::UTF8ToUTF16("Component Extension"));
    696   EXPECT_FALSE(
    697       profile1_submenu->IsCommandIdEnabled(
    698           profile1_submenu->GetCommandIdAt(0)));
    699   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(0) == 0);
    700   EXPECT_TRUE(
    701       profile1_submenu->GetLabelAt(1) ==
    702           base::UTF8ToUTF16("Component Extension with Options"));
    703   EXPECT_TRUE(
    704       profile1_submenu->IsCommandIdEnabled(
    705           profile1_submenu->GetCommandIdAt(1)));
    706   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(1) == 1);
    707   EXPECT_TRUE(
    708       profile1_submenu->GetLabelAt(2) ==
    709           base::UTF8ToUTF16("Regular Extension"));
    710   EXPECT_TRUE(
    711       profile1_submenu->IsCommandIdEnabled(
    712           profile1_submenu->GetCommandIdAt(2)));
    713   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(2) == 2);
    714   EXPECT_TRUE(
    715       profile1_submenu->GetLabelAt(3) ==
    716           base::UTF8ToUTF16("Regular Extension with Options"));
    717   EXPECT_TRUE(
    718       profile1_submenu->IsCommandIdEnabled(
    719           profile1_submenu->GetCommandIdAt(3)));
    720   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(3) == 3);
    721 
    722   // Profile 2 Submenu Checks
    723   StatusIconMenuModel* profile2_submenu =
    724       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(4));
    725   EXPECT_TRUE(
    726       profile2_submenu->GetLabelAt(0) ==
    727           base::UTF8ToUTF16("Component Extension"));
    728   EXPECT_FALSE(
    729       profile2_submenu->IsCommandIdEnabled(
    730           profile2_submenu->GetCommandIdAt(0)));
    731   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(0) == 5);
    732   EXPECT_TRUE(
    733       profile2_submenu->GetLabelAt(1) ==
    734           base::UTF8ToUTF16("Regular Extension"));
    735   EXPECT_TRUE(
    736       profile2_submenu->IsCommandIdEnabled(
    737           profile2_submenu->GetCommandIdAt(1)));
    738   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(1) == 6);
    739   EXPECT_TRUE(
    740       profile2_submenu->GetLabelAt(2) ==
    741           base::UTF8ToUTF16("Regular Extension with Options"));
    742   EXPECT_TRUE(
    743       profile2_submenu->IsCommandIdEnabled(
    744           profile2_submenu->GetCommandIdAt(2)));
    745   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(2) == 7);
    746 
    747   // Model Adapter Checks for crbug.com/315164
    748   // P1: Profile 1 Menu Item
    749   // P2: Profile 2 Menu Item
    750   // CE: Component Extension Menu Item
    751   // CEO: Component Extenison with Options Menu Item
    752   // RE: Regular Extension Menu Item
    753   // REO: Regular Extension with Options Menu Item
    754   EXPECT_FALSE(IsCommandEnabled(context_menu, 0)); // P1 - CE
    755   EXPECT_TRUE(IsCommandEnabled(context_menu, 1));  // P1 - CEO
    756   EXPECT_TRUE(IsCommandEnabled(context_menu, 2));  // P1 - RE
    757   EXPECT_TRUE(IsCommandEnabled(context_menu, 3));  // P1 - REO
    758   EXPECT_TRUE(IsCommandEnabled(context_menu, 4));  // P1
    759   EXPECT_FALSE(IsCommandEnabled(context_menu, 5)); // P2 - CE
    760   EXPECT_TRUE(IsCommandEnabled(context_menu, 6));  // P2 - RE
    761   EXPECT_TRUE(IsCommandEnabled(context_menu, 7));  // P2 - REO
    762   EXPECT_TRUE(IsCommandEnabled(context_menu, 8));  // P2
    763 
    764   // Clean up the status icon. If this is not done before profile deletes,
    765   // the context menu updates will DCHECK with the now deleted profiles.
    766   StatusIcon* status_icon = manager->status_icon_;
    767   manager->status_icon_ = NULL;
    768   delete status_icon;
    769 
    770   // We have to destroy the profiles now because we created them with real
    771   // thread state. This causes a lot of machinery to spin up that stops working
    772   // when we tear down our thread state at the end of the test.
    773   profile_manager->DeleteTestingProfile("p2");
    774   profile_manager->DeleteTestingProfile("p1");
    775 
    776   // We're getting ready to shutdown the message loop. Clear everything out!
    777   base::MessageLoop::current()->RunUntilIdle();
    778   chrome::DecrementKeepAliveCount();  // Matching the above
    779                                       // chrome::IncrementKeepAliveCount().
    780 
    781   // TestBackgroundModeManager has dependencies on the infrastructure.
    782   // It should get cleared first.
    783   manager.reset();
    784 
    785   // The Profile Manager references the Browser Process.
    786   // The Browser Process references the Notification UI Manager.
    787   // The Notification UI Manager references the Message Center.
    788   // As a result, we have to clear the browser process state here
    789   // before tearing down the Message Center.
    790   profile_manager.reset();
    791 
    792   // Message Center shutdown must occur after the DecrementKeepAliveCount
    793   // because DecrementKeepAliveCount will end up referencing the message
    794   // center during cleanup.
    795   message_center::MessageCenter::Shutdown();
    796 
    797   // Clear the shutdown flag to isolate the remaining effect of this test.
    798   browser_shutdown::SetTryingToQuit(false);
    799 }
    800