Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_test_notification_observer.h" | 5 #include "chrome/browser/extensions/extension_test_notification_observer.h" |
| 6 | 6 |
| 7 #include "base/callback_list.h" | |
| 7 #include "chrome/browser/extensions/extension_service.h" | 8 #include "chrome/browser/extensions/extension_service.h" |
| 8 #include "chrome/browser/extensions/extension_system.h" | 9 #include "chrome/browser/extensions/extension_system.h" |
| 9 #include "chrome/browser/profiles/profile_manager.h" | 10 #include "chrome/browser/profiles/profile_manager.h" |
| 10 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
| 11 #include "chrome/browser/ui/browser_window.h" | 12 #include "chrome/browser/ui/browser_window.h" |
| 12 #include "chrome/common/extensions/extension.h" | 13 #include "chrome/common/extensions/extension.h" |
| 13 #include "content/public/browser/notification_registrar.h" | 14 #include "content/public/browser/notification_registrar.h" |
| 14 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
| 15 #include "content/public/browser/render_view_host.h" | 16 #include "content/public/browser/render_view_host.h" |
| 16 #include "content/public/test/test_utils.h" | 17 #include "content/public/test/test_utils.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 28 | 29 |
| 29 bool HasExtensionPageActionVisibilityReachedTarget( | 30 bool HasExtensionPageActionVisibilityReachedTarget( |
| 30 LocationBarTesting* location_bar, | 31 LocationBarTesting* location_bar, |
| 31 int target_visible_page_action_count) { | 32 int target_visible_page_action_count) { |
| 32 VLOG(1) << "Number of visible page actions: " | 33 VLOG(1) << "Number of visible page actions: " |
| 33 << location_bar->PageActionVisibleCount(); | 34 << location_bar->PageActionVisibleCount(); |
| 34 return location_bar->PageActionVisibleCount() == | 35 return location_bar->PageActionVisibleCount() == |
| 35 target_visible_page_action_count; | 36 target_visible_page_action_count; |
| 36 } | 37 } |
| 37 | 38 |
| 39 bool HaveAllExtensionRenderViewHostsFinishedLoading( | |
| 40 extensions::ProcessManager* manager) { | |
| 41 extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); | |
| 42 for (extensions::ProcessManager::ViewSet::const_iterator iter = | |
| 43 all_views.begin(); | |
| 44 iter != all_views.end(); ++iter) { | |
| 45 if ((*iter)->IsLoading()) | |
| 46 return false; | |
| 47 } | |
| 48 return true; | |
| 49 } | |
| 50 | |
| 51 class NotificationSet : public content::NotificationObserver { | |
| 52 public: | |
| 53 void Add(int type, const content::NotificationSource& source); | |
| 54 void Add(int type); | |
| 55 | |
| 56 // Notified any time an Add()ed notification is received. | |
| 57 // The details of the notification are dropped. | |
| 58 base::CallbackList<void()>& callback_list() { | |
| 59 return callback_list_; | |
| 60 } | |
| 61 | |
| 62 private: | |
| 63 // content::NotificationObserver: | |
| 64 virtual void Observe(int type, | |
| 65 const content::NotificationSource& source, | |
| 66 const content::NotificationDetails& details) OVERRIDE; | |
| 67 | |
| 68 content::NotificationRegistrar notification_registrar_; | |
| 69 base::CallbackList<void()> callback_list_; | |
| 70 }; | |
| 71 | |
| 72 void NotificationSet::Add( | |
| 73 int type, | |
| 74 const content::NotificationSource& source) { | |
| 75 notification_registrar_.Add(this, type, source); | |
| 76 } | |
| 77 | |
| 78 void NotificationSet::Add(int type) { | |
| 79 Add(type, content::NotificationService::AllSources()); | |
| 80 } | |
| 81 | |
| 82 void NotificationSet::Observe( | |
| 83 int type, | |
| 84 const content::NotificationSource& source, | |
| 85 const content::NotificationDetails& details) { | |
| 86 callback_list_.Notify(); | |
| 87 } | |
| 88 | |
| 89 void MaybeQuit(content::MessageLoopRunner* runner, | |
| 90 const base::Callback<bool(void)>& condition) { | |
| 91 if (condition.Run()) | |
| 92 runner->Quit(); | |
| 93 } | |
| 94 | |
| 95 void WaitForCondition( | |
| 96 const base::Callback<bool(void)>& condition, | |
| 97 NotificationSet* notification_set) { | |
| 98 if (condition.Run()) | |
| 99 return; | |
| 100 | |
| 101 scoped_refptr<content::MessageLoopRunner> runner( | |
| 102 new content::MessageLoopRunner); | |
| 103 scoped_ptr<base::CallbackList<void()>::Subscription> subscription = | |
| 104 notification_set->callback_list().Add( | |
| 105 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
| |
| 106 runner->Run(); | |
| 107 } | |
| 108 | |
| 109 void WaitForCondition( | |
| 110 const base::Callback<bool(void)>& condition, | |
| 111 int type) { | |
| 112 NotificationSet notification_set; | |
| 113 notification_set.Add(type); | |
| 114 WaitForCondition(condition, ¬ification_set); | |
| 115 } | |
| 116 | |
| 38 } // namespace | 117 } // namespace |
| 39 | 118 |
| 40 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( | 119 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( |
| 41 Browser* browser) | 120 Browser* browser) |
| 42 : browser_(browser), | 121 : browser_(browser), |
| 43 profile_(NULL), | 122 profile_(NULL), |
| 44 extension_installs_observed_(0), | 123 extension_installs_observed_(0), |
| 45 extension_load_errors_observed_(0), | 124 extension_load_errors_observed_(0), |
| 46 crx_installers_done_observed_(0) { | 125 crx_installers_done_observed_(0) { |
| 47 } | 126 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 67 registrar.Add( | 146 registrar.Add( |
| 68 this, notification_type, content::NotificationService::AllSources()); | 147 this, notification_type, content::NotificationService::AllSources()); |
| 69 content::WindowedNotificationObserver( | 148 content::WindowedNotificationObserver( |
| 70 notification_type, content::NotificationService::AllSources()).Wait(); | 149 notification_type, content::NotificationService::AllSources()).Wait(); |
| 71 } | 150 } |
| 72 | 151 |
| 73 bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo( | 152 bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo( |
| 74 int count) { | 153 int count) { |
| 75 LocationBarTesting* location_bar = | 154 LocationBarTesting* location_bar = |
| 76 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); | 155 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| 77 if (!HasExtensionPageActionCountReachedTarget(location_bar, count)) { | 156 WaitForCondition( |
| 78 content::WindowedNotificationObserver( | 157 base::Bind( |
| 79 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, | 158 &HasExtensionPageActionCountReachedTarget, location_bar, count), |
| 80 base::Bind( | 159 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED); |
| 81 &HasExtensionPageActionCountReachedTarget, location_bar, count)) | 160 return true; |
| 82 .Wait(); | |
| 83 } | |
| 84 return HasExtensionPageActionCountReachedTarget(location_bar, count); | |
| 85 } | 161 } |
| 86 | 162 |
| 87 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo( | 163 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo( |
| 88 int count) { | 164 int count) { |
| 89 LocationBarTesting* location_bar = | 165 LocationBarTesting* location_bar = |
| 90 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); | 166 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| 91 if (!HasExtensionPageActionVisibilityReachedTarget(location_bar, count)) { | 167 WaitForCondition( |
| 92 content::WindowedNotificationObserver( | 168 base::Bind( |
| 93 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, | 169 &HasExtensionPageActionVisibilityReachedTarget, location_bar, count), |
| 94 base::Bind(&HasExtensionPageActionVisibilityReachedTarget, | 170 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED); |
| 95 location_bar, | 171 return true; |
| 96 count)).Wait(); | |
| 97 } | |
| 98 return HasExtensionPageActionVisibilityReachedTarget(location_bar, count); | |
| 99 } | 172 } |
| 100 | 173 |
| 101 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { | 174 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { |
| 102 extensions::ProcessManager* manager = | 175 extensions::ProcessManager* manager = |
| 103 extensions::ExtensionSystem::Get(GetProfile())->process_manager(); | 176 extensions::ExtensionSystem::Get(GetProfile())->process_manager(); |
| 104 extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); | 177 NotificationSet notification_set; |
| 105 for (extensions::ProcessManager::ViewSet::const_iterator iter = | 178 notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED); |
| 106 all_views.begin(); | 179 notification_set.Add(content::NOTIFICATION_LOAD_STOP); |
| 107 iter != all_views.end();) { | 180 WaitForCondition( |
| 108 if (!(*iter)->IsLoading()) { | 181 base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager), |
| 109 ++iter; | 182 ¬ification_set); |
| 110 } else { | |
| 111 // Wait for all the extension render view hosts that exist to finish | |
| 112 // loading. | |
| 113 content::WindowedNotificationObserver observer( | |
| 114 content::NOTIFICATION_LOAD_STOP, | |
| 115 content::NotificationService::AllSources()); | |
| 116 observer.AddNotificationType( | |
| 117 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 118 content::NotificationService::AllSources()); | |
| 119 observer.Wait(); | |
| 120 | |
| 121 // Test activity may have modified the set of extension processes during | |
| 122 // message processing, so re-start the iteration to catch added/removed | |
| 123 // processes. | |
| 124 all_views = manager->GetAllViews(); | |
| 125 iter = all_views.begin(); | |
| 126 } | |
| 127 } | |
| 128 return true; | 183 return true; |
| 129 } | 184 } |
| 130 | 185 |
| 131 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() { | 186 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() { |
| 132 int before = extension_installs_observed_; | 187 int before = extension_installs_observed_; |
| 133 WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED); | 188 WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED); |
| 134 return extension_installs_observed_ == (before + 1); | 189 return extension_installs_observed_ == (before + 1); |
| 135 } | 190 } |
| 136 | 191 |
| 137 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { | 192 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: | 280 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: |
| 226 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; | 281 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; |
| 227 ++extension_load_errors_observed_; | 282 ++extension_load_errors_observed_; |
| 228 break; | 283 break; |
| 229 | 284 |
| 230 default: | 285 default: |
| 231 NOTREACHED(); | 286 NOTREACHED(); |
| 232 break; | 287 break; |
| 233 } | 288 } |
| 234 } | 289 } |
| OLD | NEW |