| // 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 "chrome/browser/extensions/chrome_extension_test_notification_observer.h" | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/scoped_observation.h" | 
 | #include "chrome/browser/extensions/extension_action_test_util.h" | 
 | #include "chrome/browser/extensions/extension_util.h" | 
 | #include "chrome/browser/profiles/profile_manager.h" | 
 | #include "chrome/browser/ui/browser.h" | 
 | #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
 | #include "content/public/browser/browser_context.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/test/test_utils.h" | 
 | #include "extensions/browser/notification_types.h" | 
 | #include "extensions/browser/process_manager.h" | 
 | #include "extensions/common/extension.h" | 
 |  | 
 | namespace extensions { | 
 |  | 
 | namespace { | 
 |  | 
 | bool HasPageActionVisibilityReachedTarget( | 
 |     Browser* browser, | 
 |     size_t target_visible_page_action_count) { | 
 |   return extension_action_test_util::GetVisiblePageActionCount( | 
 |              browser->tab_strip_model()->GetActiveWebContents()) == | 
 |          target_visible_page_action_count; | 
 | } | 
 |  | 
 | bool HaveAllExtensionRenderFrameHostsFinishedLoading(ProcessManager* manager) { | 
 |   ProcessManager::FrameSet all_views = manager->GetAllFrames(); | 
 |   for (content::RenderFrameHost* host : manager->GetAllFrames()) { | 
 |     if (content::WebContents::FromRenderFrameHost(host)->IsLoading()) | 
 |       return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | //////////////////////////////////////////////////////////////////////////////// | 
 | // ExtensionTestNotificationObserver | 
 |  | 
 | ChromeExtensionTestNotificationObserver:: | 
 |     ChromeExtensionTestNotificationObserver(Browser* browser) | 
 |     : ExtensionTestNotificationObserver(browser ? browser->profile() : nullptr), | 
 |       browser_(browser) {} | 
 |  | 
 | ChromeExtensionTestNotificationObserver:: | 
 |     ChromeExtensionTestNotificationObserver(content::BrowserContext* context) | 
 |     : ExtensionTestNotificationObserver(context), browser_(nullptr) {} | 
 |  | 
 | ChromeExtensionTestNotificationObserver:: | 
 |     ~ChromeExtensionTestNotificationObserver() {} | 
 |  | 
 | content::BrowserContext* | 
 | ChromeExtensionTestNotificationObserver::GetBrowserContext() { | 
 |   if (!context_) { | 
 |     if (browser_) | 
 |       context_ = browser_->profile(); | 
 |     else | 
 |       context_ = ProfileManager::GetActiveUserProfile(); | 
 |   } | 
 |   return context_; | 
 | } | 
 |  | 
 | bool ChromeExtensionTestNotificationObserver:: | 
 |     WaitForPageActionVisibilityChangeTo(int count) { | 
 |   DCHECK(browser_); | 
 |   base::ScopedObservation<ExtensionActionAPI, ExtensionActionAPI::Observer> | 
 |       observer(this); | 
 |   observer.Observe(ExtensionActionAPI::Get(GetBrowserContext())); | 
 |   WaitForCondition(base::BindRepeating(&HasPageActionVisibilityReachedTarget, | 
 |                                        browser_, count), | 
 |                    nullptr); | 
 |   return true; | 
 | } | 
 |  | 
 | bool ChromeExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { | 
 |   // Some views might not be created yet. This call may become insufficient if | 
 |   // e.g. implementation of ExtensionHostQueue changes. | 
 |   base::RunLoop().RunUntilIdle(); | 
 |  | 
 |   ProcessManager* manager = ProcessManager::Get(GetBrowserContext()); | 
 |   NotificationSet notification_set; | 
 |   notification_set.AddWebContentsDestroyed(manager); | 
 |   notification_set.Add(content::NOTIFICATION_LOAD_STOP); | 
 |   notification_set.AddExtensionFrameUnregistration(manager); | 
 |   WaitForCondition( | 
 |       base::BindRepeating(&HaveAllExtensionRenderFrameHostsFinishedLoading, | 
 |                           manager), | 
 |       ¬ification_set); | 
 |   return true; | 
 | } | 
 |  | 
 | bool ChromeExtensionTestNotificationObserver::WaitForExtensionIdle( | 
 |     const std::string& extension_id) { | 
 |   NotificationSet notification_set; | 
 |   notification_set.Add(content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 
 |   WaitForCondition(base::BindRepeating(&util::IsExtensionIdle, extension_id, | 
 |                                        GetBrowserContext()), | 
 |                    ¬ification_set); | 
 |   return true; | 
 | } | 
 |  | 
 | bool ChromeExtensionTestNotificationObserver::WaitForExtensionNotIdle( | 
 |     const std::string& extension_id) { | 
 |   NotificationSet notification_set; | 
 |   notification_set.Add(content::NOTIFICATION_LOAD_STOP); | 
 |   WaitForCondition(base::BindRepeating( | 
 |                        [](const std::string& extension_id, | 
 |                           content::BrowserContext* context) -> bool { | 
 |                          return !util::IsExtensionIdle(extension_id, context); | 
 |                        }, | 
 |                        extension_id, GetBrowserContext()), | 
 |                    ¬ification_set); | 
 |   return true; | 
 | } | 
 |  | 
 | void ChromeExtensionTestNotificationObserver::OnExtensionActionUpdated( | 
 |     ExtensionAction* extension_action, | 
 |     content::WebContents* web_contents, | 
 |     content::BrowserContext* browser_context) { | 
 |   MaybeQuit(); | 
 | } | 
 |  | 
 | }  // namespace extensions |