Commit edb53660 authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Make TabManager use TabLoadTracker for load tracking.

This moves all of the responsibility for handling PageAlmostIdle to TabLoadTracker.

Change-Id: I9325109e896910d76b6aa6a615f9004dc1a4e67d
Reviewed-on: https://chromium-review.googlesource.com/1060569
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarSébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559277}
parent 668c097f
...@@ -26,20 +26,7 @@ ...@@ -26,20 +26,7 @@
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h" #include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
namespace { using resource_coordinator::TabLoadTracker;
// The manager currently doesn't exist on all platforms, which means the
// tab load tracker will not either.
// TODO(chrisha): Make the tab manager exist everywhere. It's going to start
// making scheduling decisions that apply to mobile devices as well, so there's
// no longer any reason for it to be mobile only.
resource_coordinator::TabLoadTracker* GetTabLoadTracker() {
if (auto* manager = g_browser_process->GetTabManager())
return &(manager->tab_load_tracker());
return nullptr;
}
} // namespace
DEFINE_WEB_CONTENTS_USER_DATA_KEY(ResourceCoordinatorWebContentsObserver); DEFINE_WEB_CONTENTS_USER_DATA_KEY(ResourceCoordinatorWebContentsObserver);
...@@ -71,8 +58,7 @@ ResourceCoordinatorWebContentsObserver::ResourceCoordinatorWebContentsObserver( ...@@ -71,8 +58,7 @@ ResourceCoordinatorWebContentsObserver::ResourceCoordinatorWebContentsObserver(
page_resource_coordinator_->id(), web_contents); page_resource_coordinator_->id(), web_contents);
} }
if (auto* tracker = GetTabLoadTracker()) TabLoadTracker::Get()->StartTracking(web_contents);
tracker->StartTracking(web_contents);
} }
ResourceCoordinatorWebContentsObserver:: ResourceCoordinatorWebContentsObserver::
...@@ -87,20 +73,16 @@ bool ResourceCoordinatorWebContentsObserver::IsEnabled() { ...@@ -87,20 +73,16 @@ bool ResourceCoordinatorWebContentsObserver::IsEnabled() {
void ResourceCoordinatorWebContentsObserver::DidStartLoading() { void ResourceCoordinatorWebContentsObserver::DidStartLoading() {
page_resource_coordinator_->SetIsLoading(true); page_resource_coordinator_->SetIsLoading(true);
TabLoadTracker::Get()->DidStartLoading(web_contents());
if (auto* tracker = GetTabLoadTracker())
tracker->DidStartLoading(web_contents());
} }
void ResourceCoordinatorWebContentsObserver::DidReceiveResponse() { void ResourceCoordinatorWebContentsObserver::DidReceiveResponse() {
if (auto* tracker = GetTabLoadTracker()) TabLoadTracker::Get()->DidReceiveResponse(web_contents());
tracker->DidReceiveResponse(web_contents());
} }
void ResourceCoordinatorWebContentsObserver::DidStopLoading() { void ResourceCoordinatorWebContentsObserver::DidStopLoading() {
page_resource_coordinator_->SetIsLoading(false); page_resource_coordinator_->SetIsLoading(false);
if (auto* tracker = GetTabLoadTracker()) TabLoadTracker::Get()->DidStopLoading(web_contents());
tracker->DidStopLoading(web_contents());
} }
void ResourceCoordinatorWebContentsObserver::DidFailLoad( void ResourceCoordinatorWebContentsObserver::DidFailLoad(
...@@ -108,8 +90,7 @@ void ResourceCoordinatorWebContentsObserver::DidFailLoad( ...@@ -108,8 +90,7 @@ void ResourceCoordinatorWebContentsObserver::DidFailLoad(
const GURL& validated_url, const GURL& validated_url,
int error_code, int error_code,
const base::string16& error_description) { const base::string16& error_description) {
if (auto* tracker = GetTabLoadTracker()) TabLoadTracker::Get()->DidFailLoad(web_contents());
tracker->DidFailLoad(web_contents());
} }
void ResourceCoordinatorWebContentsObserver::OnVisibilityChanged( void ResourceCoordinatorWebContentsObserver::OnVisibilityChanged(
...@@ -127,8 +108,7 @@ void ResourceCoordinatorWebContentsObserver::WebContentsDestroyed() { ...@@ -127,8 +108,7 @@ void ResourceCoordinatorWebContentsObserver::WebContentsDestroyed() {
page_signal_receiver->RemoveCoordinationUnitID( page_signal_receiver->RemoveCoordinationUnitID(
page_resource_coordinator_->id()); page_resource_coordinator_->id());
} }
if (auto* tracker = GetTabLoadTracker()) TabLoadTracker::Get()->StopTracking(web_contents());
tracker->StopTracking(web_contents());
} }
void ResourceCoordinatorWebContentsObserver::DidFinishNavigation( void ResourceCoordinatorWebContentsObserver::DidFinishNavigation(
...@@ -141,7 +121,7 @@ void ResourceCoordinatorWebContentsObserver::DidFinishNavigation( ...@@ -141,7 +121,7 @@ void ResourceCoordinatorWebContentsObserver::DidFinishNavigation(
content::RenderFrameHost* render_frame_host = content::RenderFrameHost* render_frame_host =
navigation_handle->GetRenderFrameHost(); navigation_handle->GetRenderFrameHost();
// Make sure the hierarchical structure is constructured before sending signal // Make sure the hierarchical structure is constructed before sending signal
// to Resource Coordinator. // to Resource Coordinator.
auto* frame_resource_coordinator = auto* frame_resource_coordinator =
render_frame_host->GetFrameResourceCoordinator(); render_frame_host->GetFrameResourceCoordinator();
......
...@@ -14,9 +14,13 @@ ...@@ -14,9 +14,13 @@
namespace resource_coordinator { namespace resource_coordinator {
TabLoadTracker::TabLoadTracker() {} TabLoadTracker::~TabLoadTracker() = default;
TabLoadTracker::~TabLoadTracker() {} // static
TabLoadTracker* TabLoadTracker::Get() {
static base::NoDestructor<TabLoadTracker> tab_load_tracker;
return tab_load_tracker.get();
}
TabLoadTracker::LoadingState TabLoadTracker::GetLoadingState( TabLoadTracker::LoadingState TabLoadTracker::GetLoadingState(
content::WebContents* web_contents) const { content::WebContents* web_contents) const {
...@@ -61,6 +65,16 @@ void TabLoadTracker::RemoveObserver(Observer* observer) { ...@@ -61,6 +65,16 @@ void TabLoadTracker::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void TabLoadTracker::TransitionStateForTesting(
content::WebContents* web_contents,
LoadingState loading_state) {
auto it = tabs_.find(web_contents);
DCHECK(it != tabs_.end());
TransitionState(it, loading_state, false);
}
TabLoadTracker::TabLoadTracker() = default;
void TabLoadTracker::StartTracking(content::WebContents* web_contents) { void TabLoadTracker::StartTracking(content::WebContents* web_contents) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!base::ContainsKey(tabs_, web_contents)); DCHECK(!base::ContainsKey(tabs_, web_contents));
...@@ -121,7 +135,7 @@ void TabLoadTracker::DidReceiveResponse(content::WebContents* web_contents) { ...@@ -121,7 +135,7 @@ void TabLoadTracker::DidReceiveResponse(content::WebContents* web_contents) {
// actual network requests, but not the rest of the state machinery. // actual network requests, but not the rest of the state machinery.
if (!it->second.did_start_loading_seen) if (!it->second.did_start_loading_seen)
return; return;
TransitionState(it, LOADING); TransitionState(it, LOADING, true);
} }
void TabLoadTracker::DidStopLoading(content::WebContents* web_contents) { void TabLoadTracker::DidStopLoading(content::WebContents* web_contents) {
...@@ -176,12 +190,14 @@ void TabLoadTracker::MaybeTransitionToLoaded( ...@@ -176,12 +190,14 @@ void TabLoadTracker::MaybeTransitionToLoaded(
DCHECK(it != tabs_.end()); DCHECK(it != tabs_.end());
if (it->second.loading_state != LOADING) if (it->second.loading_state != LOADING)
return; return;
TransitionState(it, LOADED); TransitionState(it, LOADED, true);
} }
void TabLoadTracker::TransitionState(TabMap::iterator it, void TabLoadTracker::TransitionState(TabMap::iterator it,
LoadingState loading_state) { LoadingState loading_state,
bool validate_transition) {
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
if (validate_transition) {
// Validate the transition. // Validate the transition.
switch (loading_state) { switch (loading_state) {
case LOADING: { case LOADING: {
...@@ -200,6 +216,7 @@ void TabLoadTracker::TransitionState(TabMap::iterator it, ...@@ -200,6 +216,7 @@ void TabLoadTracker::TransitionState(TabMap::iterator it,
case LOADING_STATE_MAX: case LOADING_STATE_MAX:
NOTREACHED(); NOTREACHED();
} }
}
#endif #endif
--state_counts_[it->second.loading_state]; --state_counts_[it->second.loading_state];
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
...@@ -33,8 +34,7 @@ class TabManagerResourceCoordinatorSignalObserverHelper; ...@@ -33,8 +34,7 @@ class TabManagerResourceCoordinatorSignalObserverHelper;
// thread. // thread.
// //
// This class is intended to be created in early startup and persists as a // This class is intended to be created in early startup and persists as a
// singleton in the browser process, owned by the TabManager. It is deliberately // singleton in the browser process. It is deliberately leaked at shutdown.
// leaked at shutdown.
// //
// This class isn't directly an observer of anything. An external source must // This class isn't directly an observer of anything. An external source must
// invoke the callbacks in the protected section of the class. In the case of // invoke the callbacks in the protected section of the class. In the case of
...@@ -47,13 +47,15 @@ class TabLoadTracker { ...@@ -47,13 +47,15 @@ class TabLoadTracker {
// state changes. // state changes.
class Observer; class Observer;
// Indicates the loading state of a WebContents. // Indicates the loading state of a WebContents. These values are written to
// logs and histograms. New enum values can be added, but existing enums must
// never be renumbered or deleted and reused.
enum LoadingState { enum LoadingState {
// An initially constructed WebContents with no loaded content is UNLOADED. // An initially constructed WebContents with no loaded content is UNLOADED.
// A WebContents that started loading but that errored out before receiving // A WebContents that started loading but that errored out before receiving
// sufficient content to render is also considered UNLOADED. // sufficient content to render is also considered UNLOADED.
// Can only transition from here to LOADING. // Can only transition from here to LOADING.
UNLOADED, UNLOADED = 0,
// A WebContents with an ongoing main-frame navigation (to a new document) // A WebContents with an ongoing main-frame navigation (to a new document)
// is in a loading state. More precisely, it is considered loading once // is in a loading state. More precisely, it is considered loading once
// network data has started to be transmitted, and not simply when the // network data has started to be transmitted, and not simply when the
...@@ -61,22 +63,24 @@ class TabLoadTracker { ...@@ -61,22 +63,24 @@ class TabLoadTracker {
// loading, and will only transition to loading once the throttle has been // loading, and will only transition to loading once the throttle has been
// removed. // removed.
// Can transition from here to UNLOADED or LOADED. // Can transition from here to UNLOADED or LOADED.
LOADING, LOADING = 1,
// A WebContents with a committed navigation whose // A WebContents with a committed navigation whose
// DidStopLoading/PageAlmostIdle event (depending on mode) or DidFailLoad // DidStopLoading/PageAlmostIdle event (depending on mode) or DidFailLoad
// event has fired is no longer considered to be LOADING. If any content has // event has fired is no longer considered to be LOADING. If any content has
// been rendered prior to the failure the document is considered LOADED, // been rendered prior to the failure the document is considered LOADED,
// otherwise it is considered UNLOADED. // otherwise it is considered UNLOADED.
// Can transition from here to LOADING. // Can transition from here to LOADING.
LOADED, LOADED = 2,
// This must be last. // This must be last.
LOADING_STATE_MAX LOADING_STATE_MAX
}; };
TabLoadTracker();
~TabLoadTracker(); ~TabLoadTracker();
// Returns the singleton TabLoadTracker instance.
static TabLoadTracker* Get();
// Allows querying the state of a tab. The provided |web_contents| must be // Allows querying the state of a tab. The provided |web_contents| must be
// actively tracked. // actively tracked.
LoadingState GetLoadingState(content::WebContents* web_contents) const; LoadingState GetLoadingState(content::WebContents* web_contents) const;
...@@ -95,13 +99,23 @@ class TabLoadTracker { ...@@ -95,13 +99,23 @@ class TabLoadTracker {
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
// Exposed so that state transitions can be simulated in tests.
void TransitionStateForTesting(content::WebContents* web_contents,
LoadingState loading_state);
protected: protected:
// This allows the various bits of TabManager plubming to forward // This allows the singleton constructor access to the protected constructor.
// notifications to the TabLoadTracker. friend class base::NoDestructor<TabLoadTracker>;
// These declarations allows the various bits of TabManager plumbing to
// forward notifications to the TabLoadTracker.
friend class ::ResourceCoordinatorWebContentsObserver; friend class ::ResourceCoordinatorWebContentsObserver;
friend class ::resource_coordinator:: friend class ::resource_coordinator::
TabManagerResourceCoordinatorSignalObserverHelper; TabManagerResourceCoordinatorSignalObserverHelper;
// This class is a singleton so the constructor is protected.
TabLoadTracker();
// Initiates tracking of a WebContents. This is fully able to determine the // Initiates tracking of a WebContents. This is fully able to determine the
// initial state of the WebContents, even if it was created long ago // initial state of the WebContents, even if it was created long ago
// (is LOADING or LOADED) and only just attached to the tracker. See the // (is LOADING or LOADED) and only just attached to the tracker. See the
...@@ -144,8 +158,12 @@ class TabLoadTracker { ...@@ -144,8 +158,12 @@ class TabLoadTracker {
void MaybeTransitionToLoaded(content::WebContents* web_contents); void MaybeTransitionToLoaded(content::WebContents* web_contents);
// Transitions a web contents to the given state. This updates the various // Transitions a web contents to the given state. This updates the various
// |state_counts_| and |tabs_| data. // |state_counts_| and |tabs_| data. Setting |validate_transition| to false
void TransitionState(TabMap::iterator it, LoadingState loading_state); // means that valid state machine transitions aren't enforced via checks; this
// is only used by state transitions forced via TransitionStateForTesting.
void TransitionState(TabMap::iterator it,
LoadingState loading_state,
bool validate_transition);
// The list of known WebContents and their states. // The list of known WebContents and their states.
TabMap tabs_; TabMap tabs_;
......
...@@ -176,11 +176,12 @@ TabManager::TabManager() ...@@ -176,11 +176,12 @@ TabManager::TabManager()
new ResourceCoordinatorSignalObserver()); new ResourceCoordinatorSignalObserver());
} }
stats_collector_.reset(new TabManagerStatsCollector()); stats_collector_.reset(new TabManagerStatsCollector());
proactive_discard_params_ = GetStaticProactiveTabDiscardParams(); proactive_discard_params_ = GetStaticProactiveTabDiscardParams();
TabLoadTracker::Get()->AddObserver(this);
} }
TabManager::~TabManager() { TabManager::~TabManager() {
TabLoadTracker::Get()->RemoveObserver(this);
resource_coordinator_signal_observer_.reset(); resource_coordinator_signal_observer_.reset();
Stop(); Stop();
} }
...@@ -578,6 +579,35 @@ void TabManager::TabReplacedAt(TabStripModel* tab_strip_model, ...@@ -578,6 +579,35 @@ void TabManager::TabReplacedAt(TabStripModel* tab_strip_model,
WebContentsData::CopyState(old_contents, new_contents); WebContentsData::CopyState(old_contents, new_contents);
} }
void TabManager::OnStartTracking(content::WebContents* web_contents,
LoadingState loading_state) {
GetWebContentsData(web_contents)->SetTabLoadingState(loading_state);
}
void TabManager::OnLoadingStateChange(content::WebContents* web_contents,
LoadingState loading_state) {
GetWebContentsData(web_contents)->SetTabLoadingState(loading_state);
if (loading_state == TabLoadTracker::LOADED) {
bool was_in_background_tab_opening_session =
IsInBackgroundTabOpeningSession();
loading_contents_.erase(web_contents);
stats_collector_->OnTabIsLoaded(web_contents);
LoadNextBackgroundTabIfNeeded();
if (was_in_background_tab_opening_session &&
!IsInBackgroundTabOpeningSession()) {
stats_collector_->OnBackgroundTabOpeningSessionEnded();
}
}
}
void TabManager::OnStopTracking(content::WebContents* web_contents,
LoadingState loading_state) {
GetWebContentsData(web_contents)->SetTabLoadingState(loading_state);
}
// static // static
TabManager::WebContentsData* TabManager::GetWebContentsData( TabManager::WebContentsData* TabManager::GetWebContentsData(
content::WebContents* contents) { content::WebContents* contents) {
...@@ -661,8 +691,6 @@ TabManager::MaybeThrottleNavigation(BackgroundTabNavigationThrottle* throttle) { ...@@ -661,8 +691,6 @@ TabManager::MaybeThrottleNavigation(BackgroundTabNavigationThrottle* throttle) {
// Notify TabUIHelper that the navigation is delayed, so that the tab UI such // Notify TabUIHelper that the navigation is delayed, so that the tab UI such
// as favicon and title can be updated accordingly. // as favicon and title can be updated accordingly.
TabUIHelper::FromWebContents(contents)->NotifyInitialNavigationDelayed(true); TabUIHelper::FromWebContents(contents)->NotifyInitialNavigationDelayed(true);
GetWebContentsData(contents)->SetTabLoadingState(TAB_IS_NOT_LOADING);
pending_navigations_.push_back(throttle); pending_navigations_.push_back(throttle);
std::stable_sort(pending_navigations_.begin(), pending_navigations_.end(), std::stable_sort(pending_navigations_.begin(), pending_navigations_.end(),
ComparePendingNavigations); ComparePendingNavigations);
...@@ -713,21 +741,6 @@ void TabManager::OnDidFinishNavigation( ...@@ -713,21 +741,6 @@ void TabManager::OnDidFinishNavigation(
} }
} }
void TabManager::OnTabIsLoaded(content::WebContents* contents) {
DCHECK_EQ(TAB_IS_LOADED, GetWebContentsData(contents)->tab_loading_state());
bool was_in_background_tab_opening_session =
IsInBackgroundTabOpeningSession();
loading_contents_.erase(contents);
stats_collector_->OnTabIsLoaded(contents);
LoadNextBackgroundTabIfNeeded();
if (was_in_background_tab_opening_session &&
!IsInBackgroundTabOpeningSession()) {
stats_collector_->OnBackgroundTabOpeningSessionEnded();
}
}
void TabManager::OnWebContentsDestroyed(content::WebContents* contents) { void TabManager::OnWebContentsDestroyed(content::WebContents* contents) {
bool was_in_background_tab_opening_session = bool was_in_background_tab_opening_session =
IsInBackgroundTabOpeningSession(); IsInBackgroundTabOpeningSession();
...@@ -801,7 +814,6 @@ void TabManager::ResumeTabNavigationIfNeeded(content::WebContents* contents) { ...@@ -801,7 +814,6 @@ void TabManager::ResumeTabNavigationIfNeeded(content::WebContents* contents) {
void TabManager::ResumeNavigation(BackgroundTabNavigationThrottle* throttle) { void TabManager::ResumeNavigation(BackgroundTabNavigationThrottle* throttle) {
content::WebContents* contents = content::WebContents* contents =
throttle->navigation_handle()->GetWebContents(); throttle->navigation_handle()->GetWebContents();
GetWebContentsData(contents)->SetTabLoadingState(TAB_IS_LOADING);
loading_contents_.insert(contents); loading_contents_.insert(contents);
TabUIHelper::FromWebContents(contents)->NotifyInitialNavigationDelayed(false); TabUIHelper::FromWebContents(contents)->NotifyInitialNavigationDelayed(false);
...@@ -855,13 +867,10 @@ int TabManager::GetNumAliveTabs() const { ...@@ -855,13 +867,10 @@ int TabManager::GetNumAliveTabs() const {
} }
bool TabManager::IsTabLoadingForTest(content::WebContents* contents) const { bool TabManager::IsTabLoadingForTest(content::WebContents* contents) const {
if (loading_contents_.count(contents) == 1) { if (base::ContainsKey(loading_contents_, contents))
DCHECK_EQ(TAB_IS_LOADING,
GetWebContentsData(contents)->tab_loading_state());
return true; return true;
} DCHECK_NE(TabLoadTracker::LOADING,
GetWebContentsData(contents)->tab_loading_state());
DCHECK_NE(TAB_IS_LOADING, GetWebContentsData(contents)->tab_loading_state());
return false; return false;
} }
......
...@@ -80,6 +80,7 @@ class TabManagerStatsCollector; ...@@ -80,6 +80,7 @@ class TabManagerStatsCollector;
// TODO(fdoray): Rename to LifecycleManager. https://crbug.com/775644 // TODO(fdoray): Rename to LifecycleManager. https://crbug.com/775644
class TabManager : public LifecycleUnitObserver, class TabManager : public LifecycleUnitObserver,
public LifecycleUnitSourceObserver, public LifecycleUnitSourceObserver,
public TabLoadTracker::Observer,
public TabStripModelObserver { public TabStripModelObserver {
public: public:
// Forward declaration of resource coordinator signal observer. // Forward declaration of resource coordinator signal observer.
...@@ -147,10 +148,6 @@ class TabManager : public LifecycleUnitObserver, ...@@ -147,10 +148,6 @@ class TabManager : public LifecycleUnitObserver,
// before. // before.
void OnDidFinishNavigation(content::NavigationHandle* navigation_handle); void OnDidFinishNavigation(content::NavigationHandle* navigation_handle);
// Called by TabManager::WebContentsData to notify TabManager that one tab is
// considered loaded. TabManager can decide which tab to load next.
void OnTabIsLoaded(content::WebContents* contents);
// Notifies TabManager that one tab WebContents has been destroyed. TabManager // Notifies TabManager that one tab WebContents has been destroyed. TabManager
// needs to clean up data related to that tab. // needs to clean up data related to that tab.
void OnWebContentsDestroyed(content::WebContents* contents); void OnWebContentsDestroyed(content::WebContents* contents);
...@@ -183,67 +180,62 @@ class TabManager : public LifecycleUnitObserver, ...@@ -183,67 +180,62 @@ class TabManager : public LifecycleUnitObserver,
// non-zero only during session restore. // non-zero only during session restore.
int restored_tab_count() const; int restored_tab_count() const;
// Accessor for the tab load tracker. This lets interested external classes
// add themselves as observers.
TabLoadTracker& tab_load_tracker() { return tab_load_tracker_; }
const TabLoadTracker& tab_load_tracker() const { return tab_load_tracker_; }
private: private:
friend class TabManagerStatsCollectorTest; friend class TabManagerStatsCollectorTest;
friend class TabManagerWithProactiveDiscardExperimentEnabledTest; friend class TabManagerWithProactiveDiscardExperimentEnabledTest;
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingMode);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, EnablePageAlmostIdleSignal);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FreezeTab);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OomPressureListener); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsTabRestoredInForeground);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectPDFPages);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerWasDiscarded);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
TabManagerWasDiscardedCrossSiteSubFrame);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, MaybeThrottleNavigation); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, MaybeThrottleNavigation);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDelayedTabSelected);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDidFinishNavigation); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDidFinishNavigation);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnTabIsLoaded); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnTabIsLoaded);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnWebContentsDestroyed); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnWebContentsDestroyed);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDelayedTabSelected); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OomPressureListener);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TimeoutWhenLoadingBackgroundTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingMode);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PauseAndResumeBackgroundTabOpening); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PauseAndResumeBackgroundTabOpening);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerWithExperimentDisabledTest,
IsInBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
SessionRestoreBeforeBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
SessionRestoreAfterBackgroundTabOpeningSession); ProactiveFastShutdownSharedTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
ProactiveFastShutdownSingleTabProcess); ProactiveFastShutdownSingleTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownSingleTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
ProactiveFastShutdownSharedTabProcess); ProactiveFastShutdownWithBeforeunloadHandler);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownSharedTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
ProactiveFastShutdownWithUnloadHandler); ProactiveFastShutdownWithUnloadHandler);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownWithUnloadHandler); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectPDFPages);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
ProactiveFastShutdownWithBeforeunloadHandler); SessionRestoreAfterBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
UrgentFastShutdownWithBeforeunloadHandler); SessionRestoreBeforeBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsTabRestoredInForeground); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, EnablePageAlmostIdleSignal); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FreezeTab); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerWasDiscarded);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
TabManagerWasDiscardedCrossSiteSubFrame);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TimeoutWhenLoadingBackgroundTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
TrackingNumberOfLoadedLifecycleUnits); TrackingNumberOfLoadedLifecycleUnits);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownSharedTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownSingleTabProcess);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
UrgentFastShutdownWithBeforeunloadHandler);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownWithUnloadHandler);
FRIEND_TEST_ALL_PREFIXES(TabManagerWithExperimentDisabledTest,
IsInBackgroundTabOpeningSession);
FRIEND_TEST_ALL_PREFIXES(TabManagerWithProactiveDiscardExperimentEnabledTest, FRIEND_TEST_ALL_PREFIXES(TabManagerWithProactiveDiscardExperimentEnabledTest,
GetTimeInBackgroundBeforeProactiveDiscardTest); GetTimeInBackgroundBeforeProactiveDiscardTest);
...@@ -317,6 +309,14 @@ class TabManager : public LifecycleUnitObserver, ...@@ -317,6 +309,14 @@ class TabManager : public LifecycleUnitObserver,
content::WebContents* new_contents, content::WebContents* new_contents,
int index) override; int index) override;
// TabLoadTracker::Observer implementation:
void OnStartTracking(content::WebContents* web_contents,
LoadingState loading_state) override;
void OnLoadingStateChange(content::WebContents* web_contents,
LoadingState loading_state) override;
void OnStopTracking(content::WebContents* web_contents,
LoadingState loading_state) override;
// Returns the WebContentsData associated with |contents|. Also takes care of // Returns the WebContentsData associated with |contents|. Also takes care of
// creating one if needed. // creating one if needed.
static WebContentsData* GetWebContentsData(content::WebContents* contents); static WebContentsData* GetWebContentsData(content::WebContents* contents);
...@@ -486,10 +486,6 @@ class TabManager : public LifecycleUnitObserver, ...@@ -486,10 +486,6 @@ class TabManager : public LifecycleUnitObserver,
// session restore. // session restore.
std::unique_ptr<TabManagerStatsCollector> stats_collector_; std::unique_ptr<TabManagerStatsCollector> stats_collector_;
// Tracks tab loads, taking into account PageAlmostIdle, NavigationThrottles
// and other complications.
TabLoadTracker tab_load_tracker_;
// Weak pointer factory used for posting delayed tasks. // Weak pointer factory used for posting delayed tasks.
base::WeakPtrFactory<TabManager> weak_ptr_factory_; base::WeakPtrFactory<TabManager> weak_ptr_factory_;
......
...@@ -12,21 +12,13 @@ ...@@ -12,21 +12,13 @@
namespace resource_coordinator { namespace resource_coordinator {
namespace {
TabLoadTracker& GetTabLoadTracker() {
return g_browser_process->GetTabManager()->tab_load_tracker();
}
} // namespace
// A helper class for accessing TabLoadTracker. TabLoadTracker can't directly // A helper class for accessing TabLoadTracker. TabLoadTracker can't directly
// friend TabManager::ResourceCoordinatorSignalObserver as it's a nested class // friend TabManager::ResourceCoordinatorSignalObserver as it's a nested class
// and can't be forward declared. // and can't be forward declared.
class TabManagerResourceCoordinatorSignalObserverHelper { class TabManagerResourceCoordinatorSignalObserverHelper {
public: public:
static void OnPageAlmostIdle(content::WebContents* web_contents) { static void OnPageAlmostIdle(content::WebContents* web_contents) {
GetTabLoadTracker().OnPageAlmostIdle(web_contents); TabLoadTracker::Get()->OnPageAlmostIdle(web_contents);
} }
}; };
...@@ -46,11 +38,6 @@ void TabManager::ResourceCoordinatorSignalObserver::OnPageAlmostIdle( ...@@ -46,11 +38,6 @@ void TabManager::ResourceCoordinatorSignalObserver::OnPageAlmostIdle(
content::WebContents* web_contents) { content::WebContents* web_contents) {
TabManagerResourceCoordinatorSignalObserverHelper::OnPageAlmostIdle( TabManagerResourceCoordinatorSignalObserverHelper::OnPageAlmostIdle(
web_contents); web_contents);
auto* web_contents_data =
TabManager::WebContentsData::FromWebContents(web_contents);
if (!web_contents_data)
return;
web_contents_data->NotifyTabIsLoaded();
} }
void TabManager::ResourceCoordinatorSignalObserver:: void TabManager::ResourceCoordinatorSignalObserver::
......
...@@ -170,19 +170,19 @@ void TabManagerStatsCollector::RecordSwitchToTab( ...@@ -170,19 +170,19 @@ void TabManagerStatsCollector::RecordSwitchToTab(
if (is_session_restore_loading_tabs_) { if (is_session_restore_loading_tabs_) {
UMA_HISTOGRAM_ENUMERATION(kHistogramSessionRestoreSwitchToTab, UMA_HISTOGRAM_ENUMERATION(kHistogramSessionRestoreSwitchToTab,
new_data->tab_loading_state(), new_data->tab_loading_state(),
TAB_LOADING_STATE_MAX); TabLoadTracker::LOADING_STATE_MAX);
} }
if (is_in_background_tab_opening_session_) { if (is_in_background_tab_opening_session_) {
UMA_HISTOGRAM_ENUMERATION(kHistogramBackgroundTabOpeningSwitchToTab, UMA_HISTOGRAM_ENUMERATION(kHistogramBackgroundTabOpeningSwitchToTab,
new_data->tab_loading_state(), new_data->tab_loading_state(),
TAB_LOADING_STATE_MAX); TabLoadTracker::LOADING_STATE_MAX);
} }
if (old_contents) if (old_contents)
foreground_contents_switched_to_times_.erase(old_contents); foreground_contents_switched_to_times_.erase(old_contents);
DCHECK( DCHECK(
!base::ContainsKey(foreground_contents_switched_to_times_, new_contents)); !base::ContainsKey(foreground_contents_switched_to_times_, new_contents));
if (new_data->tab_loading_state() != TAB_IS_LOADED) { if (new_data->tab_loading_state() != TabLoadTracker::LOADED) {
foreground_contents_switched_to_times_.insert( foreground_contents_switched_to_times_.insert(
std::make_pair(new_contents, NowTicks())); std::make_pair(new_contents, NowTicks()));
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h" #include "chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h"
#include "chrome/browser/resource_coordinator/tab_load_tracker.h"
#include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h" #include "chrome/browser/resource_coordinator/tab_manager_web_contents_data.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/ukm/test_ukm_recorder.h" #include "components/ukm/test_ukm_recorder.h"
...@@ -30,6 +31,12 @@ using WebContents = content::WebContents; ...@@ -30,6 +31,12 @@ using WebContents = content::WebContents;
namespace resource_coordinator { namespace resource_coordinator {
using LoadingState = TabLoadTracker::LoadingState;
constexpr TabLoadTracker::LoadingState UNLOADED = TabLoadTracker::UNLOADED;
constexpr TabLoadTracker::LoadingState LOADING = TabLoadTracker::LOADING;
constexpr TabLoadTracker::LoadingState LOADED = TabLoadTracker::LOADED;
class TabManagerStatsCollectorTest : public ChromeRenderViewHostTestHarness { class TabManagerStatsCollectorTest : public ChromeRenderViewHostTestHarness {
protected: protected:
TabManagerStatsCollectorTest() = default; TabManagerStatsCollectorTest() = default;
...@@ -120,11 +127,11 @@ class TabManagerStatsCollectorTabSwitchTest ...@@ -120,11 +127,11 @@ class TabManagerStatsCollectorTabSwitchTest
TabManagerStatsCollectorTabSwitchTest() = default; TabManagerStatsCollectorTabSwitchTest() = default;
~TabManagerStatsCollectorTabSwitchTest() override = default; ~TabManagerStatsCollectorTabSwitchTest() override = default;
void SetForegroundTabLoadingState(TabLoadingState state) { void SetForegroundTabLoadingState(LoadingState state) {
GetWebContentsData(foreground_tab_)->SetTabLoadingState(state); GetWebContentsData(foreground_tab_)->SetTabLoadingState(state);
} }
void SetBackgroundTabLoadingState(TabLoadingState state) { void SetBackgroundTabLoadingState(LoadingState state) {
GetWebContentsData(background_tab_)->SetTabLoadingState(state); GetWebContentsData(background_tab_)->SetTabLoadingState(state);
} }
...@@ -139,12 +146,12 @@ class TabManagerStatsCollectorTabSwitchTest ...@@ -139,12 +146,12 @@ class TabManagerStatsCollectorTabSwitchTest
} }
void FinishLoadingForegroundTab() { void FinishLoadingForegroundTab() {
SetForegroundTabLoadingState(TAB_IS_LOADED); SetForegroundTabLoadingState(LOADED);
tab_manager_stats_collector()->OnTabIsLoaded(foreground_tab_); tab_manager_stats_collector()->OnTabIsLoaded(foreground_tab_);
} }
void FinishLoadingBackgroundTab() { void FinishLoadingBackgroundTab() {
SetBackgroundTabLoadingState(TAB_IS_LOADED); SetBackgroundTabLoadingState(LOADED);
tab_manager_stats_collector()->OnTabIsLoaded(background_tab_); tab_manager_stats_collector()->OnTabIsLoaded(background_tab_);
} }
...@@ -184,39 +191,36 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsSwitchToTab) { ...@@ -184,39 +191,36 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsSwitchToTab) {
if (should_test_background_tab_opening_) if (should_test_background_tab_opening_)
StartBackgroundTabOpeningSession(); StartBackgroundTabOpeningSession();
SetBackgroundTabLoadingState(TAB_IS_NOT_LOADING); SetBackgroundTabLoadingState(UNLOADED);
SetForegroundTabLoadingState(TAB_IS_NOT_LOADING); SetForegroundTabLoadingState(UNLOADED);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
SwitchToBackgroundTab(); SwitchToBackgroundTab();
for (const auto& param : histogram_parameters) { for (const auto& param : histogram_parameters) {
if (param.enabled && !IsTestingOverlappedSession()) { if (param.enabled && !IsTestingOverlappedSession()) {
histogram_tester_.ExpectTotalCount(param.histogram_name, 2); histogram_tester_.ExpectTotalCount(param.histogram_name, 2);
histogram_tester_.ExpectBucketCount(param.histogram_name, histogram_tester_.ExpectBucketCount(param.histogram_name, UNLOADED, 2);
TAB_IS_NOT_LOADING, 2);
} else { } else {
histogram_tester_.ExpectTotalCount(param.histogram_name, 0); histogram_tester_.ExpectTotalCount(param.histogram_name, 0);
} }
} }
SetBackgroundTabLoadingState(TAB_IS_LOADING); SetBackgroundTabLoadingState(LOADING);
SetForegroundTabLoadingState(TAB_IS_LOADING); SetForegroundTabLoadingState(LOADING);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
SwitchToBackgroundTab(); SwitchToBackgroundTab();
SwitchToBackgroundTab(); SwitchToBackgroundTab();
for (const auto& param : histogram_parameters) { for (const auto& param : histogram_parameters) {
if (param.enabled && !IsTestingOverlappedSession()) { if (param.enabled && !IsTestingOverlappedSession()) {
histogram_tester_.ExpectTotalCount(param.histogram_name, 5); histogram_tester_.ExpectTotalCount(param.histogram_name, 5);
histogram_tester_.ExpectBucketCount(param.histogram_name, histogram_tester_.ExpectBucketCount(param.histogram_name, UNLOADED, 2);
TAB_IS_NOT_LOADING, 2); histogram_tester_.ExpectBucketCount(param.histogram_name, LOADING, 3);
histogram_tester_.ExpectBucketCount(param.histogram_name, TAB_IS_LOADING,
3);
} else { } else {
histogram_tester_.ExpectTotalCount(param.histogram_name, 0); histogram_tester_.ExpectTotalCount(param.histogram_name, 0);
} }
} }
SetBackgroundTabLoadingState(TAB_IS_LOADED); SetBackgroundTabLoadingState(LOADED);
SetForegroundTabLoadingState(TAB_IS_LOADED); SetForegroundTabLoadingState(LOADED);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
SwitchToBackgroundTab(); SwitchToBackgroundTab();
SwitchToBackgroundTab(); SwitchToBackgroundTab();
...@@ -224,12 +228,9 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsSwitchToTab) { ...@@ -224,12 +228,9 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsSwitchToTab) {
for (const auto& param : histogram_parameters) { for (const auto& param : histogram_parameters) {
if (param.enabled && !IsTestingOverlappedSession()) { if (param.enabled && !IsTestingOverlappedSession()) {
histogram_tester_.ExpectTotalCount(param.histogram_name, 9); histogram_tester_.ExpectTotalCount(param.histogram_name, 9);
histogram_tester_.ExpectBucketCount(param.histogram_name, histogram_tester_.ExpectBucketCount(param.histogram_name, UNLOADED, 2);
TAB_IS_NOT_LOADING, 2); histogram_tester_.ExpectBucketCount(param.histogram_name, LOADING, 3);
histogram_tester_.ExpectBucketCount(param.histogram_name, TAB_IS_LOADING, histogram_tester_.ExpectBucketCount(param.histogram_name, LOADED, 4);
3);
histogram_tester_.ExpectBucketCount(param.histogram_name, TAB_IS_LOADED,
4);
} else { } else {
histogram_tester_.ExpectTotalCount(param.histogram_name, 0); histogram_tester_.ExpectTotalCount(param.histogram_name, 0);
} }
...@@ -246,8 +247,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) { ...@@ -246,8 +247,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) {
if (should_test_background_tab_opening_) if (should_test_background_tab_opening_)
StartBackgroundTabOpeningSession(); StartBackgroundTabOpeningSession();
SetBackgroundTabLoadingState(TAB_IS_NOT_LOADING); SetBackgroundTabLoadingState(UNLOADED);
SetForegroundTabLoadingState(TAB_IS_LOADED); SetForegroundTabLoadingState(LOADED);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
FinishLoadingForegroundTab(); FinishLoadingForegroundTab();
histogram_tester_.ExpectTotalCount( histogram_tester_.ExpectTotalCount(
...@@ -258,7 +259,7 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) { ...@@ -258,7 +259,7 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) {
should_test_background_tab_opening_ && !IsTestingOverlappedSession() ? 1 should_test_background_tab_opening_ && !IsTestingOverlappedSession() ? 1
: 0); : 0);
SetBackgroundTabLoadingState(TAB_IS_LOADING); SetBackgroundTabLoadingState(LOADING);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
FinishLoadingForegroundTab(); FinishLoadingForegroundTab();
histogram_tester_.ExpectTotalCount( histogram_tester_.ExpectTotalCount(
...@@ -271,8 +272,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) { ...@@ -271,8 +272,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) {
// Metrics aren't recorded when the foreground tab has not finished loading // Metrics aren't recorded when the foreground tab has not finished loading
// and the user switches to a different tab. // and the user switches to a different tab.
SetBackgroundTabLoadingState(TAB_IS_LOADING); SetBackgroundTabLoadingState(UNLOADED);
SetForegroundTabLoadingState(TAB_IS_LOADED); SetForegroundTabLoadingState(LOADED);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
// Foreground tab is currently loading and being tracked. // Foreground tab is currently loading and being tracked.
SwitchToBackgroundTab(); SwitchToBackgroundTab();
...@@ -294,8 +295,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) { ...@@ -294,8 +295,8 @@ TEST_P(TabManagerStatsCollectorTabSwitchTest, HistogramsTabSwitchLoadTime) {
if (should_test_background_tab_opening_) if (should_test_background_tab_opening_)
FinishBackgroundTabOpeningSession(); FinishBackgroundTabOpeningSession();
SetBackgroundTabLoadingState(TAB_IS_NOT_LOADING); SetBackgroundTabLoadingState(UNLOADED);
SetForegroundTabLoadingState(TAB_IS_LOADED); SetForegroundTabLoadingState(LOADED);
SwitchToBackgroundTab(); SwitchToBackgroundTab();
FinishLoadingForegroundTab(); FinishLoadingForegroundTab();
histogram_tester_.ExpectTotalCount( histogram_tester_.ExpectTotalCount(
......
...@@ -29,12 +29,6 @@ TabManager::WebContentsData::WebContentsData(content::WebContents* web_contents) ...@@ -29,12 +29,6 @@ TabManager::WebContentsData::WebContentsData(content::WebContents* web_contents)
TabManager::WebContentsData::~WebContentsData() {} TabManager::WebContentsData::~WebContentsData() {}
void TabManager::WebContentsData::DidStopLoading() {
if (IsPageAlmostIdleSignalEnabled())
return;
NotifyTabIsLoaded();
}
void TabManager::WebContentsData::DidStartNavigation( void TabManager::WebContentsData::DidStartNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
// Only change to the loading state if there is a navigation in the main // Only change to the loading state if there is a navigation in the main
...@@ -45,7 +39,6 @@ void TabManager::WebContentsData::DidStartNavigation( ...@@ -45,7 +39,6 @@ void TabManager::WebContentsData::DidStartNavigation(
return; return;
} }
SetTabLoadingState(TAB_IS_LOADING);
g_browser_process->GetTabManager() g_browser_process->GetTabManager()
->stats_collector() ->stats_collector()
->OnDidStartMainFrameNavigation(web_contents()); ->OnDidStartMainFrameNavigation(web_contents());
...@@ -61,21 +54,10 @@ void TabManager::WebContentsData::WebContentsDestroyed() { ...@@ -61,21 +54,10 @@ void TabManager::WebContentsData::WebContentsDestroyed() {
// If Chrome is shutting down, ignore this event. // If Chrome is shutting down, ignore this event.
if (g_browser_process->IsShuttingDown()) if (g_browser_process->IsShuttingDown())
return; return;
SetTabLoadingState(TAB_IS_NOT_LOADING);
SetIsInSessionRestore(false); SetIsInSessionRestore(false);
g_browser_process->GetTabManager()->OnWebContentsDestroyed(web_contents()); g_browser_process->GetTabManager()->OnWebContentsDestroyed(web_contents());
} }
void TabManager::WebContentsData::NotifyTabIsLoaded() {
// We may already be in the stopped state if this is being invoked due to an
// iframe loading new content.
if (tab_data_.tab_loading_state != TAB_IS_LOADED) {
SetTabLoadingState(TAB_IS_LOADED);
g_browser_process->GetTabManager()->OnTabIsLoaded(web_contents());
}
}
TimeTicks TabManager::WebContentsData::LastInactiveTime() { TimeTicks TabManager::WebContentsData::LastInactiveTime() {
return tab_data_.last_inactive_time; return tab_data_.last_inactive_time;
} }
...@@ -97,7 +79,7 @@ void TabManager::WebContentsData::CopyState( ...@@ -97,7 +79,7 @@ void TabManager::WebContentsData::CopyState(
} }
TabManager::WebContentsData::Data::Data() TabManager::WebContentsData::Data::Data()
: tab_loading_state(TAB_IS_NOT_LOADING), : tab_loading_state(TabLoadTracker::UNLOADED),
is_in_session_restore(false), is_in_session_restore(false),
is_restored_in_foreground(false) {} is_restored_in_foreground(false) {}
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/resource_coordinator/tab_load_tracker.h"
#include "chrome/browser/resource_coordinator/tab_manager.h" #include "chrome/browser/resource_coordinator/tab_manager.h"
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
...@@ -18,27 +19,6 @@ class WebContents; ...@@ -18,27 +19,6 @@ class WebContents;
namespace resource_coordinator { namespace resource_coordinator {
// Tabs (WebContentsData) start in the not loading state, and transition to the
// loading state when a navigation begins in the main frame of the associated
// WebContents. The state changes to loaded when we receive the DidStopLoading*
// signal. The state can change from loaded to loading if another navigation
// occurs in the main frame, which happens if the user navigates to a new page
// and the WebContents is reused.
//
// These values are used in the TabManager.SessionRestore.SwitchToTab UMA.
//
// These values are written to logs. New enum values can be added, but existing
// enums must never be renumbered or deleted and reused.
enum TabLoadingState {
TAB_IS_NOT_LOADING = 0,
TAB_IS_LOADING = 1,
// A tab is considered loaded when DidStopLoading is called from WebContents
// for now. We are in the progress to deprecate using it, and use
// PageAlmostIdle signal from resource coordinator instead.
TAB_IS_LOADED = 2,
TAB_LOADING_STATE_MAX,
};
// Internal class used by TabManager to record the needed data for // Internal class used by TabManager to record the needed data for
// WebContentses. // WebContentses.
// TODO(michaelpg): Merge implementation into // TODO(michaelpg): Merge implementation into
...@@ -47,21 +27,18 @@ class TabManager::WebContentsData ...@@ -47,21 +27,18 @@ class TabManager::WebContentsData
: public content::WebContentsObserver, : public content::WebContentsObserver,
public content::WebContentsUserData<TabManager::WebContentsData> { public content::WebContentsUserData<TabManager::WebContentsData> {
public: public:
using LoadingState = resource_coordinator::TabLoadTracker::LoadingState;
explicit WebContentsData(content::WebContents* web_contents); explicit WebContentsData(content::WebContents* web_contents);
~WebContentsData() override; ~WebContentsData() override;
// WebContentsObserver implementation: // WebContentsObserver implementation:
void DidStopLoading() override;
void DidStartNavigation( void DidStartNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
void WebContentsDestroyed() override; void WebContentsDestroyed() override;
// Called by TabManager::ResourceCoordinatorSignalObserver to notify that a
// tab is considered loaded.
void NotifyTabIsLoaded();
// Returns the timestamp of the last time the tab changed became inactive. // Returns the timestamp of the last time the tab changed became inactive.
base::TimeTicks LastInactiveTime(); base::TimeTicks LastInactiveTime();
...@@ -91,14 +68,12 @@ class TabManager::WebContentsData ...@@ -91,14 +68,12 @@ class TabManager::WebContentsData
base::TimeDelta time_to_purge() const { return time_to_purge_; } base::TimeDelta time_to_purge() const { return time_to_purge_; }
// Sets the tab loading state. // Sets the tab loading state.
void SetTabLoadingState(TabLoadingState state) { void SetTabLoadingState(LoadingState state) {
tab_data_.tab_loading_state = state; tab_data_.tab_loading_state = state;
} }
// Returns the TabLoadingState of the tab. // Returns the loading state of the tab.
TabLoadingState tab_loading_state() const { LoadingState tab_loading_state() const { return tab_data_.tab_loading_state; }
return tab_data_.tab_loading_state;
}
void SetIsInSessionRestore(bool is_in_session_restore) { void SetIsInSessionRestore(bool is_in_session_restore) {
tab_data_.is_in_session_restore = is_in_session_restore; tab_data_.is_in_session_restore = is_in_session_restore;
...@@ -127,7 +102,7 @@ class TabManager::WebContentsData ...@@ -127,7 +102,7 @@ class TabManager::WebContentsData
// The last time the tab switched from being active to inactive. // The last time the tab switched from being active to inactive.
base::TimeTicks last_inactive_time; base::TimeTicks last_inactive_time;
// Current loading state of this tab. // Current loading state of this tab.
TabLoadingState tab_loading_state; LoadingState tab_loading_state;
// True if the tab was created by session restore. Remains true until the // True if the tab was created by session restore. Remains true until the
// end of the first navigation or the tab is closed. // end of the first navigation or the tab is closed.
bool is_in_session_restore; bool is_in_session_restore;
......
...@@ -20,6 +20,10 @@ using content::WebContentsTester; ...@@ -20,6 +20,10 @@ using content::WebContentsTester;
namespace resource_coordinator { namespace resource_coordinator {
namespace { namespace {
constexpr TabLoadTracker::LoadingState UNLOADED = TabLoadTracker::UNLOADED;
constexpr TabLoadTracker::LoadingState LOADING = TabLoadTracker::LOADING;
constexpr TabLoadTracker::LoadingState LOADED = TabLoadTracker::LOADED;
class TabManagerWebContentsDataTest : public ChromeRenderViewHostTestHarness { class TabManagerWebContentsDataTest : public ChromeRenderViewHostTestHarness {
public: public:
TabManagerWebContentsDataTest() TabManagerWebContentsDataTest()
...@@ -70,17 +74,17 @@ TEST_F(TabManagerWebContentsDataTest, LastInactiveTime) { ...@@ -70,17 +74,17 @@ TEST_F(TabManagerWebContentsDataTest, LastInactiveTime) {
} }
TEST_F(TabManagerWebContentsDataTest, TabLoadingState) { TEST_F(TabManagerWebContentsDataTest, TabLoadingState) {
EXPECT_EQ(TAB_IS_NOT_LOADING, tab_data()->tab_loading_state()); EXPECT_EQ(UNLOADED, tab_data()->tab_loading_state());
tab_data()->SetTabLoadingState(TAB_IS_LOADING); tab_data()->SetTabLoadingState(LOADING);
EXPECT_EQ(TAB_IS_LOADING, tab_data()->tab_loading_state()); EXPECT_EQ(LOADING, tab_data()->tab_loading_state());
tab_data()->SetTabLoadingState(TAB_IS_LOADED); tab_data()->SetTabLoadingState(LOADED);
EXPECT_EQ(TAB_IS_LOADED, tab_data()->tab_loading_state()); EXPECT_EQ(LOADED, tab_data()->tab_loading_state());
} }
TEST_F(TabManagerWebContentsDataTest, CopyState) { TEST_F(TabManagerWebContentsDataTest, CopyState) {
tab_data()->SetLastInactiveTime(base::TimeTicks() + tab_data()->SetLastInactiveTime(base::TimeTicks() +
base::TimeDelta::FromSeconds(42)); base::TimeDelta::FromSeconds(42));
tab_data()->SetTabLoadingState(TAB_IS_LOADED); tab_data()->SetTabLoadingState(LOADED);
tab_data()->SetIsInSessionRestore(true); tab_data()->SetIsInSessionRestore(true);
tab_data()->SetIsRestoredInForeground(true); tab_data()->SetIsRestoredInForeground(true);
......
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