Chromium Code Reviews| Index: chrome/browser/chrome_browser_main.cc |
| diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc |
| index 1d362a634301b4178ce2a3d3f6b57a56dcf1a639..0881617f6db13664d86d41e507bb011089cb58c8 100644 |
| --- a/chrome/browser/chrome_browser_main.cc |
| +++ b/chrome/browser/chrome_browser_main.cc |
| @@ -31,6 +31,7 @@ |
| #include "base/strings/string_split.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| +#include "base/synchronization/cancellation_flag.h" |
| #include "base/sys_info.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/time/time.h" |
| @@ -85,10 +86,12 @@ |
| #include "chrome/browser/ui/app_list/app_list_service.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| +#include "chrome/browser/ui/browser_iterator.h" |
| #include "chrome/browser/ui/host_desktop.h" |
| #include "chrome/browser/ui/startup/bad_flags_prompt.h" |
| #include "chrome/browser/ui/startup/default_browser_prompt.h" |
| #include "chrome/browser/ui/startup/startup_browser_creator.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/browser/ui/uma_browsing_activity_observer.h" |
| #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" |
| #include "chrome/common/chrome_constants.h" |
| @@ -224,6 +227,87 @@ using content::BrowserThread; |
| namespace { |
| +using StartupCompleteFlag = base::CancellationFlag; |
| +base::LazyInstance<StartupCompleteFlag>::Leaky g_startup_complete_flag; |
| + |
| +// Used to monitor the first page load to inform PostAfterStartupTask. |
| +class StartupObserver : public content::WebContentsObserver { |
| + public: |
| + static void Start(); |
| + |
| + private: |
| + static content::WebContents* GetFirstWebContents(); |
| + static void SetBrowserStartupIsComplete(); |
|
michaeln
2015/03/20 00:21:28
i'll probably have to expose SetBrowserStartupIsCo
|
| + |
| + explicit StartupObserver(content::WebContents* web_contents) |
| + : content::WebContentsObserver(web_contents) {} |
| + |
| + // WebContentsObserver overrides |
| + void DidFinishLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url) override; |
| + void DidFailLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url, |
| + int error_code, |
| + const base::string16& error_description) override; |
| + void WebContentsDestroyed() override; |
| +}; |
| + |
| +void StartupObserver::Start() { |
| + // Signal completion quickly when there is no first page to load. |
| + int kDefaultDelaySecs = 3; |
| + base::TimeDelta delay = base::TimeDelta::FromSeconds(kDefaultDelaySecs); |
| + |
| +#if !defined(OS_ANDROID) |
| + content::WebContents* web_contents = GetFirstWebContents(); |
| + if (web_contents) { |
| + // StartupObserver is self deleting. |
| + new StartupObserver(web_contents); |
| + |
| + // In case startup oberver never signals completion. |
| + const int kFailsafeDelayMins = 3; |
| + delay = base::TimeDelta::FromMinutes(kFailsafeDelayMins); |
| + } |
| +#endif // !defined(OS_ANDROID) |
| + |
| + BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, |
| + base::Bind(&SetBrowserStartupIsComplete), |
| + delay); |
| +} |
| + |
| +content::WebContents* StartupObserver::GetFirstWebContents() { |
| + for (chrome::BrowserIterator iterator; !iterator.done(); iterator.Next()) { |
| + Browser* browser = *iterator; |
| + content::WebContents* web_contents = |
| + browser->tab_strip_model()->GetActiveWebContents(); |
| + if (web_contents) |
| + return web_contents; |
| + } |
| + return nullptr; |
| +} |
| + |
| +void StartupObserver::SetBrowserStartupIsComplete() { |
| + g_startup_complete_flag.Get().Set(); |
| +} |
| + |
| +void StartupObserver::DidFinishLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url) { |
| + SetBrowserStartupIsComplete(); |
| + delete this; |
| +} |
| + |
| +void StartupObserver::DidFailLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url, |
| + int error_code, |
| + const base::string16& error_description) { |
| + SetBrowserStartupIsComplete(); |
| + delete this; |
| +} |
| + |
| +void StartupObserver::WebContentsDestroyed() { |
| + SetBrowserStartupIsComplete(); |
| + delete this; |
| +} |
| + |
| // This function provides some ways to test crash and assertion handling |
| // behavior of the program. |
| void HandleTestParameters(const base::CommandLine& command_line) { |
| @@ -588,6 +672,9 @@ ChromeBrowserMainParts::ChromeBrowserMainParts( |
| // cookies need to go through one of Chrome's URLRequestContexts which have |
| // a ChromeNetworkDelegate attached that selectively allows cookies again. |
| net::URLRequest::SetDefaultCookiePolicyToBlock(); |
| + |
| + // Be sure to allocate the lazy instance on the main thread. |
| + g_startup_complete_flag.Get(); |
| } |
| ChromeBrowserMainParts::~ChromeBrowserMainParts() { |
| @@ -1109,6 +1196,7 @@ void ChromeBrowserMainParts::PostBrowserStart() { |
| base::Bind(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles), |
| base::TimeDelta::FromMinutes(1)); |
| #endif // defined(ENABLE_WEBRTC) |
| + StartupObserver::Start(); |
| } |
| int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { |
| @@ -1735,3 +1823,7 @@ void ChromeBrowserMainParts::PostDestroyThreads() { |
| void ChromeBrowserMainParts::AddParts(ChromeBrowserMainExtraParts* parts) { |
| chrome_extra_parts_.push_back(parts); |
| } |
| + |
| +bool IsBrowserStartupComplete() { |
| + return g_startup_complete_flag.Get().IsSet(); |
| +} |