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 fb5034032e2085bdb551bd929c5420f4eb78b692..a0aa6621d59ea3066e3c34766bfbe92a6499e4ba 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" |
| @@ -124,6 +127,7 @@ |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| #include "content/public/browser/power_usage_monitor.h" |
| +#include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/site_instance.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/content_switches.h" |
| @@ -221,9 +225,85 @@ |
| #endif // defined(USE_AURA) |
| using content::BrowserThread; |
| +using content::WebContents; |
| +using content::WebContentsObserver; |
| namespace { |
| +// The basis for when tasks posted via PostAfterStartupTasks begin running. |
| +using StartupCompleteFlag = base::CancellationFlag; |
| +base::LazyInstance<StartupCompleteFlag>::Leaky g_startup_complete_flag; |
| + |
| +void SetBrowserStartupIsComplete() { |
| + g_startup_complete_flag.Get().Set(); |
|
jam
2015/03/26 15:38:58
what I had meant earlier (sorry if not clear), is
michaeln
2015/03/26 19:52:33
I've been trying to avoid providing an API to list
jam
2015/03/26 20:22:08
Why doesn't CCBC forward the tasks it gets to a fi
michaeln
2015/03/26 21:39:36
I guess I was trying to avoid the addition of a ne
|
| +} |
| + |
| +// Observes the first page load and set the startup complete flag accordingly. |
| +class StartupObserver : public WebContentsObserver { |
| + public: |
| + StartupObserver() : weak_factory_(this) {} |
| + ~StartupObserver() override { DCHECK(IsBrowserStartupComplete()); } |
| + |
| + void Start(); |
| + |
| + private: |
| + void OnStartupComplete() { |
| + SetBrowserStartupIsComplete(); |
| + delete this; |
| + } |
| + |
| + void OnFailsafeTimeout() { OnStartupComplete(); } |
| + |
| + // WebContentsObserver overrides |
| + void DidFinishLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url) override { |
| + if (!render_frame_host->GetParent()) |
| + OnStartupComplete(); |
| + } |
| + |
| + void DidFailLoad(content::RenderFrameHost* render_frame_host, |
| + const GURL& validated_url, |
| + int error_code, |
| + const base::string16& error_description) override { |
| + if (!render_frame_host->GetParent()) |
| + OnStartupComplete(); |
| + } |
| + |
| + void WebContentsDestroyed() override { OnStartupComplete(); } |
| + |
| + base::WeakPtrFactory<StartupObserver> weak_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StartupObserver); |
| +}; |
| + |
| +void StartupObserver::Start() { |
| + // Signal completion quickly when there is no first page to load. |
| + const int kShortDelaySecs = 3; |
| + base::TimeDelta delay = base::TimeDelta::FromSeconds(kShortDelaySecs); |
| + |
| +#if !defined(OS_ANDROID) |
| + WebContents* contents = nullptr; |
| + for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) { |
| + contents = (*iter)->tab_strip_model()->GetActiveWebContents(); |
| + if (contents) |
| + break; |
| + } |
| + |
| + if (contents) { |
| + // Give the page time to finish loading. |
| + const int kLongerDelayMins = 3; |
| + Observe(contents); |
| + delay = base::TimeDelta::FromMinutes(kLongerDelayMins); |
| + } |
| +#endif // !defined(OS_ANDROID) |
| + |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&StartupObserver::OnFailsafeTimeout, |
| + weak_factory_.GetWeakPtr()), |
| + delay); |
| +} |
| + |
| // This function provides some ways to test crash and assertion handling |
| // behavior of the program. |
| void HandleTestParameters(const base::CommandLine& command_line) { |
| @@ -590,6 +670,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() { |
| @@ -1111,6 +1194,9 @@ void ChromeBrowserMainParts::PostBrowserStart() { |
| base::Bind(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles), |
| base::TimeDelta::FromMinutes(1)); |
| #endif // defined(ENABLE_WEBRTC) |
| + |
| + // The observer is self-deleting. |
| + (new StartupObserver)->Start(); |
| } |
| int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { |
| @@ -1737,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(); |
| +} |