Commit f35770b2 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

Don't send background app notifications during Browser startup.

This restores behavior broken by 6670c336

Change the name of BackgroundApplicationListModel::is_ready() to
startup_done() to disambiguate from ExtensionService::is_ready().

Move BackgroundContentsService observation to OnExtensionSystemReady()
so we don't run BackgroundApplicationListModel::Update() too early.
Note that it's not sufficient to check whether the ExtensionService is
ready because it may return true before
BackgroundApplicationListModel::OnExtensionSystemReady runs.

Bug: 1008890
Change-Id: Ib3e5013e7857e7a9aa6f94ed6b43f3839e08fe00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1837486Reviewed-by: default avatarDrew Wilson <atwilson@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Commit-Queue: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703319}
parent 391665de
...@@ -147,9 +147,6 @@ BackgroundApplicationListModel::~BackgroundApplicationListModel() = default; ...@@ -147,9 +147,6 @@ BackgroundApplicationListModel::~BackgroundApplicationListModel() = default;
BackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile) BackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile)
: profile_(profile) { : profile_(profile) {
DCHECK(profile_); DCHECK(profile_);
background_contents_service_observer_.Add(
BackgroundContentsServiceFactory::GetForProfile(profile));
registrar_.Add(this, registrar_.Add(this,
extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
content::Source<Profile>(profile)); content::Source<Profile>(profile));
...@@ -309,7 +306,6 @@ void BackgroundApplicationListModel::OnExtensionUnloaded( ...@@ -309,7 +306,6 @@ void BackgroundApplicationListModel::OnExtensionUnloaded(
} }
void BackgroundApplicationListModel::OnExtensionSystemReady() { void BackgroundApplicationListModel::OnExtensionSystemReady() {
ready_ = true;
// All initial extensions will be loaded when extension system ready. So we // All initial extensions will be loaded when extension system ready. So we
// can get everything here. // can get everything here.
Update(); Update();
...@@ -321,6 +317,11 @@ void BackgroundApplicationListModel::OnExtensionSystemReady() { ...@@ -321,6 +317,11 @@ void BackgroundApplicationListModel::OnExtensionSystemReady() {
// for the extension system, which isn't a guarantee. Thus, register here and // for the extension system, which isn't a guarantee. Thus, register here and
// associate all initial extensions. // associate all initial extensions.
extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
background_contents_service_observer_.Add(
BackgroundContentsServiceFactory::GetForProfile(profile_));
startup_done_ = true;
} }
void BackgroundApplicationListModel::OnShutdown(ExtensionRegistry* registry) { void BackgroundApplicationListModel::OnShutdown(ExtensionRegistry* registry) {
...@@ -367,11 +368,9 @@ void BackgroundApplicationListModel::RemoveObserver(Observer* observer) { ...@@ -367,11 +368,9 @@ void BackgroundApplicationListModel::RemoveObserver(Observer* observer) {
// differs from the old list, it generates OnApplicationListChanged events for // differs from the old list, it generates OnApplicationListChanged events for
// each observer. // each observer.
void BackgroundApplicationListModel::Update() { void BackgroundApplicationListModel::Update() {
if (!ready_)
return;
extensions::ExtensionService* service = extensions::ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service(); extensions::ExtensionSystem::Get(profile_)->extension_service();
DCHECK(service->is_ready());
// Discover current background applications, compare with previous list, which // Discover current background applications, compare with previous list, which
// is consistently sorted, and notify observers if they differ. // is consistently sorted, and notify observers if they differ.
......
...@@ -101,9 +101,7 @@ class BackgroundApplicationListModel ...@@ -101,9 +101,7 @@ class BackgroundApplicationListModel
} }
// Returns true if all startup notifications have already been issued. // Returns true if all startup notifications have already been issued.
bool is_ready() const { bool startup_done() const { return startup_done_; }
return ready_;
}
private: private:
// Contains data associated with a background application that is not // Contains data associated with a background application that is not
...@@ -167,7 +165,7 @@ class BackgroundApplicationListModel ...@@ -167,7 +165,7 @@ class BackgroundApplicationListModel
base::ObserverList<Observer, true>::Unchecked observers_; base::ObserverList<Observer, true>::Unchecked observers_;
Profile* const profile_; Profile* const profile_;
content::NotificationRegistrar registrar_; content::NotificationRegistrar registrar_;
bool ready_{false}; bool startup_done_ = false;
// Listens to extension load, unload notifications. // Listens to extension load, unload notifications.
ScopedObserver<extensions::ExtensionRegistry, ScopedObserver<extensions::ExtensionRegistry,
......
...@@ -156,7 +156,7 @@ TEST_F(BackgroundApplicationListModelTest, DISABLED_ExplicitTest) { ...@@ -156,7 +156,7 @@ TEST_F(BackgroundApplicationListModelTest, DISABLED_ExplicitTest) {
service()->Init(); service()->Init();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_TRUE(service()->is_ready()); ASSERT_TRUE(service()->is_ready());
ASSERT_TRUE(model()->is_ready()); ASSERT_TRUE(model()->startup_done());
ASSERT_TRUE(registry()->enabled_extensions().is_empty()); ASSERT_TRUE(registry()->enabled_extensions().is_empty());
ASSERT_EQ(0U, model()->size()); ASSERT_EQ(0U, model()->size());
...@@ -296,11 +296,11 @@ TEST_F(BackgroundApplicationListModelTest, ExtensionLoadAndUnload) { ...@@ -296,11 +296,11 @@ TEST_F(BackgroundApplicationListModelTest, ExtensionLoadAndUnload) {
TEST_F(BackgroundApplicationListModelTest, LateExtensionSystemReady) { TEST_F(BackgroundApplicationListModelTest, LateExtensionSystemReady) {
ASSERT_FALSE(service()->is_ready()); ASSERT_FALSE(service()->is_ready());
ASSERT_FALSE(model()->is_ready()); ASSERT_FALSE(model()->startup_done());
service()->Init(); service()->Init();
// Model is not ready yet since ExtensionSystem::ready() is dispatched using // Model is not ready yet since ExtensionSystem::ready() is dispatched using
// PostTask to UI Thread. and OnExtensionSystemReady is not called yet. // PostTask to UI Thread. and OnExtensionSystemReady is not called yet.
ASSERT_FALSE(model()->is_ready()); ASSERT_FALSE(model()->startup_done());
scoped_refptr<Extension> bgapp = scoped_refptr<Extension> bgapp =
CreateExtension("background_application", true); CreateExtension("background_application", true);
...@@ -314,13 +314,13 @@ TEST_F(BackgroundApplicationListModelTest, LateExtensionSystemReady) { ...@@ -314,13 +314,13 @@ TEST_F(BackgroundApplicationListModelTest, LateExtensionSystemReady) {
service()->AddExtension(bgapp.get()); service()->AddExtension(bgapp.get());
load_observer.WaitForExtensionLoaded(); load_observer.WaitForExtensionLoaded();
EXPECT_EQ(1U, registry()->enabled_extensions().size()); EXPECT_EQ(1U, registry()->enabled_extensions().size());
// Model still has 0 item. since OnExtensionSystemReady is not called yet. // Model still has 0 items since OnExtensionSystemReady is not called yet.
EXPECT_EQ(0U, model()->size()); EXPECT_EQ(0U, model()->size());
// Wait Until OnExtensionSystemReady called. // Wait Until OnExtensionSystemReady called.
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
// Make sure background model holds extensions. // Make sure background model holds extensions.
EXPECT_TRUE(model()->is_ready()); EXPECT_TRUE(model()->startup_done());
EXPECT_EQ(1U, model()->size()); EXPECT_EQ(1U, model()->size());
} }
......
...@@ -206,7 +206,7 @@ BackgroundModeManager::BackgroundModeData::GetNewBackgroundApps() { ...@@ -206,7 +206,7 @@ BackgroundModeManager::BackgroundModeData::GetNewBackgroundApps() {
current_extensions_.insert(id); current_extensions_.insert(id);
// If this application has been newly loaded after the initial startup, // If this application has been newly loaded after the initial startup,
// notify the user. // notify the user.
if (applications_->is_ready()) if (applications_->startup_done())
new_apps.insert(application.get()); new_apps.insert(application.get());
} }
} }
...@@ -744,6 +744,7 @@ void BackgroundModeManager::OnBackgroundClientInstalled( ...@@ -744,6 +744,7 @@ void BackgroundModeManager::OnBackgroundClientInstalled(
EnableBackgroundMode(); EnableBackgroundMode();
ResumeBackgroundMode(); ResumeBackgroundMode();
++client_installed_notifications_;
// Notify the user that a background client has been installed. // Notify the user that a background client has been installed.
DisplayClientInstalledNotification(name); DisplayClientInstalledNotification(name);
} }
......
...@@ -108,6 +108,10 @@ class BackgroundModeManager : public content::NotificationObserver, ...@@ -108,6 +108,10 @@ class BackgroundModeManager : public content::NotificationObserver,
// For testing purposes. // For testing purposes.
size_t NumberOfBackgroundModeData(); size_t NumberOfBackgroundModeData();
int client_installed_notifications_for_test() {
return client_installed_notifications_;
}
private: private:
friend class AppBackgroundPageApiTest; friend class AppBackgroundPageApiTest;
friend class BackgroundModeManagerTest; friend class BackgroundModeManagerTest;
...@@ -395,6 +399,10 @@ class BackgroundModeManager : public content::NotificationObserver, ...@@ -395,6 +399,10 @@ class BackgroundModeManager : public content::NotificationObserver,
// app). // app).
bool keep_alive_for_test_ = false; bool keep_alive_for_test_ = false;
// Tracks the number of "background app installed" notifications shown to the
// user. Used for testing.
int client_installed_notifications_ = 0;
// Set to true when background mode is suspended. // Set to true when background mode is suspended.
bool background_mode_suspended_ = false; bool background_mode_suspended_ = false;
......
...@@ -9,71 +9,54 @@ ...@@ -9,71 +9,54 @@
#include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/background/background_mode_manager.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "extensions/browser/test_extension_registry_observer.h"
class TestBackgroundModeManager : public BackgroundModeManager { namespace extensions {
public:
TestBackgroundModeManager(const base::CommandLine& command_line,
ProfileAttributesStorage* profile_storage)
: BackgroundModeManager(command_line, profile_storage),
showed_background_app_installed_notification_for_test_(false) {}
~TestBackgroundModeManager() override {} using BackgroundAppBrowserTest = ExtensionBrowserTest;
void DisplayClientInstalledNotification(const base::string16& name) override {
showed_background_app_installed_notification_for_test_ = true;
}
bool showed_background_app_installed_notification_for_test() {
return showed_background_app_installed_notification_for_test_;
}
void set_showed_background_app_installed_notification_for_test(
bool showed) {
showed_background_app_installed_notification_for_test_ = showed;
}
private:
// Tracks if we have shown a "Background App Installed" notification to the
// user. Used for unit tests only.
bool showed_background_app_installed_notification_for_test_;
FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
ReloadBackgroundApp);
DISALLOW_COPY_AND_ASSIGN(TestBackgroundModeManager);
};
using BackgroundAppBrowserTest = extensions::ExtensionBrowserTest;
// Tests that if we reload a background app, we don't get a popup bubble // Tests that if we reload a background app, we don't get a popup bubble
// telling us that a new background app has been installed. // telling us that a new background app has been installed.
IN_PROC_BROWSER_TEST_F(BackgroundAppBrowserTest, ReloadBackgroundApp) { IN_PROC_BROWSER_TEST_F(BackgroundAppBrowserTest, ReloadBackgroundApp) {
// Pass this in to the browser test. BackgroundModeManager* manager = g_browser_process->background_mode_manager();
std::unique_ptr<BackgroundModeManager> test_background_mode_manager(
new TestBackgroundModeManager(*base::CommandLine::ForCurrentProcess(),
&(g_browser_process->profile_manager()
->GetProfileAttributesStorage())));
g_browser_process->set_background_mode_manager_for_test(
std::move(test_background_mode_manager));
TestBackgroundModeManager* manager =
reinterpret_cast<TestBackgroundModeManager*>(
g_browser_process->background_mode_manager());
// Load our background extension // Load our background extension
ASSERT_FALSE( EXPECT_EQ(0, manager->client_installed_notifications_for_test());
manager->showed_background_app_installed_notification_for_test()); const Extension* extension =
const extensions::Extension* extension = LoadExtension( LoadExtension(test_data_dir_.AppendASCII("background_app"));
test_data_dir_.AppendASCII("background_app")); EXPECT_EQ(1, manager->client_installed_notifications_for_test());
ASSERT_FALSE(extension == NULL); ASSERT_FALSE(extension == NULL);
// Set the test flag to not shown.
manager->set_showed_background_app_installed_notification_for_test(false);
// Reload our background extension // Reload our background extension
ReloadExtension(extension->id()); ReloadExtension(extension->id());
// Ensure that we did not see a "Background extension loaded" dialog. // Ensure that we did not see another "Background extension loaded" dialog.
EXPECT_FALSE( EXPECT_EQ(1, manager->client_installed_notifications_for_test());
manager->showed_background_app_installed_notification_for_test()); }
// Make sure that the background mode notification is sent for an app install,
// but not again on browser restart. Regression test for
// https://crbug.com/1008890
IN_PROC_BROWSER_TEST_F(BackgroundAppBrowserTest, PRE_InstallBackgroundApp) {
InstallExtension(test_data_dir_.AppendASCII("background_app"), 1);
EXPECT_EQ(1, g_browser_process->background_mode_manager()
->client_installed_notifications_for_test());
} }
IN_PROC_BROWSER_TEST_F(BackgroundAppBrowserTest, InstallBackgroundApp) {
// Verify the installed extension is still here.
const ExtensionSet& extensions = extension_registry()->enabled_extensions();
EXPECT_TRUE(
std::any_of(extensions.begin(), extensions.end(),
[](scoped_refptr<const Extension> extension) {
return extension->description() ==
"A simple app with background permission set.";
}));
// Verify the installed extension did not pop up a background mode
// notification.
EXPECT_EQ(0, g_browser_process->background_mode_manager()
->client_installed_notifications_for_test());
}
} // namespace extensions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment