Commit 93cd24be authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Update SessionRestoreStatsCollector to use TabLoadTracker.

This is necessary in order for it to work when the PageAlmostIdle
feature is enabled.

BUG=829933

Change-Id: Ic3158a984713ceef849788eaa758ecaa255eba5a
Reviewed-on: https://chromium-review.googlesource.com/1097421Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567484}
parent 7a8d2a31
...@@ -113,6 +113,10 @@ class SessionRestoreObserverTest : public ChromeRenderViewHostTestHarness { ...@@ -113,6 +113,10 @@ class SessionRestoreObserverTest : public ChromeRenderViewHostTestHarness {
void LoadWebContents(content::WebContents* contents) { void LoadWebContents(content::WebContents* contents) {
WebContentsTester::For(contents)->NavigateAndCommit(GURL(kDefaultUrl)); WebContentsTester::For(contents)->NavigateAndCommit(GURL(kDefaultUrl));
WebContentsTester::For(contents)->TestSetIsLoading(false); WebContentsTester::For(contents)->TestSetIsLoading(false);
// Transition through LOADING to LOADED in order to keep the
// SessionRestoreStatsCollector state machine happy.
TabLoadTracker::Get()->TransitionStateForTesting(contents,
TabLoadTracker::LOADING);
TabLoadTracker::Get()->TransitionStateForTesting(contents, TabLoadTracker::Get()->TransitionStateForTesting(contents,
TabLoadTracker::LOADED); TabLoadTracker::LOADED);
mock_observer_.OnDidRestoreTab(contents); mock_observer_.OnDidRestoreTab(contents);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/callback_list.h" #include "base/callback_list.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/time/tick_clock.h" #include "base/time/tick_clock.h"
#include "chrome/browser/resource_coordinator/tab_load_tracker.h"
#include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/session_restore_delegate.h" #include "chrome/browser/sessions/session_restore_delegate.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
...@@ -47,8 +48,9 @@ class RenderWidgetHost; ...@@ -47,8 +48,9 @@ class RenderWidgetHost;
// presence of an unavailable network, or when tabs are closed during loading. // presence of an unavailable network, or when tabs are closed during loading.
// Rethink the collection in these cases. // Rethink the collection in these cases.
class SessionRestoreStatsCollector class SessionRestoreStatsCollector
: public content::NotificationObserver, : public base::RefCounted<SessionRestoreStatsCollector>,
public base::RefCounted<SessionRestoreStatsCollector> { public content::NotificationObserver,
public resource_coordinator::TabLoadTracker::Observer {
public: public:
// Houses all of the statistics gathered by the SessionRestoreStatsCollector // Houses all of the statistics gathered by the SessionRestoreStatsCollector
// while the underlying TabLoader is active. These statistics are all reported // while the underlying TabLoader is active. These statistics are all reported
...@@ -160,19 +162,24 @@ class SessionRestoreStatsCollector ...@@ -160,19 +162,24 @@ class SessionRestoreStatsCollector
~SessionRestoreStatsCollector() override; ~SessionRestoreStatsCollector() override;
// NotificationObserver method. This is the workhorse of the class and drives // NotificationObserver method. Used for detecting first paint.
// all state transitions.
void Observe(int type, void Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// Called when a tab is no longer tracked. This is called by the 'Observe' // resource_coordinator::TabLoadTracker::Observer implementation:
// notification callback. Takes care of unregistering all observers and void OnLoadingStateChange(content::WebContents* contents,
// removing the tab from all internal data structures. LoadingState old_loading_state,
LoadingState new_loading_state) override;
void OnStopTracking(content::WebContents* contents,
LoadingState loading_state) override;
// Called when a tab is no longer tracked. Takes care of unregistering all
// observers and removing the tab from all internal data structures.
void RemoveTab(content::NavigationController* tab); void RemoveTab(content::NavigationController* tab);
// Registers for relevant notifications for a tab and inserts the tab into // Registers for relevant notifications for a tab and inserts the tab into
// to tabs_tracked_ map. Return a pointer to the newly created TabState. // the |tabs_tracked_| map. Return a pointer to the newly created TabState.
TabState* RegisterForNotifications(content::NavigationController* tab); TabState* RegisterForNotifications(content::NavigationController* tab);
// Returns the tab state, nullptr if not found. // Returns the tab state, nullptr if not found.
...@@ -182,6 +189,9 @@ class SessionRestoreStatsCollector ...@@ -182,6 +189,9 @@ class SessionRestoreStatsCollector
// Marks a tab as loading. // Marks a tab as loading.
void MarkTabAsLoading(TabState* tab_state); void MarkTabAsLoading(TabState* tab_state);
// Marks a tab as loaded.
void MarkTabAsLoaded(TabState* tab_state);
// Checks to see if the SessionRestoreStatsCollector has finished collecting, // Checks to see if the SessionRestoreStatsCollector has finished collecting,
// and if so, releases the self reference to the shared pointer. // and if so, releases the self reference to the shared pointer.
void ReleaseIfDoneTracking(); void ReleaseIfDoneTracking();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "chrome/browser/resource_coordinator/tab_helper.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
...@@ -24,6 +25,9 @@ ...@@ -24,6 +25,9 @@
namespace { namespace {
using resource_coordinator::TabLoadTracker;
using resource_coordinator::ResourceCoordinatorTabHelper;
using TabLoaderStats = SessionRestoreStatsCollector::TabLoaderStats; using TabLoaderStats = SessionRestoreStatsCollector::TabLoaderStats;
using StatsReportingDelegate = using StatsReportingDelegate =
SessionRestoreStatsCollector::StatsReportingDelegate; SessionRestoreStatsCollector::StatsReportingDelegate;
...@@ -277,36 +281,32 @@ class SessionRestoreStatsCollectorTest : public testing::Test { ...@@ -277,36 +281,32 @@ class SessionRestoreStatsCollectorTest : public testing::Test {
// Create a last active time in the past. // Create a last active time in the past.
contents->SetLastActiveTime(base::TimeTicks::Now() - contents->SetLastActiveTime(base::TimeTicks::Now() -
base::TimeDelta::FromMinutes(1)); base::TimeDelta::FromMinutes(1));
// TabLoadTracker needs the resource_coordinator WebContentsData to be
// initialized.
ResourceCoordinatorTabHelper::CreateForWebContents(contents);
restored_tabs_.push_back(RestoredTab(contents, is_active, false, false)); restored_tabs_.push_back(RestoredTab(contents, is_active, false, false));
if (is_active) if (is_active)
Show(restored_tabs_.size() - 1); Show(restored_tabs_.size() - 1);
} }
// Helper function for various notification generation.
void GenerateControllerNotification(size_t tab_index, int type) {
content::WebContents* contents = restored_tabs_[tab_index].contents();
content::NavigationController* controller = &contents->GetController();
stats_collector_->Observe(
type, content::Source<content::NavigationController>(controller),
content::NotificationService::NoDetails());
}
// Generates a load start notification for the given tab. // Generates a load start notification for the given tab.
void GenerateLoadStart(size_t tab_index) { void GenerateLoadStart(size_t tab_index) {
GenerateControllerNotification(tab_index, content::NOTIFICATION_LOAD_START); content::WebContents* contents = restored_tabs_[tab_index].contents();
TabLoadTracker::Get()->TransitionStateForTesting(contents,
TabLoadTracker::LOADING);
} }
// Generates a load stop notification for the given tab. // Generates a load stop notification for the given tab.
void GenerateLoadStop(size_t tab_index) { void GenerateLoadStop(size_t tab_index) {
GenerateControllerNotification(tab_index, content::NOTIFICATION_LOAD_STOP); content::WebContents* contents = restored_tabs_[tab_index].contents();
TabLoadTracker::Get()->TransitionStateForTesting(contents,
TabLoadTracker::LOADED);
} }
// Generates a web contents destroyed notification for the given tab. // Generates a web contents destroyed notification for the given tab.
void GenerateWebContentsDestroyed(size_t tab_index) { void GenerateWebContentsDestroyed(size_t tab_index) {
content::WebContents* contents = restored_tabs_[tab_index].contents(); content::WebContents* contents = restored_tabs_[tab_index].contents();
stats_collector_->Observe(content::NOTIFICATION_WEB_CONTENTS_DESTROYED, test_web_contents_factory_->DestroyWebContents(contents);
content::Source<content::WebContents>(contents),
content::NotificationService::NoDetails());
} }
// Generates a paint notification for the given tab. // Generates a paint notification for the given tab.
......
...@@ -69,8 +69,13 @@ class TabLoaderTest : public testing::Test { ...@@ -69,8 +69,13 @@ class TabLoaderTest : public testing::Test {
} }
void SimulateLoaded(size_t tab_index) { void SimulateLoaded(size_t tab_index) {
TabLoadTracker::Get()->TransitionStateForTesting( // Transition to a LOADED state. This has to pass through the LOADING state
restored_tabs_[tab_index].contents(), TabLoadTracker::LOADED); // in order to satisfy the internal logic of SessionRestoreStatsCollector.
auto* contents = restored_tabs_[tab_index].contents();
auto* tracker = TabLoadTracker::Get();
if (tracker->GetLoadingState(contents) != TabLoadTracker::LOADING)
tracker->TransitionStateForTesting(contents, TabLoadTracker::LOADING);
tracker->TransitionStateForTesting(contents, TabLoadTracker::LOADED);
} }
void SimulateLoadedAll() { void SimulateLoadedAll() {
......
...@@ -36,6 +36,9 @@ class TestWebContentsFactory { ...@@ -36,6 +36,9 @@ class TestWebContentsFactory {
// Ownership remains with the TestWebContentsFactory. // Ownership remains with the TestWebContentsFactory.
WebContents* CreateWebContents(BrowserContext* context); WebContents* CreateWebContents(BrowserContext* context);
// Destroys the provided WebContents.
void DestroyWebContents(WebContents* contents);
private: private:
// The test factory (and friends) for creating test web contents. // The test factory (and friends) for creating test web contents.
std::unique_ptr<RenderViewHostTestEnabler> rvh_enabler_; std::unique_ptr<RenderViewHostTestEnabler> rvh_enabler_;
......
...@@ -36,4 +36,15 @@ WebContents* TestWebContentsFactory::CreateWebContents( ...@@ -36,4 +36,15 @@ WebContents* TestWebContentsFactory::CreateWebContents(
return web_contents_.back().get(); return web_contents_.back().get();
} }
void TestWebContentsFactory::DestroyWebContents(WebContents* contents) {
auto it = web_contents_.begin();
for (; it != web_contents_.end(); ++it) {
if (it->get() == contents)
break;
}
if (it == web_contents_.end())
return;
web_contents_.erase(it);
}
} // namespace content } // namespace content
...@@ -79,6 +79,7 @@ MainThreadMetricsHelper::MainThreadMetricsHelper( ...@@ -79,6 +79,7 @@ MainThreadMetricsHelper::MainThreadMetricsHelper(
bool renderer_backgrounded) bool renderer_backgrounded)
: MetricsHelper(WebThreadType::kMainThread), : MetricsHelper(WebThreadType::kMainThread),
main_thread_scheduler_(main_thread_scheduler), main_thread_scheduler_(main_thread_scheduler),
renderer_shutting_down_(false),
is_page_almost_idle_signal_enabled_( is_page_almost_idle_signal_enabled_(
::resource_coordinator::IsPageAlmostIdleSignalEnabled()), ::resource_coordinator::IsPageAlmostIdleSignalEnabled()),
main_thread_load_tracker_( main_thread_load_tracker_(
...@@ -134,6 +135,7 @@ void MainThreadMetricsHelper::OnRendererBackgrounded(base::TimeTicks now) { ...@@ -134,6 +135,7 @@ void MainThreadMetricsHelper::OnRendererBackgrounded(base::TimeTicks now) {
} }
void MainThreadMetricsHelper::OnRendererShutdown(base::TimeTicks now) { void MainThreadMetricsHelper::OnRendererShutdown(base::TimeTicks now) {
renderer_shutting_down_ = true;
foreground_main_thread_load_tracker_.RecordIdle(now); foreground_main_thread_load_tracker_.RecordIdle(now);
background_main_thread_load_tracker_.RecordIdle(now); background_main_thread_load_tracker_.RecordIdle(now);
main_thread_load_tracker_.RecordIdle(now); main_thread_load_tracker_.RecordIdle(now);
...@@ -491,6 +493,13 @@ void MainThreadMetricsHelper::ReportLowThreadLoadForPageAlmostIdleSignal( ...@@ -491,6 +493,13 @@ void MainThreadMetricsHelper::ReportLowThreadLoadForPageAlmostIdleSignal(
if (!is_page_almost_idle_signal_enabled_) if (!is_page_almost_idle_signal_enabled_)
return; return;
// Avoid sending IPCs when the renderer is shutting down as this wreaks havoc
// in test harnesses. These messages aren't needed in production code either
// as the endpoint receiving them dies shortly after and does nothing with
// them.
if (renderer_shutting_down_)
return;
static const int main_thread_task_load_low_threshold = static const int main_thread_task_load_low_threshold =
::resource_coordinator::GetMainThreadTaskLoadLowThreshold(); ::resource_coordinator::GetMainThreadTaskLoadLowThreshold();
......
...@@ -55,6 +55,11 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper { ...@@ -55,6 +55,11 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
// Set to true when OnRendererShutdown is called. Used to ensure that metrics
// that need to cross IPC boundaries aren't sent, as they cause additional
// useless tasks to be posted.
bool renderer_shutting_down_;
const bool is_page_almost_idle_signal_enabled_; const bool is_page_almost_idle_signal_enabled_;
base::Optional<base::TimeTicks> last_reported_task_; base::Optional<base::TimeTicks> last_reported_task_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment