blob: 5d338a6c73e1c6555185cbde1b030e45ce09c0d8 [file] [log] [blame]
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/background/extensions/background_mode_manager.h"
#include <stddef.h>
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_simple_task_runner.h"
#include "build/build_config.h"
#include "chrome/browser/background/startup_launch_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/status_icons/status_icon_menu_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_service_impl.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension_builder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image.h"
#include "ui/message_center/public/cpp/notifier_id.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/login/users/user_manager_delegate_impl.h"
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/browser_process.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_manager_impl.h"
#endif
using extensions::mojom::ManifestLocation;
using testing::_;
using testing::AtMost;
using testing::Exactly;
using testing::InSequence;
using testing::Mock;
using testing::NiceMock;
using testing::StrictMock;
namespace {
std::unique_ptr<TestingProfileManager> CreateTestingProfileManager() {
std::unique_ptr<TestingProfileManager> profile_manager(
new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
EXPECT_TRUE(profile_manager->SetUp());
return profile_manager;
}
// Helper class that tracks state transitions in BackgroundModeManager and
// exposes them via getters.
class TestBackgroundModeManager : public StrictMock<BackgroundModeManager> {
public:
TestBackgroundModeManager(const base::CommandLine& command_line,
ProfileAttributesStorage* storage)
: StrictMock<BackgroundModeManager>(command_line, storage) {
ResumeBackgroundMode();
}
TestBackgroundModeManager(TestBackgroundModeManager&) = delete;
TestBackgroundModeManager& operator=(TestBackgroundModeManager&) = delete;
~TestBackgroundModeManager() override = default;
// TODO: Use strict-mocking rather than keeping state through overrides below.
void DisplayClientInstalledNotification(const std::u16string& name) override {
has_shown_balloon_ = true;
}
void CreateStatusTrayIcon() override { have_status_tray_ = true; }
void RemoveStatusTrayIcon() override { have_status_tray_ = false; }
bool HaveStatusTray() const { return have_status_tray_; }
bool HasShownBalloon() const { return has_shown_balloon_; }
void SetHasShownBalloon(bool value) { has_shown_balloon_ = value; }
private:
// Flags to track whether we have a status tray/have shown the balloon.
bool have_status_tray_ = false;
bool has_shown_balloon_ = false;
};
class TestStatusIcon : public StatusIcon {
public:
TestStatusIcon() = default;
TestStatusIcon(TestStatusIcon&) = delete;
TestStatusIcon& operator=(TestStatusIcon&) = delete;
void SetImage(const gfx::ImageSkia& image) override {}
void SetToolTip(const std::u16string& tool_tip) override {}
void DisplayBalloon(const gfx::ImageSkia& icon,
const std::u16string& title,
const std::u16string& contents,
const message_center::NotifierId& notifier_id) override {}
void UpdatePlatformContextMenu(StatusIconMenuModel* menu) override {}
};
class TestStartupLaunchManager : public StartupLaunchManager {
public:
TestStartupLaunchManager() = default;
MOCK_METHOD1(UpdateLaunchOnStartup, void(bool should_launch_on_startup));
};
void AssertBackgroundModeActive(const TestBackgroundModeManager& manager) {
EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
EXPECT_TRUE(manager.HaveStatusTray());
}
void AssertBackgroundModeInactive(const TestBackgroundModeManager& manager) {
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
EXPECT_FALSE(manager.HaveStatusTray());
}
} // namespace
// More complex test helper that exposes APIs for fine grained control of
// things like the number of background applications. This allows writing
// smaller tests that don't have to install/uninstall extensions.
class AdvancedTestBackgroundModeManager : public TestBackgroundModeManager {
public:
AdvancedTestBackgroundModeManager(const base::CommandLine& command_line,
ProfileAttributesStorage* storage,
bool enabled)
: TestBackgroundModeManager(command_line, storage), enabled_(enabled) {}
AdvancedTestBackgroundModeManager(AdvancedTestBackgroundModeManager&) =
delete;
AdvancedTestBackgroundModeManager& operator=(
AdvancedTestBackgroundModeManager&) = delete;
~AdvancedTestBackgroundModeManager() override = default;
// TestBackgroundModeManager:
bool HasPersistentBackgroundClient() const override {
return std::ranges::any_of(
profile_app_counts_, [](const auto& profile_count_pair) {
return profile_count_pair.second.persistent > 0;
});
}
bool HasAnyBackgroundClient() const override {
return std::ranges::any_of(profile_app_counts_,
[](const auto& profile_count_pair) {
return profile_count_pair.second.any > 0;
});
}
bool HasPersistentBackgroundClientForProfile(
const Profile* profile) const override {
auto it = profile_app_counts_.find(profile);
if (it == profile_app_counts_.end()) {
ADD_FAILURE();
return false;
}
return it->second.persistent > 0;
}
bool IsBackgroundModePrefEnabled() const override { return enabled_; }
void SetBackgroundClientCountForProfile(const Profile* profile,
size_t count) {
profile_app_counts_[profile] = {count, count};
}
void SetPersistentBackgroundClientCountForProfile(const Profile* profile,
size_t count) {
profile_app_counts_[profile].persistent = count;
}
void SetEnabled(bool enabled) {
enabled_ = enabled;
OnBackgroundModeEnabledPrefChanged();
}
using BackgroundModeManager::OnApplicationListChanged;
private:
struct AppCounts {
size_t any = 0;
size_t persistent = 0;
};
bool enabled_;
std::map<const Profile*, AppCounts> profile_app_counts_;
};
class BackgroundModeManagerTest : public testing::Test {
public:
BackgroundModeManagerTest() = default;
BackgroundModeManagerTest(BackgroundModeManagerTest&) = delete;
BackgroundModeManagerTest& operator=(BackgroundModeManagerTest&) = delete;
~BackgroundModeManagerTest() override = default;
void SetUp() override {
command_line_ =
std::make_unique<base::CommandLine>(base::CommandLine::NO_PROGRAM);
auto policy_service = std::make_unique<policy::PolicyServiceImpl>(
std::vector<
raw_ptr<policy::ConfigurationPolicyProvider, VectorExperimental>>{
&policy_provider_});
profile_manager_ = CreateTestingProfileManager();
profile_ = profile_manager_->CreateTestingProfile(
"p1", nullptr, u"p1", 0, TestingProfile::TestingFactories(),
/*is_supervised_profile=*/false, std::nullopt,
std::move(policy_service));
startup_launch_manager_ = std::make_unique<TestStartupLaunchManager>();
StartupLaunchManager::SetInstanceForTesting(startup_launch_manager_.get());
}
TestStartupLaunchManager* startup_launch_manager() {
return startup_launch_manager_.get();
}
protected:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<base::CommandLine> command_line_;
std::unique_ptr<TestStartupLaunchManager> startup_launch_manager_;
NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
std::unique_ptr<TestingProfileManager> profile_manager_;
// Test profile used by all tests - this is owned by profile_manager_.
raw_ptr<TestingProfile> profile_;
};
class BackgroundModeManagerWithExtensionsTest : public testing::Test {
public:
BackgroundModeManagerWithExtensionsTest() = default;
BackgroundModeManagerWithExtensionsTest(
BackgroundModeManagerWithExtensionsTest&) = delete;
BackgroundModeManagerWithExtensionsTest& operator=(
BackgroundModeManagerWithExtensionsTest&) = delete;
~BackgroundModeManagerWithExtensionsTest() override = default;
void SetUp() override {
command_line_ =
std::make_unique<base::CommandLine>(base::CommandLine::NO_PROGRAM);
profile_manager_ = CreateTestingProfileManager();
profile_ = profile_manager_->CreateTestingProfile("p1");
test_keep_alive_ = std::make_unique<ScopedKeepAlive>(
KeepAliveOrigin::BACKGROUND_MODE_MANAGER,
KeepAliveRestartOption::DISABLED);
startup_launch_manager_ = std::make_unique<TestStartupLaunchManager>();
StartupLaunchManager::SetInstanceForTesting(startup_launch_manager_.get());
// Create our test BackgroundModeManager.
manager_ = std::make_unique<TestBackgroundModeManager>(
*command_line_, profile_manager_->profile_attributes_storage());
manager_->RegisterProfile(profile_);
}
void TearDown() override {
// Clean up the status icon. If this is not done before profile deletes,
// the context menu updates will DCHECK with the now deleted profiles.
manager_->status_icon_ = nullptr;
// We're getting ready to shutdown the message loop. Clear everything out!
base::RunLoop().RunUntilIdle();
// TestBackgroundModeManager has dependencies on the infrastructure.
// It should get cleared first.
manager_.reset();
// Now that the background manager is destroyed, the test KeepAlive can be
// cleared without having |manager_| attempt to perform optimizations.
test_keep_alive_.reset();
profile_ = nullptr;
// The Profile Manager references the Browser Process.
// The Browser Process references the Notification UI Manager.
// The Notification UI Manager references the Message Center.
// As a result, we have to clear the browser process state here
// before tearing down the Message Center.
profile_manager_.reset();
// Clear the shutdown flag to isolate the remaining effect of this test.
browser_shutdown::SetTryingToQuit(false);
}
TestStartupLaunchManager* startup_launch_manager() {
return startup_launch_manager_.get();
}
protected:
// From views::MenuModelAdapter::IsCommandEnabled with modification.
bool IsCommandEnabled(ui::MenuModel* model, int id) const {
size_t index = 0;
return ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index) &&
model->IsEnabledAt(index);
}
std::unique_ptr<TestBackgroundModeManager> manager_;
std::unique_ptr<base::CommandLine> command_line_;
std::unique_ptr<TestingProfileManager> profile_manager_;
// Test profile used by all tests - this is owned by profile_manager_.
raw_ptr<TestingProfile> profile_;
private:
// Required for extension service.
content::BrowserTaskEnvironment task_environment_;
// BackgroundModeManager actually affects Chrome start/stop state,
// tearing down our thread bundle before we've had chance to clean
// everything up. Keeping Chrome alive prevents this.
// We aren't interested in if the keep alive works correctly in this test.
std::unique_ptr<ScopedKeepAlive> test_keep_alive_;
std::unique_ptr<TestStartupLaunchManager> startup_launch_manager_;
#if BUILDFLAG(IS_CHROMEOS)
// ChromeOS needs extra services to run in the following order.
ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
user_manager::ScopedUserManager user_manager_{
std::make_unique<user_manager::UserManagerImpl>(
std::make_unique<UserManagerDelegateImpl>(),
g_browser_process->local_state(),
CrosSettings::Get())};
#endif
};
TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) {
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
// Mimic app load.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
manager.SuspendBackgroundMode();
AssertBackgroundModeInactive(manager);
manager.ResumeBackgroundMode();
// Mimic app unload.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
manager.SuspendBackgroundMode();
AssertBackgroundModeInactive(manager);
// Mimic app load while suspended, e.g. from sync. This should enable and
// resume background mode.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
}
// Apps installed while background mode is disabled should cause activation
// after it is enabled - crbug.com/527023.
TEST_F(BackgroundModeManagerTest, DISABLED_BackgroundAppInstallWhileDisabled) {
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
// Turn off background mode (shouldn't explicitly disable launch-on-startup as
// the app-count is zero and launch-on-startup shouldn't be considered on).
manager.SetEnabled(false);
AssertBackgroundModeInactive(manager);
// When a new client is installed, status tray icons will not be created,
// launch on startup status will not be modified.
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
AssertBackgroundModeInactive(manager);
// Turn back on background mode, should show status tray icon as there is now
// an app installed.
manager.SetEnabled(true);
AssertBackgroundModeActive(manager);
}
// Apps installed and uninstalled while background mode is disabled should do
// nothing.
TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
// Turn off background mode (should explicitly disable launch-on-startup as
// the app-count is zero and launch-on-startup hasn't been initialized yet).
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetEnabled(false);
AssertBackgroundModeInactive(manager);
Mock::VerifyAndClearExpectations(launch_manager);
// When a new client is installed, status tray icons will not be created,
// launch on startup status will not be modified.
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
AssertBackgroundModeInactive(manager);
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
AssertBackgroundModeInactive(manager);
// Re-enable background mode (shouldn't actually enable launch-on-startup as
// the app-count is zero).
manager.SetEnabled(true);
AssertBackgroundModeInactive(manager);
}
// Apps installed before background mode is disabled cause the icon to show up
// again when it is enabled.
TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
// Install app, should show status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
// OnBackgroundClientInstalled does not actually add an app to the
// BackgroundApplicationListModel which would result in another
// call to CreateStatusTray.
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
AssertBackgroundModeActive(manager);
Mock::VerifyAndClearExpectations(launch_manager);
// Turn off background mode - should hide status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetEnabled(false);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
// Turn back on background mode, should show status tray icon again as there
// was already an app installed before background mode was disabled.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.SetEnabled(true);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
// Uninstall app, should hide status tray icon again.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
}
TEST_F(BackgroundModeManagerTest, MultiProfile) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
manager.RegisterProfile(profile2);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
// Install app, should show status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
// Install app for other profile, should show other status tray icon.
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile2, 2);
manager.OnApplicationListChanged(profile2);
AssertBackgroundModeActive(manager);
// Should hide both status tray icons.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetEnabled(false);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
// Turn back on background mode - should show both status tray icons.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.SetEnabled(true);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
manager.SetBackgroundClientCountForProfile(profile2, 1);
manager.OnApplicationListChanged(profile2);
// There is still one background app alive
AssertBackgroundModeActive(manager);
// Verify the implicit expectations of no calls on this StrictMock.
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile2, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
}
TEST_F(BackgroundModeManagerTest, ProfileAttributesStorage) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
ProfileAttributesStorage* storage =
profile_manager_->profile_attributes_storage();
AdvancedTestBackgroundModeManager manager(*command_line_, storage, true);
manager.RegisterProfile(profile_);
manager.RegisterProfile(profile2);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
EXPECT_EQ(2u, storage->GetNumberOfProfiles());
ProfileAttributesEntry* entry1 =
storage->GetProfileAttributesWithPath(profile_->GetPath());
ASSERT_NE(entry1, nullptr);
ProfileAttributesEntry* entry2 =
storage->GetProfileAttributesWithPath(profile2->GetPath());
ASSERT_NE(entry2, nullptr);
EXPECT_FALSE(entry1->GetBackgroundStatus());
EXPECT_FALSE(entry2->GetBackgroundStatus());
// Install app, should show status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
// Install app for other profile.
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile2, 1);
manager.OnApplicationListChanged(profile2);
EXPECT_TRUE(entry1->GetBackgroundStatus());
EXPECT_TRUE(entry2->GetBackgroundStatus());
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
EXPECT_FALSE(entry1->GetBackgroundStatus());
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile2, 0);
manager.OnApplicationListChanged(profile2);
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_FALSE(entry2->GetBackgroundStatus());
// Even though neither has background status on, there should still be two
// profiles in the ProfileAttributesStorage.
EXPECT_EQ(2u, storage->GetNumberOfProfiles());
}
TEST_F(BackgroundModeManagerTest, ProfileAttributesStorageObserver) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
// Install app, should show status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
// Background mode should remain active for the remainder of this test.
manager.OnProfileNameChanged(profile_->GetPath(),
manager.GetBackgroundModeData(profile_)->name());
EXPECT_EQ(u"p1", manager.GetBackgroundModeData(profile_)->name());
EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
manager.RegisterProfile(profile2);
EXPECT_EQ(2U, manager.NumberOfBackgroundModeData());
manager.OnProfileAdded(profile2->GetPath());
EXPECT_EQ(u"p2", manager.GetBackgroundModeData(profile2)->name());
manager.OnProfileWillBeRemoved(profile2->GetPath());
// Should still be in background mode after deleting profile.
EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
EXPECT_EQ(1U, manager.NumberOfBackgroundModeData());
// Check that the background mode data we think is in the map actually is.
EXPECT_EQ(u"p1", manager.GetBackgroundModeData(profile_)->name());
}
TEST_F(BackgroundModeManagerTest, DeleteBackgroundProfile) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
// Tests whether deleting the only profile when it is a BG profile works
// or not (http://crbug.com/346214).
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
// Install app, should show status tray icon.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
manager.OnBackgroundClientInstalled(u"name");
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
manager.OnProfileNameChanged(profile_->GetPath(),
manager.GetBackgroundModeData(profile_)->name());
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnProfileWillBeRemoved(profile_->GetPath());
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
}
TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) {
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
command_line_->AppendSwitch(switches::kKeepAliveForTest);
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
EXPECT_TRUE(manager.ShouldBeInBackgroundMode());
// No enable-launch-on-startup calls expected yet.
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetEnabled(false);
EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
}
TEST_F(BackgroundModeManagerTest,
BackgroundModeDisabledPreventsKeepAliveOnStartup) {
command_line_->AppendSwitch(switches::kKeepAliveForTest);
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), false);
manager.RegisterProfile(profile_);
EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
}
TEST_F(BackgroundModeManagerWithExtensionsTest, BackgroundMenuGeneration) {
scoped_refptr<const extensions::Extension> component_extension =
extensions::ExtensionBuilder("Component Extension")
.SetLocation(ManifestLocation::kComponent)
.AddAPIPermission("background")
.Build();
scoped_refptr<const extensions::Extension> component_extension_with_options =
extensions::ExtensionBuilder("Component Extension with Options")
.SetLocation(ManifestLocation::kComponent)
.AddAPIPermission("background")
.SetManifestKey("options_page", "test.html")
.Build();
scoped_refptr<const extensions::Extension> regular_extension =
extensions::ExtensionBuilder("Regular Extension")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.Build();
scoped_refptr<const extensions::Extension> regular_extension_with_options =
extensions::ExtensionBuilder("Regular Extension with Options")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.SetManifestKey("options_page", "test.html")
.Build();
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->Init();
extensions::ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
service->Init();
// ExtensionSystem::ready() is dispatched using PostTask to UI Thread. Wait
// until idle so that BackgroundApplicationListModel::OnExtensionSystemReady
// called.
base::RunLoop().RunUntilIdle();
extensions::ExtensionRegistrar* registrar =
extensions::ExtensionRegistrar::Get(profile_);
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
registrar->AddComponentExtension(component_extension.get());
registrar->AddComponentExtension(component_extension_with_options.get());
registrar->AddExtension(regular_extension.get());
registrar->AddExtension(regular_extension_with_options.get());
Mock::VerifyAndClearExpectations(launch_manager);
auto menu = std::make_unique<StatusIconMenuModel>(nullptr);
auto submenu = std::make_unique<StatusIconMenuModel>(nullptr);
BackgroundModeManager::BackgroundModeData* bmd =
manager_->GetBackgroundModeData(profile_);
bmd->BuildProfileMenu(submenu.get(), menu.get());
EXPECT_EQ(submenu->GetLabelAt(0), u"Component Extension");
EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0)));
EXPECT_EQ(submenu->GetLabelAt(1), u"Component Extension with Options");
EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1)));
EXPECT_EQ(submenu->GetLabelAt(2), u"Regular Extension");
EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2)));
EXPECT_EQ(submenu->GetLabelAt(3), u"Regular Extension with Options");
EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3)));
}
TEST_F(BackgroundModeManagerWithExtensionsTest,
BackgroundMenuGenerationMultipleProfile) {
// Helper methods to build extensions; we build new instances so that each
// Extension object is only used in a single profile.
auto build_component_extension = []() {
return extensions::ExtensionBuilder("Component Extension")
.SetLocation(ManifestLocation::kComponent)
.AddAPIPermission("background")
.Build();
};
auto build_component_extension_with_options = []() {
return extensions::ExtensionBuilder("Component Extension with Options")
.SetLocation(ManifestLocation::kComponent)
.AddAPIPermission("background")
.SetManifestKey("options_page", "test.html")
.Build();
};
auto build_regular_extension = []() {
return extensions::ExtensionBuilder("Regular Extension")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.Build();
};
auto build_regular_extension_with_options = []() {
return extensions::ExtensionBuilder("Regular Extension with Options")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.SetManifestKey("options_page", "test.html")
.Build();
};
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
base::FilePath(), false);
extensions::ExtensionService* service1 =
extensions::ExtensionSystem::Get(profile_)->extension_service();
service1->Init();
base::RunLoop().RunUntilIdle();
extensions::ExtensionRegistrar* registrar1 =
extensions::ExtensionRegistrar::Get(profile_);
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
registrar1->AddComponentExtension(build_component_extension().get());
registrar1->AddComponentExtension(
build_component_extension_with_options().get());
registrar1->AddExtension(build_regular_extension().get());
registrar1->AddExtension(build_regular_extension_with_options().get());
Mock::VerifyAndClearExpectations(launch_manager);
TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
manager_->RegisterProfile(profile2);
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile2))
->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
base::FilePath(), false);
extensions::ExtensionService* service2 =
extensions::ExtensionSystem::Get(profile2)->extension_service();
service2->Init();
base::RunLoop().RunUntilIdle();
extensions::ExtensionRegistrar* registrar2 =
extensions::ExtensionRegistrar::Get(profile2);
registrar2->AddComponentExtension(build_component_extension().get());
registrar2->AddExtension(build_regular_extension().get());
registrar2->AddExtension(build_regular_extension_with_options().get());
std::unique_ptr<StatusIcon> test_status_icon =
std::make_unique<TestStatusIcon>();
manager_->status_icon_ = test_status_icon.get();
manager_->UpdateStatusTrayIconContextMenu();
StatusIconMenuModel* context_menu = manager_->context_menu_;
EXPECT_TRUE(context_menu);
// Background Profile Enable Checks
EXPECT_EQ(context_menu->GetLabelAt(3), u"p1");
EXPECT_TRUE(
context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3)));
EXPECT_EQ(context_menu->GetCommandIdAt(3), 4);
EXPECT_EQ(context_menu->GetLabelAt(4), u"p2");
EXPECT_TRUE(
context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4)));
EXPECT_EQ(context_menu->GetCommandIdAt(4), 8);
// Profile 1 Submenu Checks
StatusIconMenuModel* profile1_submenu =
static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(3));
EXPECT_EQ(profile1_submenu->GetLabelAt(0), u"Component Extension");
EXPECT_FALSE(profile1_submenu->IsCommandIdEnabled(
profile1_submenu->GetCommandIdAt(0)));
EXPECT_EQ(profile1_submenu->GetCommandIdAt(0), 0);
EXPECT_EQ(profile1_submenu->GetLabelAt(1),
u"Component Extension with Options");
EXPECT_TRUE(profile1_submenu->IsCommandIdEnabled(
profile1_submenu->GetCommandIdAt(1)));
EXPECT_EQ(profile1_submenu->GetCommandIdAt(1), 1);
EXPECT_EQ(profile1_submenu->GetLabelAt(2), u"Regular Extension");
EXPECT_TRUE(profile1_submenu->IsCommandIdEnabled(
profile1_submenu->GetCommandIdAt(2)));
EXPECT_EQ(profile1_submenu->GetCommandIdAt(2), 2);
EXPECT_EQ(profile1_submenu->GetLabelAt(3), u"Regular Extension with Options");
EXPECT_TRUE(profile1_submenu->IsCommandIdEnabled(
profile1_submenu->GetCommandIdAt(3)));
EXPECT_EQ(profile1_submenu->GetCommandIdAt(3), 3);
// Profile 2 Submenu Checks
StatusIconMenuModel* profile2_submenu =
static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(4));
EXPECT_EQ(profile2_submenu->GetLabelAt(0), u"Component Extension");
EXPECT_FALSE(profile2_submenu->IsCommandIdEnabled(
profile2_submenu->GetCommandIdAt(0)));
EXPECT_EQ(profile2_submenu->GetCommandIdAt(0), 5);
EXPECT_EQ(profile2_submenu->GetLabelAt(1), u"Regular Extension");
EXPECT_TRUE(profile2_submenu->IsCommandIdEnabled(
profile2_submenu->GetCommandIdAt(1)));
EXPECT_EQ(profile2_submenu->GetCommandIdAt(1), 6);
EXPECT_EQ(profile2_submenu->GetLabelAt(2), u"Regular Extension with Options");
EXPECT_TRUE(profile2_submenu->IsCommandIdEnabled(
profile2_submenu->GetCommandIdAt(2)));
EXPECT_EQ(profile2_submenu->GetCommandIdAt(2), 7);
// Model Adapter Checks for crbug.com/315164
// P1: Profile 1 Menu Item
// P2: Profile 2 Menu Item
// CE: Component Extension Menu Item
// CEO: Component Extenison with Options Menu Item
// RE: Regular Extension Menu Item
// REO: Regular Extension with Options Menu Item
EXPECT_FALSE(IsCommandEnabled(context_menu, 0)); // P1 - CE
EXPECT_TRUE(IsCommandEnabled(context_menu, 1)); // P1 - CEO
EXPECT_TRUE(IsCommandEnabled(context_menu, 2)); // P1 - RE
EXPECT_TRUE(IsCommandEnabled(context_menu, 3)); // P1 - REO
EXPECT_TRUE(IsCommandEnabled(context_menu, 4)); // P1
EXPECT_FALSE(IsCommandEnabled(context_menu, 5)); // P2 - CE
EXPECT_TRUE(IsCommandEnabled(context_menu, 6)); // P2 - RE
EXPECT_TRUE(IsCommandEnabled(context_menu, 7)); // P2 - REO
EXPECT_TRUE(IsCommandEnabled(context_menu, 8)); // P2
manager_->context_menu_ = nullptr;
manager_->status_icon_ = nullptr;
}
TEST_F(BackgroundModeManagerWithExtensionsTest, BalloonDisplay) {
scoped_refptr<const extensions::Extension> bg_ext =
extensions::ExtensionBuilder("Background Extension")
.SetVersion("1.0")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.Build();
scoped_refptr<const extensions::Extension> upgraded_bg_ext =
extensions::ExtensionBuilder("Background Extension")
.SetVersion("2.0")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.Build();
scoped_refptr<const extensions::Extension> no_bg_ext =
extensions::ExtensionBuilder("Regular Extension")
.SetVersion("1.0")
.SetLocation(ManifestLocation::kCommandLine)
.Build();
scoped_refptr<const extensions::Extension> upgraded_no_bg_ext_has_bg =
extensions::ExtensionBuilder("Regular Extension")
.SetVersion("1.0")
.SetLocation(ManifestLocation::kCommandLine)
.AddAPIPermission("background")
.Build();
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
base::FilePath(), false);
extensions::ExtensionSystem* system =
extensions::ExtensionSystem::Get(profile_);
ASSERT_FALSE(system->is_ready());
extensions::ExtensionService* service = system->extension_service();
service->Init();
base::RunLoop run_loop;
system->ready().Post(FROM_HERE, run_loop.QuitClosure());
run_loop.Run();
extensions::ExtensionRegistrar* registrar =
extensions::ExtensionRegistrar::Get(profile_);
ASSERT_TRUE(system->is_ready());
std::unique_ptr<StatusIcon> test_status_icon =
std::make_unique<TestStatusIcon>();
manager_->status_icon_ = test_status_icon.get();
manager_->UpdateStatusTrayIconContextMenu();
// Adding a background extension should show the balloon.
EXPECT_FALSE(manager_->HasShownBalloon());
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
registrar->AddExtension(bg_ext.get());
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_TRUE(manager_->HasShownBalloon());
// Adding an extension without background should not show the balloon.
manager_->SetHasShownBalloon(false);
registrar->AddExtension(no_bg_ext.get());
EXPECT_FALSE(manager_->HasShownBalloon());
// Upgrading an extension that has background should not reshow the balloon.
{
// TODO(crbug.com/41145854): Fix crbug.com/438376 and remove these checks.
InSequence expected_call_sequence;
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false))
.Times(Exactly(1));
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(Exactly(1));
}
registrar->AddExtension(upgraded_bg_ext.get());
Mock::VerifyAndClearExpectations(launch_manager);
EXPECT_FALSE(manager_->HasShownBalloon());
// Upgrading an extension that didn't have background to one that does should
// show the balloon.
registrar->AddExtension(upgraded_no_bg_ext_has_bg.get());
EXPECT_TRUE(manager_->HasShownBalloon());
manager_->context_menu_ = nullptr;
manager_->status_icon_ = nullptr;
}
TEST_F(BackgroundModeManagerTest, TransientBackgroundApp) {
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
ProfileAttributesEntry* entry =
profile_manager_->profile_attributes_storage()
->GetProfileAttributesWithPath(profile_->GetPath());
ASSERT_NE(entry, nullptr);
EXPECT_FALSE(entry->GetBackgroundStatus());
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
// Mimic transient app launch.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(_)).Times(0);
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.SetPersistentBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_FALSE(entry->GetBackgroundStatus());
manager.SuspendBackgroundMode();
AssertBackgroundModeInactive(manager);
EXPECT_FALSE(entry->GetBackgroundStatus());
manager.ResumeBackgroundMode();
// Mimic transient app shutdown.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(_)).Times(0);
manager.SetBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeInactive(manager);
EXPECT_FALSE(entry->GetBackgroundStatus());
}
TEST_F(BackgroundModeManagerTest, TransientBackgroundAppWithPersistent) {
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
ProfileAttributesEntry* entry =
profile_manager_->profile_attributes_storage()
->GetProfileAttributesWithPath(profile_->GetPath());
ASSERT_NE(entry, nullptr);
EXPECT_FALSE(entry->GetBackgroundStatus());
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(1);
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
// Mimic transient app launch.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(_)).Times(0);
manager.SetBackgroundClientCountForProfile(profile_, 2);
manager.SetPersistentBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
manager.SuspendBackgroundMode();
AssertBackgroundModeInactive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
manager.ResumeBackgroundMode();
// Mimic transient app shutdown.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(_)).Times(0);
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
}
TEST_F(BackgroundModeManagerTest,
BackgroundPersistentAppWhileTransientRunning) {
AdvancedTestBackgroundModeManager manager(
*command_line_, profile_manager_->profile_attributes_storage(), true);
manager.RegisterProfile(profile_);
ProfileAttributesEntry* entry =
profile_manager_->profile_attributes_storage()
->GetProfileAttributesWithPath(profile_->GetPath());
ASSERT_NE(entry, nullptr);
EXPECT_FALSE(entry->GetBackgroundStatus());
EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
// Mimic transient app launch.
TestStartupLaunchManager* const launch_manager = startup_launch_manager();
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.SetPersistentBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_FALSE(entry->GetBackgroundStatus());
// Mimic persistent app install.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(true)).Times(1);
manager.SetBackgroundClientCountForProfile(profile_, 2);
manager.SetPersistentBackgroundClientCountForProfile(profile_, 1);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
manager.SuspendBackgroundMode();
AssertBackgroundModeInactive(manager);
EXPECT_TRUE(entry->GetBackgroundStatus());
manager.ResumeBackgroundMode();
// Mimic persistent app uninstall.
EXPECT_CALL(*launch_manager, UpdateLaunchOnStartup(false)).Times(Exactly(1));
manager.SetBackgroundClientCountForProfile(profile_, 1);
manager.SetPersistentBackgroundClientCountForProfile(profile_, 0);
manager.OnApplicationListChanged(profile_);
Mock::VerifyAndClearExpectations(launch_manager);
AssertBackgroundModeActive(manager);
EXPECT_FALSE(entry->GetBackgroundStatus());
}
TEST_F(BackgroundModeManagerTest, ForceInstalledExtensionsKeepAlive) {
const auto* keep_alive_registry = KeepAliveRegistry::GetInstance();
EXPECT_FALSE(keep_alive_registry->IsKeepingAlive());
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch(switches::kNoStartupWindow);
TestBackgroundModeManager manager(
command_line, profile_manager_->profile_attributes_storage());
EXPECT_TRUE(keep_alive_registry->IsKeepingAlive());
EXPECT_TRUE(keep_alive_registry->WouldRestartWithout({
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_STARTUP,
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_FORCE_INSTALLED_EXTENSIONS,
}));
manager.RegisterProfile(profile_);
EXPECT_TRUE(keep_alive_registry->IsKeepingAlive());
EXPECT_TRUE(keep_alive_registry->WouldRestartWithout({
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_STARTUP,
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_FORCE_INSTALLED_EXTENSIONS,
}));
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->CreateExtensionService(&command_line, base::FilePath(), false);
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->SetReady();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(keep_alive_registry->IsKeepingAlive());
EXPECT_TRUE(keep_alive_registry->WouldRestartWithout({
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_FORCE_INSTALLED_EXTENSIONS,
}));
manager.GetBackgroundModeData(profile_)->OnForceInstalledExtensionsReady();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(keep_alive_registry->IsKeepingAlive());
}
TEST_F(BackgroundModeManagerTest,
ForceInstalledExtensionsKeepAliveReleasedOnAppTerminating) {
const auto* keep_alive_registry = KeepAliveRegistry::GetInstance();
EXPECT_FALSE(keep_alive_registry->IsKeepingAlive());
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch(switches::kNoStartupWindow);
TestBackgroundModeManager manager(
command_line, profile_manager_->profile_attributes_storage());
manager.RegisterProfile(profile_);
EXPECT_TRUE(keep_alive_registry->IsKeepingAlive());
EXPECT_TRUE(keep_alive_registry->WouldRestartWithout({
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_STARTUP,
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_FORCE_INSTALLED_EXTENSIONS,
}));
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->CreateExtensionService(&command_line, base::FilePath(), false);
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile_))
->SetReady();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(keep_alive_registry->IsKeepingAlive());
EXPECT_TRUE(keep_alive_registry->WouldRestartWithout({
KeepAliveOrigin::BACKGROUND_MODE_MANAGER_FORCE_INSTALLED_EXTENSIONS,
}));
manager.OnAppTerminating();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(keep_alive_registry->IsKeepingAlive());
}