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