Chromium Code Reviews| Index: chrome/browser/extensions/extension_test_notification_observer.cc |
| diff --git a/chrome/browser/extensions/extension_test_notification_observer.cc b/chrome/browser/extensions/extension_test_notification_observer.cc |
| index 77c140d4e15c31718a1a200156708c75d517a426..c9f22ef7cc1ab9e2bc4b5f2675ce8aaa641bf68a 100644 |
| --- a/chrome/browser/extensions/extension_test_notification_observer.cc |
| +++ b/chrome/browser/extensions/extension_test_notification_observer.cc |
| @@ -4,6 +4,7 @@ |
| #include "chrome/browser/extensions/extension_test_notification_observer.h" |
| +#include "base/callback_list.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| @@ -35,6 +36,84 @@ bool HasExtensionPageActionVisibilityReachedTarget( |
| target_visible_page_action_count; |
| } |
| +bool HaveAllExtensionRenderViewHostsFinishedLoading( |
| + extensions::ProcessManager* manager) { |
| + extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); |
| + for (extensions::ProcessManager::ViewSet::const_iterator iter = |
| + all_views.begin(); |
| + iter != all_views.end(); ++iter) { |
| + if ((*iter)->IsLoading()) |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +class NotificationSet : public content::NotificationObserver { |
| + public: |
| + void Add(int type, const content::NotificationSource& source); |
| + void Add(int type); |
| + |
| + // Notified any time an Add()ed notification is received. |
| + // The details of the notification are dropped. |
| + base::CallbackList<void()>& callback_list() { |
| + return callback_list_; |
| + } |
| + |
| + private: |
| + // content::NotificationObserver: |
| + virtual void Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) OVERRIDE; |
| + |
| + content::NotificationRegistrar notification_registrar_; |
| + base::CallbackList<void()> callback_list_; |
| +}; |
| + |
| +void NotificationSet::Add( |
| + int type, |
| + const content::NotificationSource& source) { |
| + notification_registrar_.Add(this, type, source); |
| +} |
| + |
| +void NotificationSet::Add(int type) { |
| + Add(type, content::NotificationService::AllSources()); |
| +} |
| + |
| +void NotificationSet::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + callback_list_.Notify(); |
| +} |
| + |
| +void MaybeQuit(content::MessageLoopRunner* runner, |
| + const base::Callback<bool(void)>& condition) { |
| + if (condition.Run()) |
| + runner->Quit(); |
| +} |
| + |
| +void WaitForCondition( |
| + const base::Callback<bool(void)>& condition, |
| + NotificationSet* notification_set) { |
| + if (condition.Run()) |
| + return; |
| + |
| + scoped_refptr<content::MessageLoopRunner> runner( |
| + new content::MessageLoopRunner); |
| + scoped_ptr<base::CallbackList<void()>::Subscription> subscription = |
| + notification_set->callback_list().Add( |
| + base::Bind(&MaybeQuit, base::Unretained(runner.get()), condition)); |
|
Cait (Slow)
2013/11/12 17:04:07
What's the reasoning behind using a CallbackList h
Bernhard Bauer
2013/11/12 17:51:45
I think the idea was to use CallbackList in place
|
| + runner->Run(); |
| +} |
| + |
| +void WaitForCondition( |
| + const base::Callback<bool(void)>& condition, |
| + int type) { |
| + NotificationSet notification_set; |
| + notification_set.Add(type); |
| + WaitForCondition(condition, ¬ification_set); |
| +} |
| + |
| } // namespace |
| ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( |
| @@ -74,57 +153,33 @@ bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo( |
| int count) { |
| LocationBarTesting* location_bar = |
| browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| - if (!HasExtensionPageActionCountReachedTarget(location_bar, count)) { |
| - content::WindowedNotificationObserver( |
| - chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, |
| - base::Bind( |
| - &HasExtensionPageActionCountReachedTarget, location_bar, count)) |
| - .Wait(); |
| - } |
| - return HasExtensionPageActionCountReachedTarget(location_bar, count); |
| + WaitForCondition( |
| + base::Bind( |
| + &HasExtensionPageActionCountReachedTarget, location_bar, count), |
| + chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED); |
| + return true; |
| } |
| bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo( |
| int count) { |
| LocationBarTesting* location_bar = |
| browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| - if (!HasExtensionPageActionVisibilityReachedTarget(location_bar, count)) { |
| - content::WindowedNotificationObserver( |
| - chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, |
| - base::Bind(&HasExtensionPageActionVisibilityReachedTarget, |
| - location_bar, |
| - count)).Wait(); |
| - } |
| - return HasExtensionPageActionVisibilityReachedTarget(location_bar, count); |
| + WaitForCondition( |
| + base::Bind( |
| + &HasExtensionPageActionVisibilityReachedTarget, location_bar, count), |
| + chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED); |
| + return true; |
| } |
| bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { |
| extensions::ProcessManager* manager = |
| - extensions::ExtensionSystem::Get(GetProfile())->process_manager(); |
| - extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); |
| - for (extensions::ProcessManager::ViewSet::const_iterator iter = |
| - all_views.begin(); |
| - iter != all_views.end();) { |
| - if (!(*iter)->IsLoading()) { |
| - ++iter; |
| - } else { |
| - // Wait for all the extension render view hosts that exist to finish |
| - // loading. |
| - content::WindowedNotificationObserver observer( |
| - content::NOTIFICATION_LOAD_STOP, |
| - content::NotificationService::AllSources()); |
| - observer.AddNotificationType( |
| - content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| - content::NotificationService::AllSources()); |
| - observer.Wait(); |
| - |
| - // Test activity may have modified the set of extension processes during |
| - // message processing, so re-start the iteration to catch added/removed |
| - // processes. |
| - all_views = manager->GetAllViews(); |
| - iter = all_views.begin(); |
| - } |
| - } |
| + extensions::ExtensionSystem::Get(GetProfile())->process_manager(); |
| + NotificationSet notification_set; |
| + notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED); |
| + notification_set.Add(content::NOTIFICATION_LOAD_STOP); |
| + WaitForCondition( |
| + base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager), |
| + ¬ification_set); |
| return true; |
| } |