Extract code handling PrinterProviderAPI from PrintPreviewHandler
[chromium-blink-merge.git] / chrome / browser / extensions / extension_test_notification_observer.cc
blob403e6b9f9f39d1ff8b09e674783d2e2f7d1dfa8e
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_test_notification_observer.h"
7 #include "base/callback_list.h"
8 #include "chrome/browser/extensions/extension_action_test_util.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_util.h"
11 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "content/public/browser/notification_registrar.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/test/test_utils.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/browser/process_manager.h"
21 #include "extensions/common/extension.h"
23 using extensions::Extension;
25 namespace {
27 // A callback that returns true if the condition has been met and takes no
28 // arguments.
29 typedef base::Callback<bool(void)> ConditionCallback;
31 bool HasPageActionVisibilityReachedTarget(
32 Browser* browser, size_t target_visible_page_action_count) {
33 return extensions::extension_action_test_util::GetVisiblePageActionCount(
34 browser->tab_strip_model()->GetActiveWebContents()) ==
35 target_visible_page_action_count;
38 bool HaveAllExtensionRenderViewHostsFinishedLoading(
39 extensions::ProcessManager* manager) {
40 extensions::ProcessManager::ViewSet all_views = manager->GetAllViews();
41 for (extensions::ProcessManager::ViewSet::const_iterator iter =
42 all_views.begin();
43 iter != all_views.end(); ++iter) {
44 if ((*iter)->IsLoading())
45 return false;
47 return true;
50 bool IsExtensionNotIdle(const std::string& extension_id,
51 content::BrowserContext* context) {
52 return !extensions::util::IsExtensionIdle(extension_id, context);
55 } // namespace
57 ////////////////////////////////////////////////////////////////////////////////
58 // ExtensionTestNotificationObserver::NotificationSet
60 class ExtensionTestNotificationObserver::NotificationSet
61 : public content::NotificationObserver {
62 public:
63 void Add(int type, const content::NotificationSource& source);
64 void Add(int type);
66 // Notified any time an Add()ed notification is received.
67 // The details of the notification are dropped.
68 base::CallbackList<void()>& callback_list() {
69 return callback_list_;
72 private:
73 // content::NotificationObserver:
74 void Observe(int type,
75 const content::NotificationSource& source,
76 const content::NotificationDetails& details) override;
78 content::NotificationRegistrar notification_registrar_;
79 base::CallbackList<void()> callback_list_;
82 void ExtensionTestNotificationObserver::NotificationSet::Add(
83 int type,
84 const content::NotificationSource& source) {
85 notification_registrar_.Add(this, type, source);
88 void ExtensionTestNotificationObserver::NotificationSet::Add(int type) {
89 Add(type, content::NotificationService::AllSources());
92 void ExtensionTestNotificationObserver::NotificationSet::Observe(
93 int type,
94 const content::NotificationSource& source,
95 const content::NotificationDetails& details) {
96 callback_list_.Notify();
99 ////////////////////////////////////////////////////////////////////////////////
100 // ExtensionTestNotificationObserver
102 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver(
103 Browser* browser)
104 : browser_(browser),
105 profile_(NULL),
106 extension_installs_observed_(0),
107 extension_load_errors_observed_(0),
108 crx_installers_done_observed_(0) {
111 ExtensionTestNotificationObserver::~ExtensionTestNotificationObserver() {}
113 Profile* ExtensionTestNotificationObserver::GetProfile() {
114 if (!profile_) {
115 if (browser_)
116 profile_ = browser_->profile();
117 else
118 profile_ = ProfileManager::GetActiveUserProfile();
120 return profile_;
123 void ExtensionTestNotificationObserver::WaitForNotification(
124 int notification_type) {
125 // TODO(bauerb): Using a WindowedNotificationObserver like this can break
126 // easily, if the notification we're waiting for is sent before this method.
127 // Change it so that the WindowedNotificationObserver is constructed earlier.
128 content::NotificationRegistrar registrar;
129 registrar.Add(
130 this, notification_type, content::NotificationService::AllSources());
131 content::WindowedNotificationObserver(
132 notification_type, content::NotificationService::AllSources()).Wait();
135 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo(
136 int count) {
137 extensions::ExtensionActionAPI::Get(GetProfile())->AddObserver(this);
138 WaitForCondition(
139 base::Bind(&HasPageActionVisibilityReachedTarget, browser_, count),
140 NULL);
141 extensions::ExtensionActionAPI::Get(GetProfile())->
142 RemoveObserver(this);
143 return true;
146 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() {
147 extensions::ProcessManager* manager =
148 extensions::ProcessManager::Get(GetProfile());
149 NotificationSet notification_set;
150 notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
151 notification_set.Add(content::NOTIFICATION_LOAD_STOP);
152 WaitForCondition(
153 base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager),
154 &notification_set);
155 return true;
158 bool ExtensionTestNotificationObserver::WaitForExtensionIdle(
159 const std::string& extension_id) {
160 NotificationSet notification_set;
161 notification_set.Add(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
162 WaitForCondition(base::Bind(&extensions::util::IsExtensionIdle, extension_id,
163 GetProfile()),
164 &notification_set);
165 return true;
168 bool ExtensionTestNotificationObserver::WaitForExtensionNotIdle(
169 const std::string& extension_id) {
170 NotificationSet notification_set;
171 notification_set.Add(content::NOTIFICATION_LOAD_STOP);
172 WaitForCondition(base::Bind(&IsExtensionNotIdle, extension_id, GetProfile()),
173 &notification_set);
174 return true;
177 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() {
178 int before = extension_installs_observed_;
179 WaitForNotification(
180 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED);
181 return extension_installs_observed_ == (before + 1);
184 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() {
185 int before = extension_installs_observed_;
186 content::WindowedNotificationObserver(
187 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
188 content::NotificationService::AllSources()).Wait();
189 return extension_installs_observed_ == before;
192 void ExtensionTestNotificationObserver::WaitForExtensionLoad() {
193 WaitForNotification(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED);
196 void ExtensionTestNotificationObserver::WaitForExtensionAndViewLoad() {
197 this->WaitForExtensionLoad();
198 WaitForExtensionViewsToLoad();
201 bool ExtensionTestNotificationObserver::WaitForExtensionLoadError() {
202 int before = extension_load_errors_observed_;
203 WaitForNotification(extensions::NOTIFICATION_EXTENSION_LOAD_ERROR);
204 return extension_load_errors_observed_ != before;
207 bool ExtensionTestNotificationObserver::WaitForExtensionCrash(
208 const std::string& extension_id) {
209 ExtensionService* service = extensions::ExtensionSystem::Get(
210 GetProfile())->extension_service();
212 if (!service->GetExtensionById(extension_id, true)) {
213 // The extension is already unloaded, presumably due to a crash.
214 return true;
216 content::WindowedNotificationObserver(
217 extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
218 content::NotificationService::AllSources()).Wait();
219 return (service->GetExtensionById(extension_id, true) == NULL);
222 bool ExtensionTestNotificationObserver::WaitForCrxInstallerDone() {
223 int before = crx_installers_done_observed_;
224 WaitForNotification(extensions::NOTIFICATION_CRX_INSTALLER_DONE);
225 return crx_installers_done_observed_ == (before + 1);
228 void ExtensionTestNotificationObserver::Watch(
229 int type,
230 const content::NotificationSource& source) {
231 CHECK(!observer_);
232 observer_.reset(new content::WindowedNotificationObserver(type, source));
233 registrar_.Add(this, type, source);
236 void ExtensionTestNotificationObserver::Wait() {
237 observer_->Wait();
239 registrar_.RemoveAll();
240 observer_.reset();
243 void ExtensionTestNotificationObserver::Observe(
244 int type,
245 const content::NotificationSource& source,
246 const content::NotificationDetails& details) {
247 switch (type) {
248 case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
249 last_loaded_extension_id_ =
250 content::Details<const Extension>(details).ptr()->id();
251 VLOG(1) << "Got EXTENSION_LOADED notification.";
252 break;
254 case extensions::NOTIFICATION_CRX_INSTALLER_DONE:
255 VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
257 const Extension* extension =
258 content::Details<const Extension>(details).ptr();
259 if (extension)
260 last_loaded_extension_id_ = extension->id();
261 else
262 last_loaded_extension_id_.clear();
264 ++crx_installers_done_observed_;
265 break;
267 case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED:
268 VLOG(1) << "Got EXTENSION_INSTALLED notification.";
269 ++extension_installs_observed_;
270 break;
272 case extensions::NOTIFICATION_EXTENSION_LOAD_ERROR:
273 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
274 ++extension_load_errors_observed_;
275 break;
277 default:
278 NOTREACHED();
279 break;
283 void ExtensionTestNotificationObserver::OnPageActionsUpdated(
284 content::WebContents* web_contents) {
285 MaybeQuit();
288 void ExtensionTestNotificationObserver::WaitForCondition(
289 const ConditionCallback& condition,
290 NotificationSet* notification_set) {
291 if (condition.Run())
292 return;
293 condition_ = condition;
295 scoped_refptr<content::MessageLoopRunner> runner(
296 new content::MessageLoopRunner);
297 quit_closure_ = runner->QuitClosure();
299 scoped_ptr<base::CallbackList<void()>::Subscription> subscription;
300 if (notification_set) {
301 subscription = notification_set->callback_list().Add(
302 base::Bind(&ExtensionTestNotificationObserver::MaybeQuit,
303 base::Unretained(this)));
305 runner->Run();
307 condition_.Reset();
308 quit_closure_.Reset();
311 void ExtensionTestNotificationObserver::MaybeQuit() {
312 if (condition_.Run())
313 quit_closure_.Run();