Commit e509ad4e authored by Ryan Sturm's avatar Ryan Sturm Committed by Commit Bot

Limit idle users' speculative connections

When a user is idle (i.e., has not navigated or foreground/background
the tab for 5 minutes), we should stop attempting to preconnect to the
foreground tab.

Bug: 1055256
Change-Id: I76324c36508f0ee8720058db6f02235df482c693
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2076217Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Commit-Queue: Ryan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745616}
parent 9326d319
...@@ -66,14 +66,14 @@ void NavigationPredictorPreconnectClient::DidFinishNavigation( ...@@ -66,14 +66,14 @@ void NavigationPredictorPreconnectClient::DidFinishNavigation(
int delay_ms = base::GetFieldTrialParamByFeatureAsInt( int delay_ms = base::GetFieldTrialParamByFeatureAsInt(
kPreconnectOnDidFinishNavigation, "delay_after_commit_in_ms", 3000); kPreconnectOnDidFinishNavigation, "delay_after_commit_in_ms", 3000);
if (delay_ms <= 0) { if (delay_ms <= 0) {
MaybePreconnectNow(); MaybePreconnectNow(/*preconnects_attempted=*/0u);
return; return;
} }
timer_.Start( timer_.Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
base::BindOnce(&NavigationPredictorPreconnectClient::MaybePreconnectNow, base::BindOnce(&NavigationPredictorPreconnectClient::MaybePreconnectNow,
base::Unretained(this))); base::Unretained(this), /*preconnects_attempted=*/0u));
} }
} }
...@@ -99,7 +99,7 @@ void NavigationPredictorPreconnectClient::OnVisibilityChanged( ...@@ -99,7 +99,7 @@ void NavigationPredictorPreconnectClient::OnVisibilityChanged(
// Previously, the visibility was HIDDEN, and now it is VISIBLE implying that // Previously, the visibility was HIDDEN, and now it is VISIBLE implying that
// the web contents that was fully hidden is now fully visible. // the web contents that was fully hidden is now fully visible.
MaybePreconnectNow(); MaybePreconnectNow(/*preconnects_attempted=*/0u);
} }
void NavigationPredictorPreconnectClient::DidFinishLoad( void NavigationPredictorPreconnectClient::DidFinishLoad(
...@@ -109,10 +109,11 @@ void NavigationPredictorPreconnectClient::DidFinishLoad( ...@@ -109,10 +109,11 @@ void NavigationPredictorPreconnectClient::DidFinishLoad(
if (render_frame_host->GetParent()) if (render_frame_host->GetParent())
return; return;
MaybePreconnectNow(); MaybePreconnectNow(/*preconnects_attempted=*/0u);
} }
void NavigationPredictorPreconnectClient::MaybePreconnectNow() { void NavigationPredictorPreconnectClient::MaybePreconnectNow(
size_t preconnects_attempted) {
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
features::kNavigationPredictorPreconnectHoldback)) features::kNavigationPredictorPreconnectHoldback))
return; return;
...@@ -124,10 +125,14 @@ void NavigationPredictorPreconnectClient::MaybePreconnectNow() { ...@@ -124,10 +125,14 @@ void NavigationPredictorPreconnectClient::MaybePreconnectNow() {
if (current_visibility_ != content::Visibility::VISIBLE) if (current_visibility_ != content::Visibility::VISIBLE)
return; return;
// On search engine results page, next navigation is likely to be a different // Only allow 5 preconnects per foreground/load.
// origin. Currently, the preconnect is only allowed for same origins. Hence, if (preconnects_attempted >= 5u)
// preconnect is currently disabled on search engine results page. return;
// If preconnect to DSE is enabled, skip this check.
// On search engine results page, next navigation is likely to be a
// different origin. Currently, the preconnect is only allowed for same
// origins. Hence, preconnect is currently disabled on search engine results
// page. If preconnect to DSE is enabled, skip this check.
if (!base::FeatureList::IsEnabled(features::kPreconnectToSearch) && if (!base::FeatureList::IsEnabled(features::kPreconnectToSearch) &&
IsSearchEnginePage()) IsSearchEnginePage())
return; return;
...@@ -164,7 +169,7 @@ void NavigationPredictorPreconnectClient::MaybePreconnectNow() { ...@@ -164,7 +169,7 @@ void NavigationPredictorPreconnectClient::MaybePreconnectNow() {
"unused_idle_socket_timeout_seconds", 60)) + "unused_idle_socket_timeout_seconds", 60)) +
base::TimeDelta::FromMilliseconds(retry_delay_ms), base::TimeDelta::FromMilliseconds(retry_delay_ms),
base::BindOnce(&NavigationPredictorPreconnectClient::MaybePreconnectNow, base::BindOnce(&NavigationPredictorPreconnectClient::MaybePreconnectNow,
base::Unretained(this))); base::Unretained(this), preconnects_attempted + 1));
} }
bool NavigationPredictorPreconnectClient::IsSearchEnginePage() const { bool NavigationPredictorPreconnectClient::IsSearchEnginePage() const {
......
...@@ -49,7 +49,7 @@ class NavigationPredictorPreconnectClient ...@@ -49,7 +49,7 @@ class NavigationPredictorPreconnectClient
const GURL& document_url) const; const GURL& document_url) const;
// MaybePreconnectNow preconnects to an origin server if it's allowed. // MaybePreconnectNow preconnects to an origin server if it's allowed.
void MaybePreconnectNow(); void MaybePreconnectNow(size_t preconnects_attempted);
// Used to get keyed services. // Used to get keyed services.
content::BrowserContext* const browser_context_; content::BrowserContext* const browser_context_;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/predictors/loading_predictor_factory.h"
...@@ -184,6 +185,26 @@ IN_PROC_BROWSER_TEST_F( ...@@ -184,6 +185,26 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(4, preresolve_done_count_); EXPECT_EQ(4, preresolve_done_count_);
} }
// Test that we preconnect after the last preconnect timed out.
IN_PROC_BROWSER_TEST_F(
NavigationPredictorPreconnectClientBrowserTestWithUnusedIdleSocketTimeout,
CappedAtFiveAttempts) {
const GURL& url = GetTestURL("/page_with_same_host_anchor_element.html");
ui_test_utils::NavigateToURL(browser(), url);
// Expect 1 navigation preresolve and 5 repeated onLoad calls.
WaitForPreresolveCount(6);
EXPECT_EQ(6, preresolve_done_count_);
// We should not see additional preresolves.
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
EXPECT_EQ(6, preresolve_done_count_);
}
class NavigationPredictorPreconnectClientBrowserTestWithHoldback class NavigationPredictorPreconnectClientBrowserTestWithHoldback
: public NavigationPredictorPreconnectClientBrowserTest { : public NavigationPredictorPreconnectClientBrowserTest {
public: public:
......
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