Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / extension_test_notification_observer.cc
blobd81b093d45ae4924a56cd7d24add3105b9bf339e
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_service.h"
9 #include "chrome/browser/extensions/extension_system.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_window.h"
13 #include "content/public/browser/notification_registrar.h"
14 #include "content/public/browser/notification_service.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/test/test_utils.h"
17 #include "extensions/browser/process_manager.h"
18 #include "extensions/common/extension.h"
20 using extensions::Extension;
22 namespace {
24 bool HasExtensionPageActionCountReachedTarget(LocationBarTesting* location_bar,
25 int target_page_action_count) {
26 VLOG(1) << "Number of page actions: " << location_bar->PageActionCount();
27 return location_bar->PageActionCount() == target_page_action_count;
30 bool HasExtensionPageActionVisibilityReachedTarget(
31 LocationBarTesting* location_bar,
32 int target_visible_page_action_count) {
33 VLOG(1) << "Number of visible page actions: "
34 << location_bar->PageActionVisibleCount();
35 return location_bar->PageActionVisibleCount() ==
36 target_visible_page_action_count;
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;
48 return true;
51 class NotificationSet : public content::NotificationObserver {
52 public:
53 void Add(int type, const content::NotificationSource& source);
54 void Add(int type);
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_;
62 private:
63 // content::NotificationObserver:
64 virtual void Observe(int type,
65 const content::NotificationSource& source,
66 const content::NotificationDetails& details) OVERRIDE;
68 content::NotificationRegistrar notification_registrar_;
69 base::CallbackList<void()> callback_list_;
72 void NotificationSet::Add(
73 int type,
74 const content::NotificationSource& source) {
75 notification_registrar_.Add(this, type, source);
78 void NotificationSet::Add(int type) {
79 Add(type, content::NotificationService::AllSources());
82 void NotificationSet::Observe(
83 int type,
84 const content::NotificationSource& source,
85 const content::NotificationDetails& details) {
86 callback_list_.Notify();
89 void MaybeQuit(content::MessageLoopRunner* runner,
90 const base::Callback<bool(void)>& condition) {
91 if (condition.Run())
92 runner->Quit();
95 void WaitForCondition(
96 const base::Callback<bool(void)>& condition,
97 NotificationSet* notification_set) {
98 if (condition.Run())
99 return;
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));
106 runner->Run();
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, &notification_set);
117 } // namespace
119 ExtensionTestNotificationObserver::ExtensionTestNotificationObserver(
120 Browser* browser)
121 : browser_(browser),
122 profile_(NULL),
123 extension_installs_observed_(0),
124 extension_load_errors_observed_(0),
125 crx_installers_done_observed_(0) {
128 ExtensionTestNotificationObserver::~ExtensionTestNotificationObserver() {}
130 Profile* ExtensionTestNotificationObserver::GetProfile() {
131 if (!profile_) {
132 if (browser_)
133 profile_ = browser_->profile();
134 else
135 profile_ = ProfileManager::GetActiveUserProfile();
137 return profile_;
140 void ExtensionTestNotificationObserver::WaitForNotification(
141 int notification_type) {
142 // TODO(bauerb): Using a WindowedNotificationObserver like this can break
143 // easily, if the notification we're waiting for is sent before this method.
144 // Change it so that the WindowedNotificationObserver is constructed earlier.
145 content::NotificationRegistrar registrar;
146 registrar.Add(
147 this, notification_type, content::NotificationService::AllSources());
148 content::WindowedNotificationObserver(
149 notification_type, content::NotificationService::AllSources()).Wait();
152 bool ExtensionTestNotificationObserver::WaitForPageActionCountChangeTo(
153 int count) {
154 LocationBarTesting* location_bar =
155 browser_->window()->GetLocationBar()->GetLocationBarForTesting();
156 WaitForCondition(
157 base::Bind(
158 &HasExtensionPageActionCountReachedTarget, location_bar, count),
159 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_COUNT_CHANGED);
160 return true;
163 bool ExtensionTestNotificationObserver::WaitForPageActionVisibilityChangeTo(
164 int count) {
165 LocationBarTesting* location_bar =
166 browser_->window()->GetLocationBar()->GetLocationBarForTesting();
167 WaitForCondition(
168 base::Bind(
169 &HasExtensionPageActionVisibilityReachedTarget, location_bar, count),
170 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED);
171 return true;
174 bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() {
175 extensions::ProcessManager* manager =
176 extensions::ExtensionSystem::Get(GetProfile())->process_manager();
177 NotificationSet notification_set;
178 notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED);
179 notification_set.Add(content::NOTIFICATION_LOAD_STOP);
180 WaitForCondition(
181 base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager),
182 &notification_set);
183 return true;
186 bool ExtensionTestNotificationObserver::WaitForExtensionInstall() {
187 int before = extension_installs_observed_;
188 WaitForNotification(chrome::NOTIFICATION_EXTENSION_INSTALLED);
189 return extension_installs_observed_ == (before + 1);
192 bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() {
193 int before = extension_installs_observed_;
194 content::WindowedNotificationObserver(
195 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
196 content::NotificationService::AllSources()).Wait();
197 return extension_installs_observed_ == before;
200 void ExtensionTestNotificationObserver::WaitForExtensionLoad() {
201 WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOADED);
204 void ExtensionTestNotificationObserver::WaitForExtensionAndViewLoad() {
205 this->WaitForExtensionLoad();
206 WaitForExtensionViewsToLoad();
209 bool ExtensionTestNotificationObserver::WaitForExtensionLoadError() {
210 int before = extension_load_errors_observed_;
211 WaitForNotification(chrome::NOTIFICATION_EXTENSION_LOAD_ERROR);
212 return extension_load_errors_observed_ != before;
215 bool ExtensionTestNotificationObserver::WaitForExtensionCrash(
216 const std::string& extension_id) {
217 ExtensionService* service = extensions::ExtensionSystem::Get(
218 GetProfile())->extension_service();
220 if (!service->GetExtensionById(extension_id, true)) {
221 // The extension is already unloaded, presumably due to a crash.
222 return true;
224 content::WindowedNotificationObserver(
225 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
226 content::NotificationService::AllSources()).Wait();
227 return (service->GetExtensionById(extension_id, true) == NULL);
230 bool ExtensionTestNotificationObserver::WaitForCrxInstallerDone() {
231 int before = crx_installers_done_observed_;
232 WaitForNotification(chrome::NOTIFICATION_CRX_INSTALLER_DONE);
233 return crx_installers_done_observed_ == (before + 1);
236 void ExtensionTestNotificationObserver::Watch(
237 int type,
238 const content::NotificationSource& source) {
239 CHECK(!observer_);
240 observer_.reset(new content::WindowedNotificationObserver(type, source));
241 registrar_.Add(this, type, source);
244 void ExtensionTestNotificationObserver::Wait() {
245 observer_->Wait();
247 registrar_.RemoveAll();
248 observer_.reset();
251 void ExtensionTestNotificationObserver::Observe(
252 int type,
253 const content::NotificationSource& source,
254 const content::NotificationDetails& details) {
255 switch (type) {
256 case chrome::NOTIFICATION_EXTENSION_LOADED:
257 last_loaded_extension_id_ =
258 content::Details<const Extension>(details).ptr()->id();
259 VLOG(1) << "Got EXTENSION_LOADED notification.";
260 break;
262 case chrome::NOTIFICATION_CRX_INSTALLER_DONE:
263 VLOG(1) << "Got CRX_INSTALLER_DONE notification.";
265 const Extension* extension =
266 content::Details<const Extension>(details).ptr();
267 if (extension)
268 last_loaded_extension_id_ = extension->id();
269 else
270 last_loaded_extension_id_.clear();
272 ++crx_installers_done_observed_;
273 break;
275 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
276 VLOG(1) << "Got EXTENSION_INSTALLED notification.";
277 ++extension_installs_observed_;
278 break;
280 case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR:
281 VLOG(1) << "Got EXTENSION_LOAD_ERROR notification.";
282 ++extension_load_errors_observed_;
283 break;
285 default:
286 NOTREACHED();
287 break;