Chromium Code Reviews| Index: extensions/test/extension_test_notification_observer.cc |
| diff --git a/extensions/test/extension_test_notification_observer.cc b/extensions/test/extension_test_notification_observer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5cdfb6619b1fb59739c33681dda7be512f5ebf14 |
| --- /dev/null |
| +++ b/extensions/test/extension_test_notification_observer.cc |
| @@ -0,0 +1,210 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "extensions/test/extension_test_notification_observer.h" |
| + |
| +#include <stddef.h> |
| + |
| +#include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/notification_registrar.h" |
|
Devlin
2016/10/06 15:52:17
trim
Rahul Chaturvedi
2016/10/11 20:12:35
Done.
|
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/render_view_host.h" |
| +#include "content/public/test/test_utils.h" |
| +#include "extensions/browser/extension_registry.h" |
| +#include "extensions/browser/extension_system.h" |
| +#include "extensions/browser/notification_types.h" |
| +#include "extensions/common/extension.h" |
| + |
| +using extensions::Extension; |
| + |
| +namespace { |
| + |
| +// A callback that returns true if the condition has been met and takes no |
| +// arguments. |
| +typedef base::Callback<bool(void)> ConditionCallback; |
|
Devlin
2016/10/06 15:52:17
using syntax
Rahul Chaturvedi
2016/10/11 20:12:35
Done.
|
| + |
| +const Extension* GetNonTerminatedExtensions(const std::string& id, |
| + content::BrowserContext* context) { |
| + return extensions::ExtensionRegistry::Get(context)->GetExtensionById( |
| + id, extensions::ExtensionRegistry::EVERYTHING & |
| + ~extensions::ExtensionRegistry::TERMINATED); |
| +} |
| + |
| +} // namespace |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ExtensionTestNotificationObserver::NotificationSet |
| + |
| +ExtensionTestNotificationObserver::NotificationSet::NotificationSet() |
| + : process_manager_observer_(this) {} |
| +ExtensionTestNotificationObserver::NotificationSet::~NotificationSet() {} |
| + |
| +void ExtensionTestNotificationObserver::NotificationSet::Add( |
| + int type, |
| + const content::NotificationSource& source) { |
| + notification_registrar_.Add(this, type, source); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::NotificationSet::Add(int type) { |
| + Add(type, content::NotificationService::AllSources()); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::NotificationSet:: |
| + AddExtensionFrameUnregistration(extensions::ProcessManager* manager) { |
| + process_manager_observer_.Add(manager); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::NotificationSet::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + callback_list_.Notify(); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::NotificationSet:: |
| + OnExtensionFrameUnregistered(const std::string& extension_id, |
| + content::RenderFrameHost* render_frame_host) { |
| + callback_list_.Notify(); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ExtensionTestNotificationObserver |
| + |
| +ExtensionTestNotificationObserver::ExtensionTestNotificationObserver( |
| + content::BrowserContext* context) |
| + : context_(context), |
| + extension_installs_observed_(0), |
| + extension_load_errors_observed_(0), |
| + crx_installers_done_observed_(0) {} |
| + |
| +ExtensionTestNotificationObserver::~ExtensionTestNotificationObserver() {} |
| + |
| +void ExtensionTestNotificationObserver::WaitForNotification( |
| + int notification_type) { |
| + // TODO(bauerb): Using a WindowedNotificationObserver like this can break |
| + // easily, if the notification we're waiting for is sent before this method. |
| + // Change it so that the WindowedNotificationObserver is constructed earlier. |
| + content::NotificationRegistrar registrar; |
| + registrar.Add(this, notification_type, |
| + content::NotificationService::AllSources()); |
| + content::WindowedNotificationObserver( |
| + notification_type, content::NotificationService::AllSources()) |
| + .Wait(); |
| +} |
| + |
| +bool ExtensionTestNotificationObserver::WaitForExtensionInstallError() { |
| + int before = extension_installs_observed_; |
| + content::WindowedNotificationObserver( |
| + extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
| + content::NotificationService::AllSources()) |
| + .Wait(); |
| + return extension_installs_observed_ == before; |
| +} |
| + |
| +void ExtensionTestNotificationObserver::WaitForExtensionLoad() { |
| + WaitForNotification(extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED); |
| +} |
| + |
| +bool ExtensionTestNotificationObserver::WaitForExtensionLoadError() { |
| + int before = extension_load_errors_observed_; |
| + WaitForNotification(extensions::NOTIFICATION_EXTENSION_LOAD_ERROR); |
| + return extension_load_errors_observed_ != before; |
| +} |
| + |
| +bool ExtensionTestNotificationObserver::WaitForExtensionCrash( |
| + const std::string& extension_id) { |
| + if (!GetNonTerminatedExtensions(extension_id, context_)) { |
| + // The extension is already unloaded, presumably due to a crash. |
| + return true; |
| + } |
| + |
| + content::WindowedNotificationObserver( |
| + extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
| + content::NotificationService::AllSources()) |
| + .Wait(); |
| + return (GetNonTerminatedExtensions(extension_id, context_) == NULL); |
| +} |
| + |
| +bool ExtensionTestNotificationObserver::WaitForCrxInstallerDone() { |
| + int before = crx_installers_done_observed_; |
| + WaitForNotification(extensions::NOTIFICATION_CRX_INSTALLER_DONE); |
| + return crx_installers_done_observed_ == (before + 1); |
|
Devlin
2016/10/06 15:52:17
no parens
Rahul Chaturvedi
2016/10/11 20:12:35
Done.
|
| +} |
| + |
| +void ExtensionTestNotificationObserver::Watch( |
| + int type, |
| + const content::NotificationSource& source) { |
| + CHECK(!observer_); |
| + observer_.reset(new content::WindowedNotificationObserver(type, source)); |
| + registrar_.Add(this, type, source); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::Wait() { |
| + observer_->Wait(); |
| + |
| + registrar_.RemoveAll(); |
| + observer_.reset(); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + switch (type) { |
| + case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: |
| + last_loaded_extension_id_ = |
| + content::Details<const Extension>(details).ptr()->id(); |
| + VLOG(1) << "Got EXTENSION_LOADED notification."; |
| + break; |
| + |
| + case extensions::NOTIFICATION_CRX_INSTALLER_DONE: |
| + VLOG(1) << "Got CRX_INSTALLER_DONE notification."; |
| + { |
| + const Extension* extension = |
| + content::Details<const Extension>(details).ptr(); |
| + if (extension) |
| + last_loaded_extension_id_ = extension->id(); |
| + else |
| + last_loaded_extension_id_.clear(); |
| + } |
| + ++crx_installers_done_observed_; |
| + break; |
| + |
| + case extensions::NOTIFICATION_EXTENSION_LOAD_ERROR: |
| + VLOG(1) << "Got EXTENSION_LOAD_ERROR notification."; |
| + ++extension_load_errors_observed_; |
| + break; |
| + |
| + default: |
| + NOTREACHED(); |
| + break; |
| + } |
| +} |
| + |
| +void ExtensionTestNotificationObserver::WaitForCondition( |
| + const ConditionCallback& condition, |
| + NotificationSet* notification_set) { |
| + if (condition.Run()) |
| + return; |
| + condition_ = condition; |
| + |
| + scoped_refptr<content::MessageLoopRunner> runner( |
| + new content::MessageLoopRunner); |
| + quit_closure_ = runner->QuitClosure(); |
| + |
| + std::unique_ptr<base::CallbackList<void()>::Subscription> subscription; |
| + if (notification_set) { |
| + subscription = notification_set->callback_list().Add(base::Bind( |
| + &ExtensionTestNotificationObserver::MaybeQuit, base::Unretained(this))); |
| + } |
| + runner->Run(); |
| + |
| + condition_.Reset(); |
| + quit_closure_.Reset(); |
| +} |
| + |
| +void ExtensionTestNotificationObserver::MaybeQuit() { |
| + if (condition_.Run()) |
| + quit_closure_.Run(); |
| +} |