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 "chrome/browser/extensions/extension_process_manager.h" | 7 #include "chrome/browser/extensions/extension_process_manager.h" |
| 8 #include "chrome/browser/extensions/extension_service.h" | 8 #include "chrome/browser/extensions/extension_service.h" |
| 9 #include "chrome/browser/extensions/extension_system.h" | 9 #include "chrome/browser/extensions/extension_system.h" |
| 10 #include "chrome/browser/profiles/profile_manager.h" | 10 #include "chrome/browser/profiles/profile_manager.h" |
| 11 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
| 12 #include "chrome/browser/ui/browser_window.h" | 12 #include "chrome/browser/ui/browser_window.h" |
| 13 #include "chrome/common/extensions/extension.h" | 13 #include "chrome/common/extensions/extension.h" |
| 14 #include "content/public/browser/notification_registrar.h" | 14 #include "content/public/browser/notification_registrar.h" |
| 15 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
| 16 #include "content/public/browser/render_view_host.h" | 16 #include "content/public/browser/render_view_host.h" |
| 17 #include "content/public/test/test_utils.h" | 17 #include "content/public/test/test_utils.h" |
| 18 | 18 |
| 19 using extensions::Extension; | 19 using extensions::Extension; |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 class ConditionRunLoop { | |
| 24 public: | |
| 25 typedef base::Callback<bool(void)> ConditionCallback; | |
| 26 | |
| 27 explicit ConditionRunLoop(const ConditionCallback& callback); | |
| 28 | |
| 29 void Wait(); | |
| 30 | |
| 31 void Check(); | |
| 32 | |
| 33 private: | |
| 34 base::RunLoop run_loop_; | |
| 35 ConditionCallback condition_callback_; | |
| 36 }; | |
| 37 | |
| 38 ConditionRunLoop::ConditionRunLoop(const ConditionCallback& callback) | |
| 39 : condition_callback_(callback) {} | |
| 40 | |
| 41 void ConditionRunLoop::Wait() { | |
| 42 if (condition_callback_.Run()) | |
| 43 return; | |
| 44 | |
| 45 run_loop_.Run(); | |
| 46 } | |
| 47 | |
| 48 void ConditionRunLoop::Check() { | |
| 49 if (condition_callback_.Run()) | |
| 50 run_loop_.Quit(); | |
| 51 } | |
| 52 | |
| 23 bool HasExtensionPageActionCountReachedTarget(LocationBarTesting* location_bar, | 53 bool HasExtensionPageActionCountReachedTarget(LocationBarTesting* location_bar, |
| 24 int target_page_action_count) { | 54 int target_page_action_count) { |
| 25 VLOG(1) << "Number of page actions: " << location_bar->PageActionCount(); | 55 VLOG(1) << "Number of page actions: " << location_bar->PageActionCount(); |
| 26 return location_bar->PageActionCount() == target_page_action_count; | 56 return location_bar->PageActionCount() == target_page_action_count; |
| 27 } | 57 } |
| 28 | 58 |
| 29 bool HasExtensionPageActionVisibilityReachedTarget( | 59 bool HasExtensionPageActionVisibilityReachedTarget( |
| 30 LocationBarTesting* location_bar, | 60 LocationBarTesting* location_bar, |
| 31 int target_visible_page_action_count) { | 61 int target_visible_page_action_count) { |
| 32 VLOG(1) << "Number of visible page actions: " | 62 VLOG(1) << "Number of visible page actions: " |
| 33 << location_bar->PageActionVisibleCount(); | 63 << location_bar->PageActionVisibleCount(); |
| 34 return location_bar->PageActionVisibleCount() == | 64 return location_bar->PageActionVisibleCount() == |
| 35 target_visible_page_action_count; | 65 target_visible_page_action_count; |
| 36 } | 66 } |
| 37 | 67 |
| 68 bool HaveAllExtensionRenderViewHostsFinishedLoading( | |
| 69 ExtensionProcessManager* manager) { | |
| 70 ExtensionProcessManager::ViewSet all_views = manager->GetAllViews(); | |
| 71 for (ExtensionProcessManager::ViewSet::const_iterator iter = | |
| 72 all_views.begin(); | |
| 73 iter != all_views.end(); ++iter) { | |
| 74 if ((*iter)->IsLoading()) | |
| 75 return false; | |
| 76 } | |
| 77 return true; | |
| 78 } | |
| 79 | |
| 80 class NotificationCallbackRunner : public content::NotificationObserver { | |
|
Jeffrey Yasskin
2013/10/24 23:49:23
What if we had something like:
class Notification
Bernhard Bauer
2013/10/29 16:37:02
Done. As an aside, the interface to CallbackList i
Jeffrey Yasskin
2013/11/06 03:33:59
:-/
| |
| 81 public: | |
| 82 NotificationCallbackRunner(int type, | |
| 83 const content::NotificationSource& source, | |
| 84 const base::Closure& callback); | |
| 85 | |
| 86 private: | |
| 87 // content::NotificationObserver | |
| 88 virtual void Observe(int type, | |
| 89 const content::NotificationSource& source, | |
| 90 const content::NotificationDetails& details) OVERRIDE; | |
| 91 | |
| 92 content::NotificationRegistrar notification_registrar_; | |
| 93 base::Closure callback_; | |
| 94 }; | |
| 95 | |
| 96 NotificationCallbackRunner::NotificationCallbackRunner( | |
| 97 int type, | |
| 98 const content::NotificationSource& source, | |
| 99 const base::Closure& callback) | |
| 100 : callback_(callback) { | |
| 101 notification_registrar_.Add(this, type, source); | |
| 102 } | |
| 103 | |
| 104 void NotificationCallbackRunner::Observe( | |
| 105 int type, | |
| 106 const content::NotificationSource& source, | |
| 107 const content::NotificationDetails& details) { | |
| 108 callback_.Run(); | |
| 109 } | |
| 110 | |
| 111 void WaitForConditionWithNotification( | |
| 112 const base::Callback<bool(void)>& condition, | |
| 113 int type, | |
| 114 const content::NotificationSource& source) { | |
| 115 ConditionRunLoop run_loop(condition); | |
| 116 NotificationCallbackRunner callback_runner( | |
| 117 type, | |
| 118 source, | |
| 119 base::Bind(&ConditionRunLoop::Check, base::Unretained(&run_loop))); | |
| 120 run_loop.Wait(); | |
| 121 } | |
| 122 | |
| 123 void WaitForConditionWithNotification( | |
| 124 const base::Callback<bool(void)>& condition, | |
| 125 int type) { | |
| 126 WaitForConditionWithNotification( | |
| 127 condition, type, content::NotificationService::AllSources()); | |
| 128 } | |
| 129 | |
| 38 } // namespace | 130 } // namespace |
| 39 | 131 |
| 40 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( | 132 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( |
| 41 Browser* browser) | 133 Browser* browser) |
| 42 : browser_(browser), | 134 : browser_(browser), |
| 43 profile_(NULL), | 135 profile_(NULL), |
| 44 extension_installs_observed_(0), | 136 extension_installs_observed_(0), |
| 45 extension_load_errors_observed_(0), | 137 extension_load_errors_observed_(0), |
| 46 crx_installers_done_observed_(0) { | 138 crx_installers_done_observed_(0) { |
| 47 } | 139 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 67 registrar.Add( | 159 registrar.Add( |
| 68 this, notification_type, content::NotificationService::AllSources()); | 160 this, notification_type, content::NotificationService::AllSources()); |
| 69 content::WindowedNotificationObserver( | 161 content::WindowedNotificationObserver( |
| 70 notification_type, content::NotificationService::AllSources()).Wait(); | 162 notification_type, content::NotificationService::AllSources()).Wait(); |
| 71 } | 163 } |
| 72 | 164 |
| 73 bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo( | 165 bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo( |
| 74 int count) { | 166 int count) { |
| 75 LocationBarTesting* location_bar = | 167 LocationBarTesting* location_bar = |
| 76 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); | 168 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| 77 if (!HasExtensionPageActionCountReachedTarget(location_bar, count)) { | 169 WaitForConditionWithNotification( |
|
Jeffrey Yasskin
2013/10/24 23:49:23
I definitely like this since it removes the duplic
| |
| 78 content::WindowedNotificationObserver( | 170 base::Bind( |
| 79 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED, | 171 &HasExtensionPageActionCountReachedTarget, location_bar, count), |
| 80 base::Bind( | 172 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED); |
| 81 &HasExtensionPageActionCountReachedTarget, location_bar, count)) | 173 return true; |
| 82 .Wait(); | |
| 83 } | |
| 84 return HasExtensionPageActionCountReachedTarget(location_bar, count); | |
| 85 } | 174 } |
| 86 | 175 |
| 87 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo( | 176 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo( |
| 88 int count) { | 177 int count) { |
| 89 LocationBarTesting* location_bar = | 178 LocationBarTesting* location_bar = |
| 90 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); | 179 browser_->window()->GetLocationBar()->GetLocationBarForTesting(); |
| 91 if (!HasExtensionPageActionVisibilityReachedTarget(location_bar, count)) { | 180 WaitForConditionWithNotification( |
| 92 content::WindowedNotificationObserver( | 181 base::Bind( |
| 93 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, | 182 &HasExtensionPageActionVisibilityReachedTarget, location_bar, count), |
| 94 base::Bind(&HasExtensionPageActionVisibilityReachedTarget, | 183 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED); |
| 95 location_bar, | 184 return true; |
| 96 count)).Wait(); | |
| 97 } | |
| 98 return HasExtensionPageActionVisibilityReachedTarget(location_bar, count); | |
| 99 } | 185 } |
| 100 | 186 |
| 101 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { | 187 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { |
| 102 ExtensionProcessManager* manager = | 188 ExtensionProcessManager* manager = |
| 103 extensions::ExtensionSystem::Get(GetProfile())->process_manager(); | 189 extensions::ExtensionSystem::Get(GetProfile())->process_manager(); |
| 104 ExtensionProcessManager::ViewSet all_views = manager->GetAllViews(); | 190 ConditionRunLoop run_loop( |
| 105 for (ExtensionProcessManager::ViewSet::const_iterator iter = | 191 base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager)); |
| 106 all_views.begin(); | 192 NotificationCallbackRunner callback_runner( |
|
Jeffrey Yasskin
2013/10/24 23:49:23
I don't really like using NotificationCallbackRunn
| |
| 107 iter != all_views.end();) { | 193 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 108 if (!(*iter)->IsLoading()) { | 194 content::NotificationService::AllSources(), |
| 109 ++iter; | 195 base::Bind(&ConditionRunLoop::Check, base::Unretained(&run_loop))); |
| 110 } else { | 196 NotificationCallbackRunner callback_runner_2( |
| 111 // Wait for all the extension render view hosts that exist to finish | 197 content::NOTIFICATION_LOAD_STOP, |
| 112 // loading. | 198 content::NotificationService::AllSources(), |
| 113 content::WindowedNotificationObserver observer( | 199 base::Bind(&ConditionRunLoop::Check, base::Unretained(&run_loop))); |
| 114 content::NOTIFICATION_LOAD_STOP, | 200 run_loop.Wait(); |
| 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; | 201 return true; |
| 129 } | 202 } |
| 130 | 203 |
| 131 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() { | 204 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() { |
| 132 int before = extension_installs_observed_; | 205 int before = extension_installs_observed_; |
| 133 WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED); | 206 WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED); |
| 134 return extension_installs_observed_ == (before + 1); | 207 return extension_installs_observed_ == (before + 1); |
| 135 } | 208 } |
| 136 | 209 |
| 137 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { | 210 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: | 298 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: |
| 226 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; | 299 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; |
| 227 ++extension_load_errors_observed_; | 300 ++extension_load_errors_observed_; |
| 228 break; | 301 break; |
| 229 | 302 |
| 230 default: | 303 default: |
| 231 NOTREACHED(); | 304 NOTREACHED(); |
| 232 break; | 305 break; |
| 233 } | 306 } |
| 234 } | 307 } |
| OLD | NEW |