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..8364bf9c6b0f6dd815086777da0ca099ed635f06 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" |
@@ -221,9 +224,98 @@ |
#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 { |
jam
2015/03/23 23:19:44
nit: this would be much smaller lines if the metho
michaeln
2015/03/24 23:01:11
Done.
|
+ public: |
+ StartupObserver() : weak_factory_(this) {} |
+ ~StartupObserver() override {} |
+ |
+ void Start(); |
+ |
+ private: |
+ void OnStartupComplete(); |
+ void OnFailsafeTimeout(); |
+ |
+ // 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; |
+ |
+ base::WeakPtrFactory<StartupObserver> weak_factory_; |
+}; |
cmumford
2015/03/23 23:57:20
Not sure: Is DISALLOW_COPY_AND_ASSIGN required for
michaeln
2015/03/24 23:01:12
Done.
|
+ |
+void StartupObserver::Start() { |
+ // Signal completion quickly when there is no first page to load. |
+ int kShortDelaySecs = 3; |
cmumford
2015/03/23 23:57:19
const int kShortDelaySecs = 3;
michaeln
2015/03/24 23:01:11
Done.
|
+ base::TimeDelta delay = base::TimeDelta::FromSeconds(kShortDelaySecs); |
+ |
+#if !defined(OS_ANDROID) |
michaeln
2015/03/23 20:24:23
FUD: Initially mimic'ing chrome_browser_main_extra
|
+ 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); |
+} |
+ |
+void StartupObserver::OnStartupComplete() { |
+ SetBrowserStartupIsComplete(); |
+ delete this; |
+} |
+ |
+void StartupObserver::OnFailsafeTimeout() { |
+ OnStartupComplete(); |
+} |
+ |
+void StartupObserver::DidFinishLoad(content::RenderFrameHost* render_frame_host, |
+ const GURL& validated_url) { |
+ if (web_contents()->GetMainFrame() == render_frame_host) |
cmumford
2015/03/23 23:57:19
The rest of Chrome does if (!render_frame_host->Ge
michaeln
2015/03/24 23:01:11
thnx, done
|
+ OnStartupComplete(); |
+} |
+ |
+void StartupObserver::DidFailLoad(content::RenderFrameHost* render_frame_host, |
+ const GURL& validated_url, |
+ int error_code, |
+ const base::string16& error_description) { |
+ if (web_contents()->GetMainFrame() == render_frame_host) |
+ OnStartupComplete(); |
+} |
+ |
+void StartupObserver::WebContentsDestroyed() { |
+ OnStartupComplete(); |
+} |
+ |
// This function provides some ways to test crash and assertion handling |
// behavior of the program. |
void HandleTestParameters(const base::CommandLine& command_line) { |
@@ -588,6 +680,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 +1204,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() { |
@@ -1735,3 +1833,7 @@ void ChromeBrowserMainParts::PostDestroyThreads() { |
void ChromeBrowserMainParts::AddParts(ChromeBrowserMainExtraParts* parts) { |
chrome_extra_parts_.push_back(parts); |
} |
+ |
+bool IsBrowserStartupComplete() { |
+ return g_startup_complete_flag.Get().IsSet(); |
+} |