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 |