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(); |
+} |