Commit dec90199 authored by Robert Ogden's avatar Robert Ogden Committed by Commit Bot

Add TLS Socket Connection as an Origin Prober Mechanism

Creates a TLS socket connection to probe connectivity to the origin.
This probe must also complete a DNS resolution in order to complete
successfully, in order to get the IPAddress of the probe url.

Bug: 1115731
Change-Id: I862ef52d353c4572e45d8596f5809af1b0b60081
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2358490Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Commit-Queue: Robert Ogden <robertogden@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801570}
parent 4fe98ecb
...@@ -307,6 +307,38 @@ std::unique_ptr<net::ClientCertStore> CreateCertStore() { ...@@ -307,6 +307,38 @@ std::unique_ptr<net::ClientCertStore> CreateCertStore() {
new ClientCertStoreStub(std::move(cert_identity_list))); new ClientCertStoreStub(std::move(cert_identity_list)));
} }
class CustomProbeOverrideDelegate
: public IsolatedPrerenderOriginProber::ProbeURLOverrideDelegate {
public:
explicit CustomProbeOverrideDelegate(const GURL& override_url)
: url_(override_url) {}
~CustomProbeOverrideDelegate() = default;
GURL OverrideProbeURL(const GURL& url) override { return url_; }
private:
GURL url_;
};
class TestServerConnectionCounter
: public net::test_server::EmbeddedTestServerConnectionListener {
public:
TestServerConnectionCounter() = default;
~TestServerConnectionCounter() override = default;
size_t count() const { return count_; }
private:
void ReadFromSocket(const net::StreamSocket& connection, int rv) override {}
std::unique_ptr<net::StreamSocket> AcceptedSocket(
std::unique_ptr<net::StreamSocket> socket) override {
count_++;
return socket;
}
size_t count_ = 0;
};
} // namespace } // namespace
// Occasional flakes on Windows (https://crbug.com/1045971). // Occasional flakes on Windows (https://crbug.com/1045971).
...@@ -319,8 +351,7 @@ std::unique_ptr<net::ClientCertStore> CreateCertStore() { ...@@ -319,8 +351,7 @@ std::unique_ptr<net::ClientCertStore> CreateCertStore() {
class IsolatedPrerenderBrowserTest class IsolatedPrerenderBrowserTest
: public InProcessBrowserTest, : public InProcessBrowserTest,
public prerender::PrerenderHandle::Observer, public prerender::PrerenderHandle::Observer,
public net::test_server::EmbeddedTestServerConnectionListener, public net::test_server::EmbeddedTestServerConnectionListener {
public IsolatedPrerenderOriginProber::ProbeURLOverrideDelegate {
public: public:
IsolatedPrerenderBrowserTest() { IsolatedPrerenderBrowserTest() {
origin_server_ = std::make_unique<net::EmbeddedTestServer>( origin_server_ = std::make_unique<net::EmbeddedTestServer>(
...@@ -402,10 +433,6 @@ class IsolatedPrerenderBrowserTest ...@@ -402,10 +433,6 @@ class IsolatedPrerenderBrowserTest
host_resolver()->AddSimulatedFailure("baddnsprobe.a.test"); host_resolver()->AddSimulatedFailure("baddnsprobe.a.test");
} }
GURL OverrideProbeURL(const GURL& url) override {
return GURL("https://baddnsprobe.a.test");
}
void SetUpCommandLine(base::CommandLine* cmd) override { void SetUpCommandLine(base::CommandLine* cmd) override {
InProcessBrowserTest::SetUpCommandLine(cmd); InProcessBrowserTest::SetUpCommandLine(cmd);
// For the proxy. // For the proxy.
...@@ -1914,6 +1941,20 @@ class ProbingEnabled_CanaryOff_DNS_IsolatedPrerenderBrowserTest ...@@ -1914,6 +1941,20 @@ class ProbingEnabled_CanaryOff_DNS_IsolatedPrerenderBrowserTest
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
}; };
class ProbingEnabled_CanaryOff_TLS_IsolatedPrerenderBrowserTest
: public IsolatedPrerenderBrowserTest {
public:
void SetFeatures() override {
IsolatedPrerenderBrowserTest::SetFeatures();
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kIsolatePrerendersMustProbeOrigin,
{{"do_canary", "false"}, {"probe_type", "tls"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
class ProbingEnabled_CanaryOn_CanaryGood_IsolatedPrerenderBrowserTest class ProbingEnabled_CanaryOn_CanaryGood_IsolatedPrerenderBrowserTest
: public IsolatedPrerenderBrowserTest { : public IsolatedPrerenderBrowserTest {
public: public:
...@@ -2179,7 +2220,176 @@ IN_PROC_BROWSER_TEST_F( ...@@ -2179,7 +2220,176 @@ IN_PROC_BROWSER_TEST_F(
IsolatedPrerenderService* service = IsolatedPrerenderService* service =
IsolatedPrerenderServiceFactory::GetForProfile(browser()->profile()); IsolatedPrerenderServiceFactory::GetForProfile(browser()->profile());
service->origin_prober()->SetProbeURLOverrideDelegateOverrideForTesting(this); CustomProbeOverrideDelegate delegate(GURL("https://baddnsprobe.a.test"));
service->origin_prober()->SetProbeURLOverrideDelegateOverrideForTesting(
&delegate);
IsolatedPrerenderTabHelper* tab_helper =
IsolatedPrerenderTabHelper::FromWebContents(GetWebContents());
GURL eligible_link = GetOriginServerURLWithBadProbe("/title2.html");
TestTabHelperObserver tab_helper_observer(tab_helper);
tab_helper_observer.SetExpectedSuccessfulURLs({eligible_link});
base::RunLoop run_loop;
tab_helper_observer.SetOnPrefetchSuccessfulClosure(run_loop.QuitClosure());
GURL doc_url("https://www.google.com/search?q=test");
MakeNavigationPrediction(doc_url, {eligible_link});
// This run loop will quit when all the prefetch responses have been
// successfully done and processed.
run_loop.Run();
// Navigate to the prefetched page, this also triggers UKM recording.
size_t starting_origin_request_count = OriginServerRequestCount();
ui_test_utils::NavigateToURL(browser(), eligible_link);
// The request for the page should have hit the origin server, since the
// prefetched page couldn't be used.
EXPECT_EQ(starting_origin_request_count + 1, OriginServerRequestCount());
EXPECT_EQ(base::UTF8ToUTF16("Title Of Awesomeness"),
GetWebContents()->GetTitle());
ASSERT_TRUE(tab_helper->after_srp_metrics());
ASSERT_TRUE(tab_helper->after_srp_metrics()->prefetch_status_.has_value());
// 2 is the value of "prefetch used, probe failed". The test does not
// reference the enum directly to ensure that casting the enum to an int went
// cleanly, and to provide an extra review point if the value should ever
// accidentally change in the future, which it never should.
EXPECT_EQ(2, static_cast<int>(
tab_helper->after_srp_metrics()->prefetch_status_.value()));
base::Optional<base::TimeDelta> probe_latency =
tab_helper->after_srp_metrics()->probe_latency_;
ASSERT_TRUE(probe_latency.has_value());
EXPECT_GT(probe_latency.value(), base::TimeDelta());
// Navigate again to trigger UKM recording.
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
base::RunLoop().RunUntilIdle();
// 2 = |PrefetchStatus::kPrefetchNotUsedProbeFailed|.
EXPECT_EQ(base::Optional<int64_t>(2),
GetUKMMetric(eligible_link,
ukm::builders::PrefetchProxy_AfterSRPClick::kEntryName,
ukm::builders::PrefetchProxy_AfterSRPClick::
kSRPClickPrefetchStatusName));
// The actual probe latency is hard to deterministically test for. Just make
// sure it is set within reasonable bounds.
base::Optional<int64_t> probe_latency_ms = GetUKMMetric(
eligible_link, ukm::builders::PrefetchProxy_AfterSRPClick::kEntryName,
ukm::builders::PrefetchProxy_AfterSRPClick::kProbeLatencyMsName);
EXPECT_NE(base::nullopt, probe_latency_ms);
}
IN_PROC_BROWSER_TEST_F(
ProbingEnabled_CanaryOff_TLS_IsolatedPrerenderBrowserTest,
DISABLE_ON_WIN_MAC_CHROMEOS(ProbeGood)) {
SetDataSaverEnabled(true);
GURL starting_page = GetOriginServerURL("/simple.html");
ui_test_utils::NavigateToURL(browser(), starting_page);
WaitForUpdatedCustomProxyConfig();
// Setup a local probing server so we can watch its accepted socket count.
TestServerConnectionCounter probe_counter;
net::EmbeddedTestServer probing_server(net::EmbeddedTestServer::TYPE_HTTPS);
probing_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
probing_server.SetConnectionListener(&probe_counter);
ASSERT_TRUE(probing_server.Start());
// Override the probing URL to always hit this server.
IsolatedPrerenderService* service =
IsolatedPrerenderServiceFactory::GetForProfile(browser()->profile());
CustomProbeOverrideDelegate delegate(probing_server.GetURL("a.test", "/"));
service->origin_prober()->SetProbeURLOverrideDelegateOverrideForTesting(
&delegate);
IsolatedPrerenderTabHelper* tab_helper =
IsolatedPrerenderTabHelper::FromWebContents(GetWebContents());
GURL eligible_link = GetOriginServerURL("/title2.html");
TestTabHelperObserver tab_helper_observer(tab_helper);
tab_helper_observer.SetExpectedSuccessfulURLs({eligible_link});
base::RunLoop run_loop;
tab_helper_observer.SetOnPrefetchSuccessfulClosure(run_loop.QuitClosure());
GURL doc_url("https://www.google.com/search?q=test");
MakeNavigationPrediction(doc_url, {eligible_link});
// This run loop will quit when all the prefetch responses have been
// successfully done and processed.
run_loop.Run();
size_t starting_origin_request_count = OriginServerRequestCount();
ASSERT_EQ(0U, probe_counter.count());
ui_test_utils::NavigateToURL(browser(), eligible_link);
EXPECT_EQ(1U, probe_counter.count());
// No full requests should have hit the server.
EXPECT_EQ(starting_origin_request_count, OriginServerRequestCount());
EXPECT_EQ(base::UTF8ToUTF16("Title Of Awesomeness"),
GetWebContents()->GetTitle());
ASSERT_TRUE(tab_helper->after_srp_metrics());
ASSERT_TRUE(tab_helper->after_srp_metrics()->prefetch_status_.has_value());
// 1 is the value of "prefetch used, probe success". The test does not
// reference the enum directly to ensure that casting the enum to an int went
// cleanly, and to provide an extra review point if the value should ever
// accidentally change in the future, which it never should.
EXPECT_EQ(1, static_cast<int>(
tab_helper->after_srp_metrics()->prefetch_status_.value()));
base::Optional<base::TimeDelta> probe_latency =
tab_helper->after_srp_metrics()->probe_latency_;
ASSERT_TRUE(probe_latency.has_value());
EXPECT_GT(probe_latency.value(), base::TimeDelta());
// Navigate again to trigger UKM recording.
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
base::RunLoop().RunUntilIdle();
// 1 = |PrefetchStatus::kPrefetchUsedProbeSuccess|.
EXPECT_EQ(base::Optional<int64_t>(1),
GetUKMMetric(eligible_link,
ukm::builders::PrefetchProxy_AfterSRPClick::kEntryName,
ukm::builders::PrefetchProxy_AfterSRPClick::
kSRPClickPrefetchStatusName));
// The actual probe latency is hard to deterministically test for. Just make
// sure it is set within reasonable bounds.
base::Optional<int64_t> probe_latency_ms = GetUKMMetric(
eligible_link, ukm::builders::PrefetchProxy_AfterSRPClick::kEntryName,
ukm::builders::PrefetchProxy_AfterSRPClick::kProbeLatencyMsName);
EXPECT_NE(base::nullopt, probe_latency_ms);
}
IN_PROC_BROWSER_TEST_F(
ProbingEnabled_CanaryOff_TLS_IsolatedPrerenderBrowserTest,
DISABLE_ON_WIN_MAC_CHROMEOS(ProbeBad)) {
SetDataSaverEnabled(true);
GURL starting_page = GetOriginServerURL("/simple.html");
ui_test_utils::NavigateToURL(browser(), starting_page);
WaitForUpdatedCustomProxyConfig();
// Setup a local probing server so we can watch its accepted socket count.
TestServerConnectionCounter probe_counter;
net::EmbeddedTestServer probing_server(net::EmbeddedTestServer::TYPE_HTTPS);
probing_server.SetSSLConfig(net::EmbeddedTestServer::CERT_BAD_VALIDITY);
probing_server.SetConnectionListener(&probe_counter);
ASSERT_TRUE(probing_server.Start());
// Override the probing URL to always hit this server.
IsolatedPrerenderService* service =
IsolatedPrerenderServiceFactory::GetForProfile(browser()->profile());
CustomProbeOverrideDelegate delegate(probing_server.GetURL("a.test", "/"));
service->origin_prober()->SetProbeURLOverrideDelegateOverrideForTesting(
&delegate);
IsolatedPrerenderTabHelper* tab_helper = IsolatedPrerenderTabHelper* tab_helper =
IsolatedPrerenderTabHelper::FromWebContents(GetWebContents()); IsolatedPrerenderTabHelper::FromWebContents(GetWebContents());
...@@ -2201,8 +2411,11 @@ IN_PROC_BROWSER_TEST_F( ...@@ -2201,8 +2411,11 @@ IN_PROC_BROWSER_TEST_F(
// Navigate to the prefetched page, this also triggers UKM recording. // Navigate to the prefetched page, this also triggers UKM recording.
size_t starting_origin_request_count = OriginServerRequestCount(); size_t starting_origin_request_count = OriginServerRequestCount();
ASSERT_EQ(0U, probe_counter.count());
ui_test_utils::NavigateToURL(browser(), eligible_link); ui_test_utils::NavigateToURL(browser(), eligible_link);
EXPECT_EQ(1U, probe_counter.count());
// The request for the page should have hit the origin server, since the // The request for the page should have hit the origin server, since the
// prefetched page couldn't be used. // prefetched page couldn't be used.
EXPECT_EQ(starting_origin_request_count + 1, OriginServerRequestCount()); EXPECT_EQ(starting_origin_request_count + 1, OriginServerRequestCount());
......
...@@ -14,16 +14,47 @@ ...@@ -14,16 +14,47 @@
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/host_port_pair.h" #include "net/base/host_port_pair.h"
#include "net/base/isolation_info.h" #include "net/base/isolation_info.h"
#include "net/base/network_isolation_key.h" #include "net/base/network_isolation_key.h"
#include "services/network/public/mojom/host_resolver.mojom.h" #include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/tls_socket.mojom.h"
#include "url/origin.h" #include "url/origin.h"
namespace { namespace {
net::NetworkTrafficAnnotationTag GetProbingTrafficAnnotation() {
return net::DefineNetworkTrafficAnnotation("isolated_prerender_probe", R"(
semantics {
sender: "Isolated Prerender Probe Loader"
description:
"Verifies the end to end connection between Chrome and the "
"origin site that the user is currently navigating to. This is "
"done during a navigation that was previously prerendered over a "
"proxy to check that the site is not blocked by middleboxes. "
"Such prerenders will be used to prefetch render-blocking "
"content before being navigated by the user without impacting "
"privacy."
trigger:
"Used for sites off of Google SRPs (Search Result Pages) only "
"for Lite mode users when the experimental feature flag is "
"enabled."
data: "None."
destination: WEBSITE
}
policy {
cookies_allowed: NO
setting:
"Users can control Lite mode on Android via the settings menu. "
"Lite mode is not available on iOS, and on desktop only for "
"developer testing."
policy_exception_justification: "Not implemented."
})");
}
class DNSProber : public network::mojom::ResolveHostClient { class DNSProber : public network::mojom::ResolveHostClient {
public: public:
using OnDNSResultsCallback = base::OnceCallback< using OnDNSResultsCallback = base::OnceCallback<
...@@ -57,6 +88,90 @@ class DNSProber : public network::mojom::ResolveHostClient { ...@@ -57,6 +88,90 @@ class DNSProber : public network::mojom::ResolveHostClient {
OnDNSResultsCallback callback_; OnDNSResultsCallback callback_;
}; };
void TLSDropHandler(base::OnceClosure ui_only_callback) {
content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
std::move(ui_only_callback));
}
class TLSProber {
public:
TLSProber(const GURL& url,
IsolatedPrerenderOriginProber::OnProbeResultCallback callback)
: url_(url), callback_(std::move(callback)) {}
~TLSProber() { DCHECK(!callback_); }
network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
GetOnTCPConnectedCallback() {
network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
tcp_handler = base::BindOnce(&TLSProber::OnTCPConnected,
weak_factory_.GetWeakPtr());
return mojo::WrapCallbackWithDropHandler(std::move(tcp_handler),
GetDropHandler());
}
mojo::PendingReceiver<network::mojom::TCPConnectedSocket>
GetTCPSocketReceiver() {
return tcp_socket_.BindNewPipeAndPassReceiver();
}
private:
void OnTCPConnected(int result,
const base::Optional<net::IPEndPoint>& local_addr,
const base::Optional<net::IPEndPoint>& peer_addr,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
if (result != net::OK) {
HandleFailure();
return;
}
network::mojom::TCPConnectedSocket::UpgradeToTLSCallback tls_handler =
base::BindOnce(&TLSProber::OnUpgradeToTLS, weak_factory_.GetWeakPtr());
tcp_socket_->UpgradeToTLS(
net::HostPortPair::FromURL(url_), /*options=*/nullptr,
net::MutableNetworkTrafficAnnotationTag(GetProbingTrafficAnnotation()),
tls_socket_.BindNewPipeAndPassReceiver(),
/*observer=*/mojo::NullRemote(),
mojo::WrapCallbackWithDropHandler(std::move(tls_handler),
GetDropHandler()));
}
void OnUpgradeToTLS(int result,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream,
const base::Optional<net::SSLInfo>& ssl_info) {
std::move(callback_).Run(result == net::OK);
delete this;
}
base::OnceClosure GetDropHandler() {
// The drop handler is not guaranteed to be run on the original thread. Use
// the anon method above to fix that.
return base::BindOnce(
&TLSDropHandler,
base::BindOnce(&TLSProber::HandleFailure, weak_factory_.GetWeakPtr()));
}
void HandleFailure() {
std::move(callback_).Run(false);
delete this;
}
// The URL of the resource being probed. Only the host:port is used.
const GURL url_;
// The callback to run when the probe is complete.
IsolatedPrerenderOriginProber::OnProbeResultCallback callback_;
// Mojo sockets. We only test that both can be connected.
mojo::Remote<network::mojom::TCPConnectedSocket> tcp_socket_;
mojo::Remote<network::mojom::TLSClientSocket> tls_socket_;
base::WeakPtrFactory<TLSProber> weak_factory_{this};
};
void HTTPProbeHelper( void HTTPProbeHelper(
std::unique_ptr<AvailabilityProber> prober, std::unique_ptr<AvailabilityProber> prober,
IsolatedPrerenderOriginProber::OnProbeResultCallback callback, IsolatedPrerenderOriginProber::OnProbeResultCallback callback,
...@@ -220,6 +335,9 @@ void IsolatedPrerenderOriginProber::Probe(const GURL& url, ...@@ -220,6 +335,9 @@ void IsolatedPrerenderOriginProber::Probe(const GURL& url,
case IsolatedPrerenderOriginProbeType::kHttpHead: case IsolatedPrerenderOriginProbeType::kHttpHead:
HTTPProbe(probe_url, std::move(callback)); HTTPProbe(probe_url, std::move(callback));
return; return;
case IsolatedPrerenderOriginProbeType::kTls:
TLSProbe(probe_url, std::move(callback));
return;
} }
} }
...@@ -228,6 +346,11 @@ void IsolatedPrerenderOriginProber::DNSProbe(const GURL& url, ...@@ -228,6 +346,11 @@ void IsolatedPrerenderOriginProber::DNSProbe(const GURL& url,
StartDNSResolution(url, std::move(callback), /*also_do_tls_connect=*/false); StartDNSResolution(url, std::move(callback), /*also_do_tls_connect=*/false);
} }
void IsolatedPrerenderOriginProber::TLSProbe(const GURL& url,
OnProbeResultCallback callback) {
StartDNSResolution(url, std::move(callback), /*also_do_tls_connect=*/true);
}
void IsolatedPrerenderOriginProber::StartDNSResolution( void IsolatedPrerenderOriginProber::StartDNSResolution(
const GURL& url, const GURL& url,
OnProbeResultCallback callback, OnProbeResultCallback callback,
...@@ -257,34 +380,6 @@ void IsolatedPrerenderOriginProber::StartDNSResolution( ...@@ -257,34 +380,6 @@ void IsolatedPrerenderOriginProber::StartDNSResolution(
void IsolatedPrerenderOriginProber::HTTPProbe(const GURL& url, void IsolatedPrerenderOriginProber::HTTPProbe(const GURL& url,
OnProbeResultCallback callback) { OnProbeResultCallback callback) {
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("isolated_prerender_probe", R"(
semantics {
sender: "Isolated Prerender Probe Loader"
description:
"Verifies the end to end connection between Chrome and the "
"origin site that the user is currently navigating to. This is "
"done during a navigation that was previously prerendered over a "
"proxy to check that the site is not blocked by middleboxes. "
"Such prerenders will be used to prefetch render-blocking "
"content before being navigated by the user without impacting "
"privacy."
trigger:
"Used for sites off of Google SRPs (Search Result Pages) only "
"for Lite mode users when the experimental feature flag is "
"enabled."
data: "None."
destination: WEBSITE
}
policy {
cookies_allowed: NO
setting:
"Users can control Lite mode on Android via the settings menu. "
"Lite mode is not available on iOS, and on desktop only for "
"developer testing."
policy_exception_justification: "Not implemented."
})");
AvailabilityProber::TimeoutPolicy timeout_policy; AvailabilityProber::TimeoutPolicy timeout_policy;
timeout_policy.base_timeout = IsolatedPrerenderProbeTimeout(); timeout_policy.base_timeout = IsolatedPrerenderProbeTimeout();
AvailabilityProber::RetryPolicy retry_policy; AvailabilityProber::RetryPolicy retry_policy;
...@@ -298,7 +393,7 @@ void IsolatedPrerenderOriginProber::HTTPProbe(const GURL& url, ...@@ -298,7 +393,7 @@ void IsolatedPrerenderOriginProber::HTTPProbe(const GURL& url,
nullptr /* pref_service */, nullptr /* pref_service */,
AvailabilityProber::ClientName::kIsolatedPrerenderOriginCheck, url, AvailabilityProber::ClientName::kIsolatedPrerenderOriginCheck, url,
AvailabilityProber::HttpMethod::kHead, net::HttpRequestHeaders(), AvailabilityProber::HttpMethod::kHead, net::HttpRequestHeaders(),
retry_policy, timeout_policy, traffic_annotation, retry_policy, timeout_policy, GetProbingTrafficAnnotation(),
0 /* max_cache_entries */, 0 /* max_cache_entries */,
base::TimeDelta::FromSeconds(0) /* revalidate_cache_after */); base::TimeDelta::FromSeconds(0) /* revalidate_cache_after */);
AvailabilityProber* prober_ptr = prober.get(); AvailabilityProber* prober_ptr = prober.get();
...@@ -332,6 +427,28 @@ void IsolatedPrerenderOriginProber::OnDNSResolved( ...@@ -332,6 +427,28 @@ void IsolatedPrerenderOriginProber::OnDNSResolved(
return; return;
} }
// TODO(robertogden): Handle also_do_tls_connect. DoTLSProbeAfterDNSResolution(url, std::move(callback), *resolved_addresses);
NOTREACHED(); }
void IsolatedPrerenderOriginProber::DoTLSProbeAfterDNSResolution(
const GURL& url,
OnProbeResultCallback callback,
const net::AddressList& addresses) {
DCHECK(!addresses.empty());
std::unique_ptr<TLSProber> prober =
std::make_unique<TLSProber>(url, std::move(callback));
content::BrowserContext::GetDefaultStoragePartition(profile_)
->GetNetworkContext()
->CreateTCPConnectedSocket(
/*local_addr=*/base::nullopt, addresses,
/*tcp_connected_socket_options=*/nullptr,
net::MutableNetworkTrafficAnnotationTag(
GetProbingTrafficAnnotation()),
prober->GetTCPSocketReceiver(),
/*observer=*/mojo::NullRemote(), prober->GetOnTCPConnectedCallback());
// |prober| manages its own lifetime, using the mojo pipes.
prober.release();
} }
...@@ -48,6 +48,7 @@ class IsolatedPrerenderOriginProber { ...@@ -48,6 +48,7 @@ class IsolatedPrerenderOriginProber {
private: private:
void DNSProbe(const GURL& url, OnProbeResultCallback callback); void DNSProbe(const GURL& url, OnProbeResultCallback callback);
void HTTPProbe(const GURL& url, OnProbeResultCallback callback); void HTTPProbe(const GURL& url, OnProbeResultCallback callback);
void TLSProbe(const GURL& url, OnProbeResultCallback callback);
// Does a DNS resolution for a DNS or TLS probe, passing all the arguments to // Does a DNS resolution for a DNS or TLS probe, passing all the arguments to
// |OnDNSResolved|. // |OnDNSResolved|.
...@@ -55,6 +56,12 @@ class IsolatedPrerenderOriginProber { ...@@ -55,6 +56,12 @@ class IsolatedPrerenderOriginProber {
OnProbeResultCallback callback, OnProbeResultCallback callback,
bool also_do_tls_connect); bool also_do_tls_connect);
// Both DNS and TLS probes need to resolve DNS. This starts the TLS probe with
// the |addresses| from the DNS resolution.
void DoTLSProbeAfterDNSResolution(const GURL& url,
OnProbeResultCallback callback,
const net::AddressList& addresses);
// If the DNS resolution was successful, this will either run |callback| for a // If the DNS resolution was successful, this will either run |callback| for a
// DNS probe, or start the TLS socket for a TLS probe. This is determined by // DNS probe, or start the TLS socket for a TLS probe. This is determined by
// |also_do_tls_connect|. If the DNS resolution failed, |callback| is run with // |also_do_tls_connect|. If the DNS resolution failed, |callback| is run with
......
...@@ -131,6 +131,9 @@ IsolatedPrerenderOriginProbeType IsolatedPrerenderOriginProbeMechanism() { ...@@ -131,6 +131,9 @@ IsolatedPrerenderOriginProbeType IsolatedPrerenderOriginProbeMechanism() {
return IsolatedPrerenderOriginProbeType::kDns; return IsolatedPrerenderOriginProbeType::kDns;
if (param == "http_head") if (param == "http_head")
return IsolatedPrerenderOriginProbeType::kHttpHead; return IsolatedPrerenderOriginProbeType::kHttpHead;
if (param == "tls")
return IsolatedPrerenderOriginProbeType::kTls;
// Most restrictive by default.
return IsolatedPrerenderOriginProbeType::kHttpHead; return IsolatedPrerenderOriginProbeType::kHttpHead;
} }
...@@ -65,6 +65,7 @@ base::TimeDelta IsolatedPrerenderCanaryCheckCacheLifetime(); ...@@ -65,6 +65,7 @@ base::TimeDelta IsolatedPrerenderCanaryCheckCacheLifetime();
enum class IsolatedPrerenderOriginProbeType { enum class IsolatedPrerenderOriginProbeType {
kDns, kDns,
kHttpHead, kHttpHead,
kTls,
}; };
IsolatedPrerenderOriginProbeType IsolatedPrerenderOriginProbeMechanism(); IsolatedPrerenderOriginProbeType IsolatedPrerenderOriginProbeMechanism();
......
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