Commit a1506da7 authored by Zhen Wang's avatar Zhen Wang Committed by Commit Bot

Defer loading internal pages for background tabs

Internal pages are deferred to load after other pages.

Bug: 730098
Change-Id: I3b8f2dbbb1d7e2e4d858750432597e882ef60b9f
Reviewed-on: https://chromium-review.googlesource.com/585241
Commit-Queue: Zhen Wang <zhenw@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490710}
parent c88d595b
...@@ -1118,6 +1118,8 @@ TabManager::MaybeThrottleNavigation(BackgroundTabNavigationThrottle* throttle) { ...@@ -1118,6 +1118,8 @@ TabManager::MaybeThrottleNavigation(BackgroundTabNavigationThrottle* throttle) {
GetWebContentsData(navigation_handle->GetWebContents()) GetWebContentsData(navigation_handle->GetWebContents())
->SetTabLoadingState(TAB_IS_NOT_LOADING); ->SetTabLoadingState(TAB_IS_NOT_LOADING);
pending_navigations_.push_back(throttle); pending_navigations_.push_back(throttle);
std::stable_sort(pending_navigations_.begin(), pending_navigations_.end(),
ComparePendingNavigations);
StartForceLoadTimer(); StartForceLoadTimer();
return content::NavigationThrottle::DEFER; return content::NavigationThrottle::DEFER;
...@@ -1211,6 +1213,21 @@ BackgroundTabNavigationThrottle* TabManager::RemovePendingNavigationIfNeeded( ...@@ -1211,6 +1213,21 @@ BackgroundTabNavigationThrottle* TabManager::RemovePendingNavigationIfNeeded(
return nullptr; return nullptr;
} }
// static
bool TabManager::ComparePendingNavigations(
const BackgroundTabNavigationThrottle* first,
const BackgroundTabNavigationThrottle* second) {
bool first_is_internal_page =
IsInternalPage(first->navigation_handle()->GetURL());
bool second_is_internal_page =
IsInternalPage(second->navigation_handle()->GetURL());
if (first_is_internal_page != second_is_internal_page)
return !first_is_internal_page;
return false;
}
bool TabManager::IsTabLoadingForTest(content::WebContents* contents) const { bool TabManager::IsTabLoadingForTest(content::WebContents* contents) const {
if (loading_contents_.count(contents) == 1) { if (loading_contents_.count(contents) == 1) {
DCHECK_EQ(TAB_IS_LOADING, DCHECK_EQ(TAB_IS_LOADING,
......
...@@ -241,6 +241,7 @@ class TabManager : public TabStripModelObserver, ...@@ -241,6 +241,7 @@ class TabManager : public TabStripModelObserver,
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDelayedTabSelected); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDelayedTabSelected);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TimeoutWhenLoadingBackgroundTabs); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TimeoutWhenLoadingBackgroundTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering);
FRIEND_TEST_ALL_PREFIXES(TabManagerStatsCollectorTest, FRIEND_TEST_ALL_PREFIXES(TabManagerStatsCollectorTest,
HistogramsSessionRestoreSwitchToTab); HistogramsSessionRestoreSwitchToTab);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
...@@ -426,6 +427,11 @@ class TabManager : public TabStripModelObserver, ...@@ -426,6 +427,11 @@ class TabManager : public TabStripModelObserver,
BackgroundTabNavigationThrottle* RemovePendingNavigationIfNeeded( BackgroundTabNavigationThrottle* RemovePendingNavigationIfNeeded(
content::WebContents* contents); content::WebContents* contents);
// Returns true if |first| is considered to resume navigation before |second|.
static bool ComparePendingNavigations(
const BackgroundTabNavigationThrottle* first,
const BackgroundTabNavigationThrottle* second);
// Check if the tab is loading. Use only in tests. // Check if the tab is loading. Use only in tests.
bool IsTabLoadingForTest(content::WebContents* contents) const; bool IsTabLoadingForTest(content::WebContents* contents) const;
......
...@@ -132,22 +132,22 @@ class TabManagerTest : public ChromeRenderViewHostTestHarness { ...@@ -132,22 +132,22 @@ class TabManagerTest : public ChromeRenderViewHostTestHarness {
return web_contents; return web_contents;
} }
std::unique_ptr<NavigationHandle> CreateTabAndNavigation() { std::unique_ptr<NavigationHandle> CreateTabAndNavigation(const char* url) {
content::TestWebContents* web_contents = content::TestWebContents* web_contents =
content::TestWebContents::Create(profile(), nullptr); content::TestWebContents::Create(profile(), nullptr);
return content::NavigationHandle::CreateNavigationHandleForTesting( return content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kTestUrl), web_contents->GetMainFrame()); GURL(url), web_contents->GetMainFrame());
}
void MaybeThrottleNavigations(TabManager* tab_manager) {
MaybeThrottleNavigations(tab_manager, 1);
} }
// Simulate creating 3 tabs and their navigations. // Simulate creating 3 tabs and their navigations.
void MaybeThrottleNavigations(TabManager* tab_manager, size_t loading_slots) { void MaybeThrottleNavigations(TabManager* tab_manager,
nav_handle1_ = CreateTabAndNavigation(); size_t loading_slots = 1,
nav_handle2_ = CreateTabAndNavigation(); const char* url1 = kTestUrl,
nav_handle3_ = CreateTabAndNavigation(); const char* url2 = kTestUrl,
const char* url3 = kTestUrl) {
nav_handle1_ = CreateTabAndNavigation(url1);
nav_handle2_ = CreateTabAndNavigation(url2);
nav_handle3_ = CreateTabAndNavigation(url3);
contents1_ = nav_handle1_->GetWebContents(); contents1_ = nav_handle1_->GetWebContents();
contents2_ = nav_handle2_->GetWebContents(); contents2_ = nav_handle2_->GetWebContents();
contents3_ = nav_handle3_->GetWebContents(); contents3_ = nav_handle3_->GetWebContents();
...@@ -875,4 +875,33 @@ TEST_F(TabManagerTest, BackgroundTabLoadingSlots) { ...@@ -875,4 +875,33 @@ TEST_F(TabManagerTest, BackgroundTabLoadingSlots) {
EXPECT_FALSE(tab_manager3.IsNavigationDelayedForTest(nav_handle3_.get())); EXPECT_FALSE(tab_manager3.IsNavigationDelayedForTest(nav_handle3_.get()));
} }
TEST_F(TabManagerTest, BackgroundTabsLoadingOrdering) {
TabManager* tab_manager = g_browser_process->GetTabManager();
base::SimpleTestTickClock test_clock;
tab_manager->set_test_tick_clock(&test_clock);
MaybeThrottleNavigations(
tab_manager, 1, kTestUrl,
chrome::kChromeUISettingsURL, // Using internal page URL for tab 2.
kTestUrl);
tab_manager->GetWebContentsData(contents1_)
->DidStartNavigation(nav_handle1_.get());
EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents1_));
EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents2_));
EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents3_));
EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle1_.get()));
EXPECT_TRUE(tab_manager->IsNavigationDelayedForTest(nav_handle2_.get()));
EXPECT_TRUE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get()));
// Simulate tab 1 has finished loading. Tab 3 should be loaded before tab 2,
// because tab 2 is internal page.
tab_manager->GetWebContentsData(contents1_)->DidStopLoading();
EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents2_));
EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_));
EXPECT_TRUE(tab_manager->IsNavigationDelayedForTest(nav_handle2_.get()));
EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get()));
}
} // namespace resource_coordinator } // namespace resource_coordinator
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