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) {
GetWebContentsData(navigation_handle->GetWebContents())
->SetTabLoadingState(TAB_IS_NOT_LOADING);
pending_navigations_.push_back(throttle);
std::stable_sort(pending_navigations_.begin(), pending_navigations_.end(),
ComparePendingNavigations);
StartForceLoadTimer();
return content::NavigationThrottle::DEFER;
......@@ -1211,6 +1213,21 @@ BackgroundTabNavigationThrottle* TabManager::RemovePendingNavigationIfNeeded(
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 {
if (loading_contents_.count(contents) == 1) {
DCHECK_EQ(TAB_IS_LOADING,
......
......@@ -241,6 +241,7 @@ class TabManager : public TabStripModelObserver,
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OnDelayedTabSelected);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TimeoutWhenLoadingBackgroundTabs);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering);
FRIEND_TEST_ALL_PREFIXES(TabManagerStatsCollectorTest,
HistogramsSessionRestoreSwitchToTab);
FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
......@@ -426,6 +427,11 @@ class TabManager : public TabStripModelObserver,
BackgroundTabNavigationThrottle* RemovePendingNavigationIfNeeded(
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.
bool IsTabLoadingForTest(content::WebContents* contents) const;
......
......@@ -132,22 +132,22 @@ class TabManagerTest : public ChromeRenderViewHostTestHarness {
return web_contents;
}
std::unique_ptr<NavigationHandle> CreateTabAndNavigation() {
std::unique_ptr<NavigationHandle> CreateTabAndNavigation(const char* url) {
content::TestWebContents* web_contents =
content::TestWebContents::Create(profile(), nullptr);
return content::NavigationHandle::CreateNavigationHandleForTesting(
GURL(kTestUrl), web_contents->GetMainFrame());
}
void MaybeThrottleNavigations(TabManager* tab_manager) {
MaybeThrottleNavigations(tab_manager, 1);
GURL(url), web_contents->GetMainFrame());
}
// Simulate creating 3 tabs and their navigations.
void MaybeThrottleNavigations(TabManager* tab_manager, size_t loading_slots) {
nav_handle1_ = CreateTabAndNavigation();
nav_handle2_ = CreateTabAndNavigation();
nav_handle3_ = CreateTabAndNavigation();
void MaybeThrottleNavigations(TabManager* tab_manager,
size_t loading_slots = 1,
const char* url1 = kTestUrl,
const char* url2 = kTestUrl,
const char* url3 = kTestUrl) {
nav_handle1_ = CreateTabAndNavigation(url1);
nav_handle2_ = CreateTabAndNavigation(url2);
nav_handle3_ = CreateTabAndNavigation(url3);
contents1_ = nav_handle1_->GetWebContents();
contents2_ = nav_handle2_->GetWebContents();
contents3_ = nav_handle3_->GetWebContents();
......@@ -875,4 +875,33 @@ TEST_F(TabManagerTest, BackgroundTabLoadingSlots) {
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
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