Commit c63504e6 authored by Nigel Tao's avatar Nigel Tao Committed by Commit Bot

Add OnAppRegistryCacheWillBeDestroyed method

This allows cleanly breaking observer-observee reference cycles,
regardless of which object is destroyed first. Prior to this commit, the
implicit assumption was that the observer was always destroyed first.

A follow-up commit will introduce some tests that create and destroy
AppRegistryCache objects.

BUG=826982

Change-Id: I94966439001ba310b5ee824ff62e72a533887c0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1629892
Commit-Queue: Nigel Tao <nigeltao@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarLucas Tenório <ltenorio@chromium.org>
Reviewed-by: default avatarYury Khmel <khmel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664095}
parent 7d455c05
...@@ -65,7 +65,7 @@ AppControllerService::AppControllerService(Profile* profile) ...@@ -65,7 +65,7 @@ AppControllerService::AppControllerService(Profile* profile)
app_service_proxy_(apps::AppServiceProxyFactory::GetForProfile(profile)), app_service_proxy_(apps::AppServiceProxyFactory::GetForProfile(profile)),
intent_config_helper_(IntentConfigHelper::GetInstance()) { intent_config_helper_(IntentConfigHelper::GetInstance()) {
DCHECK(profile); DCHECK(profile);
app_service_proxy_->AppRegistryCache().AddObserver(this); Observe(&app_service_proxy_->AppRegistryCache());
// Add the chrome://app-icon URL data source. // Add the chrome://app-icon URL data source.
// TODO(ltenorio): Move this to a more suitable location when we change // TODO(ltenorio): Move this to a more suitable location when we change
...@@ -74,9 +74,7 @@ AppControllerService::AppControllerService(Profile* profile) ...@@ -74,9 +74,7 @@ AppControllerService::AppControllerService(Profile* profile)
std::make_unique<apps::AppIconSource>(profile)); std::make_unique<apps::AppIconSource>(profile));
} }
AppControllerService::~AppControllerService() { AppControllerService::~AppControllerService() = default;
app_service_proxy_->AppRegistryCache().RemoveObserver(this);
}
void AppControllerService::BindRequest(mojom::AppControllerRequest request) { void AppControllerService::BindRequest(mojom::AppControllerRequest request) {
bindings_.AddBinding(this, std::move(request)); bindings_.AddBinding(this, std::move(request));
...@@ -171,6 +169,11 @@ void AppControllerService::OnAppUpdate(const apps::AppUpdate& update) { ...@@ -171,6 +169,11 @@ void AppControllerService::OnAppUpdate(const apps::AppUpdate& update) {
} }
} }
void AppControllerService::OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) {
Observe(nullptr);
}
void AppControllerService::SetIntentConfigHelperForTesting( void AppControllerService::SetIntentConfigHelperForTesting(
std::unique_ptr<IntentConfigHelper> helper) { std::unique_ptr<IntentConfigHelper> helper) {
intent_config_helper_ = std::move(helper); intent_config_helper_ = std::move(helper);
......
...@@ -59,6 +59,8 @@ class AppControllerService : public mojom::AppController, ...@@ -59,6 +59,8 @@ class AppControllerService : public mojom::AppController,
// apps::AppRegistryCache::Observer: // apps::AppRegistryCache::Observer:
void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppUpdate(const apps::AppUpdate& update) override;
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override;
// Allows overriding the intent config helper for tests. // Allows overriding the intent config helper for tests.
void SetIntentConfigHelperForTesting( void SetIntentConfigHelperForTesting(
......
...@@ -105,3 +105,8 @@ void AppServiceAppModelBuilder::OnAppUpdate(const apps::AppUpdate& update) { ...@@ -105,3 +105,8 @@ void AppServiceAppModelBuilder::OnAppUpdate(const apps::AppUpdate& update) {
profile(), model_updater(), GetSyncItem(update.AppId()), update)); profile(), model_updater(), GetSyncItem(update.AppId()), update));
} }
} }
void AppServiceAppModelBuilder::OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) {
Observe(nullptr);
}
...@@ -26,6 +26,8 @@ class AppServiceAppModelBuilder : public AppListModelBuilder, ...@@ -26,6 +26,8 @@ class AppServiceAppModelBuilder : public AppListModelBuilder,
// apps::AppRegistryCache::Observer overrides: // apps::AppRegistryCache::Observer overrides:
void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppUpdate(const apps::AppUpdate& update) override;
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override;
std::unique_ptr<AppListModelUpdaterObserver> crostini_folder_observer_; std::unique_ptr<AppListModelUpdaterObserver> crostini_folder_observer_;
......
...@@ -361,6 +361,11 @@ class AppServiceDataSource : public AppSearchProvider::DataSource, ...@@ -361,6 +361,11 @@ class AppServiceDataSource : public AppSearchProvider::DataSource,
} }
} }
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override {
Observe(nullptr);
}
// The AppServiceDataSource seems like one (but not the only) good place to // The AppServiceDataSource seems like one (but not the only) good place to
// add an App Service icon caching wrapper, because (1) the AppSearchProvider // add an App Service icon caching wrapper, because (1) the AppSearchProvider
// destroys and creates multiple search results in a short period of time, // destroys and creates multiple search results in a short period of time,
......
...@@ -220,3 +220,8 @@ void AppManagementPageHandler::OnAppUpdate(const apps::AppUpdate& update) { ...@@ -220,3 +220,8 @@ void AppManagementPageHandler::OnAppUpdate(const apps::AppUpdate& update) {
page_->OnAppChanged(CreateUIAppPtr(update)); page_->OnAppChanged(CreateUIAppPtr(update));
} }
} }
void AppManagementPageHandler::OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) {
Observe(nullptr);
}
...@@ -44,6 +44,8 @@ class AppManagementPageHandler : public app_management::mojom::PageHandler, ...@@ -44,6 +44,8 @@ class AppManagementPageHandler : public app_management::mojom::PageHandler,
// apps::AppRegistryCache::Observer overrides: // apps::AppRegistryCache::Observer overrides:
void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppUpdate(const apps::AppUpdate& update) override;
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override;
mojo::Binding<app_management::mojom::PageHandler> binding_; mojo::Binding<app_management::mojom::PageHandler> binding_;
......
...@@ -36,7 +36,12 @@ void AppRegistryCache::Observer::Observe(AppRegistryCache* cache) { ...@@ -36,7 +36,12 @@ void AppRegistryCache::Observer::Observe(AppRegistryCache* cache) {
AppRegistryCache::AppRegistryCache() = default; AppRegistryCache::AppRegistryCache() = default;
AppRegistryCache::~AppRegistryCache() = default; AppRegistryCache::~AppRegistryCache() {
for (auto& obs : observers_) {
obs.OnAppRegistryCacheWillBeDestroyed(this);
}
DCHECK(!observers_.might_have_observers());
}
void AppRegistryCache::AddObserver(Observer* observer) { void AppRegistryCache::AddObserver(Observer* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
......
...@@ -37,20 +37,27 @@ class AppRegistryCache { ...@@ -37,20 +37,27 @@ class AppRegistryCache {
// returns. // returns.
virtual void OnAppUpdate(const AppUpdate& update) = 0; virtual void OnAppUpdate(const AppUpdate& update) = 0;
// Called when the AppRegistryCache object (the thing that this observer
// observes) will be destroyed. In response, the observer, |this|, should
// call "cache->RemoveObserver(this)", whether directly or indirectly (e.g.
// via ScopedObserver::Remove or via Observe(nullptr)).
virtual void OnAppRegistryCacheWillBeDestroyed(AppRegistryCache* cache) = 0;
protected: protected:
// Use this constructor when the object is tied to a single // Use this constructor when the observer |this| is tied to a single
// AppRegistryCache for its entire lifetime. // AppRegistryCache for its entire lifetime, or until the observee (the
// AppRegistryCache) is destroyed, whichever comes first.
explicit Observer(AppRegistryCache* cache); explicit Observer(AppRegistryCache* cache);
// Use this constructor when the object wants to observe a AppRegistryCache // Use this constructor when the observer |this| wants to observe a
// for part of its lifetime. It can then call Observe() to start and stop // AppRegistryCache for part of its lifetime. It can then call Observe() to
// observing. // start and stop observing.
Observer(); Observer();
~Observer() override; ~Observer() override;
// Start observing a different AppRegistryCache; used with the default // Start observing a different AppRegistryCache. |cache| may be nullptr,
// constructor. // meaning to stop observing.
void Observe(AppRegistryCache* cache); void Observe(AppRegistryCache* cache);
private: private:
......
...@@ -47,6 +47,12 @@ class AppRegistryCacheTest : public testing::Test, ...@@ -47,6 +47,12 @@ class AppRegistryCacheTest : public testing::Test,
updated_names_.insert(update.Name()); updated_names_.insert(update.Name());
} }
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override {
// The test code explicitly calls both AddObserver and RemoveObserver.
NOTREACHED();
}
int num_freshly_installed_ = 0; int num_freshly_installed_ = 0;
std::set<std::string> updated_ids_; std::set<std::string> updated_ids_;
std::set<std::string> updated_names_; std::set<std::string> updated_names_;
...@@ -63,10 +69,10 @@ class AppRegistryCacheTest : public testing::Test, ...@@ -63,10 +69,10 @@ class AppRegistryCacheTest : public testing::Test,
class RecursiveObserver : public apps::AppRegistryCache::Observer { class RecursiveObserver : public apps::AppRegistryCache::Observer {
public: public:
explicit RecursiveObserver(apps::AppRegistryCache* cache) : cache_(cache) { explicit RecursiveObserver(apps::AppRegistryCache* cache) : cache_(cache) {
cache_->AddObserver(this); Observe(cache);
} }
~RecursiveObserver() override { cache_->RemoveObserver(this); } ~RecursiveObserver() override = default;
void PrepareForOnApps( void PrepareForOnApps(
int expected_num_apps, int expected_num_apps,
...@@ -156,6 +162,11 @@ class RecursiveObserver : public apps::AppRegistryCache::Observer { ...@@ -156,6 +162,11 @@ class RecursiveObserver : public apps::AppRegistryCache::Observer {
num_apps_seen_on_app_update_++; num_apps_seen_on_app_update_++;
} }
void OnAppRegistryCacheWillBeDestroyed(
apps::AppRegistryCache* cache) override {
Observe(nullptr);
}
static void ExpectEq(const apps::AppUpdate& outer, static void ExpectEq(const apps::AppUpdate& outer,
const apps::AppUpdate& inner) { const apps::AppUpdate& inner) {
EXPECT_EQ(outer.AppType(), inner.AppType()); EXPECT_EQ(outer.AppType(), inner.AppType());
......
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