Commit 4a5d72f1 authored by Cammie Smith Barnes's avatar Cammie Smith Barnes Committed by Chromium LUCI CQ

Net: Plumb CNAME aliases to HttpStream with aim to expose to ad-tag.

The overall project aims to expose CNAME aliases to the
SubresourceFilter to aid in ad tagging and blocking.

A previous CL added a base::Optional parameter to
net::ConnectJob::SetSocket and a getter and setter to net::Socket.

This change continues the plumbing by adding an accessor to
net::HttpBasicState as well as one to net::HttpStream.

All of HttpStream's derived classes receive trivial implementations
except for HttpBasicStream and WebSocketBasicHandshakeStream. SPDY and
QUIC support will come in later CLs.

Relevant tests:
net:net_unittests
out/Default/net_unittests --gtest_filter=*Dns*Alias*

Bug: 1151047
Change-Id: I8b38591e4b186ded8cb41f89571385eee9fe0aa6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2563450
Commit-Queue: Cammie Smith Barnes <cammie@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838249}
parent 2413bb01
......@@ -7,6 +7,7 @@
#include <utility>
#include "base/check_op.h"
#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/http/http_request_info.h"
......@@ -74,4 +75,11 @@ bool HttpBasicState::IsConnectionReused() const {
connection_->reuse_type() == ClientSocketHandle::UNUSED_IDLE;
}
const std::vector<std::string>& HttpBasicState::GetDnsAliases() const {
static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
return (connection_ && connection_->socket())
? connection_->socket()->GetDnsAliases()
: *emptyvector_result;
}
} // namespace net
......@@ -66,6 +66,11 @@ class NET_EXPORT_PRIVATE HttpBasicState {
// ClientSocketHandle::is_reused().
bool IsConnectionReused() const;
// Retrieves any DNS aliases for the remote endpoint. The alias chain order
// is preserved in reverse, from canonical name (i.e. address record name)
// through to query name.
const std::vector<std::string>& GetDnsAliases() const;
private:
scoped_refptr<GrowableIOBuffer> read_buf_;
......
......@@ -196,6 +196,10 @@ void HttpBasicStream::SetRequestHeadersCallback(
request_headers_callback_ = std::move(callback);
}
const std::vector<std::string>& HttpBasicStream::GetDnsAliases() const {
return state_.GetDnsAliases();
}
void HttpBasicStream::OnHandshakeConfirmed(CompletionOnceCallback callback,
int rv) {
if (rv == OK) {
......
......@@ -91,6 +91,8 @@ class NET_EXPORT_PRIVATE HttpBasicStream : public HttpStream {
void SetRequestHeadersCallback(RequestHeadersCallback callback) override;
const std::vector<std::string>& GetDnsAliases() const override;
private:
HttpStreamParser* parser() const { return state_.parser(); }
......
......@@ -14,6 +14,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
......@@ -142,6 +143,11 @@ class MockHttpStream : public HttpStream {
void SetPriority(RequestPriority priority) override {}
const std::vector<std::string>& GetDnsAliases() const override {
static const base::NoDestructor<std::vector<std::string>> nullvector_result;
return *nullvector_result;
}
// Methods to tweak/observer mock behavior:
void set_stall_reads_forever() { stall_reads_forever_ = true; }
......
......@@ -191,6 +191,11 @@ class NET_EXPORT_PRIVATE HttpStream {
// Set the idempotency of the request. No-op by default.
virtual void SetRequestIdempotency(Idempotency idempotency) {}
// Retrieves any DNS aliases for the remote endpoint. The alias chain order
// is preserved in reverse, from canonical name (i.e. address record name)
// through to query name.
virtual const std::vector<std::string>& GetDnsAliases() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(HttpStream);
};
......
......@@ -14,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
......@@ -164,6 +165,10 @@ class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
void SetPriority(RequestPriority priority) override {}
HttpStream* RenewStreamForAuth() override { return nullptr; }
const std::vector<std::string>& GetDnsAliases() const override {
static const base::NoDestructor<std::vector<std::string>> nullvector_result;
return *nullvector_result;
}
std::unique_ptr<WebSocketStream> Upgrade() override {
return std::unique_ptr<WebSocketStream>();
......
......@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/string_split.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/ip_endpoint.h"
......@@ -424,6 +425,11 @@ void QuicHttpStream::OnReadResponseHeadersComplete(int rv) {
}
}
const std::vector<std::string>& QuicHttpStream::GetDnsAliases() const {
static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
return *emptyvector_result;
}
void QuicHttpStream::ReadTrailingHeaders() {
int rv = stream_->ReadTrailingHeaders(
&trailing_header_block_,
......
......@@ -68,6 +68,7 @@ class NET_EXPORT_PRIVATE QuicHttpStream : public MultiplexedHttpStream {
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
void SetRequestIdempotency(Idempotency idempotency) override;
const std::vector<std::string>& GetDnsAliases() const override;
static HttpResponseInfo::ConnectionInfo ConnectionInfoFromQuicVersion(
quic::ParsedQuicVersion quic_version);
......
......@@ -13,6 +13,7 @@
#include "base/check_op.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
......@@ -711,4 +712,9 @@ void SpdyHttpStream::SetPriority(RequestPriority priority) {
}
}
const std::vector<std::string>& SpdyHttpStream::GetDnsAliases() const {
static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
return *emptyvector_result;
}
} // namespace net
......@@ -83,6 +83,7 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
const std::vector<std::string>& GetDnsAliases() const override;
// SpdyStream::Delegate implementation.
void OnHeadersSent() override;
......
......@@ -390,6 +390,11 @@ HttpStream* WebSocketBasicHandshakeStream::RenewStreamForAuth() {
return handshake_stream.release();
}
const std::vector<std::string>& WebSocketBasicHandshakeStream::GetDnsAliases()
const {
return state_.GetDnsAliases();
}
std::unique_ptr<WebSocketStream> WebSocketBasicHandshakeStream::Upgrade() {
// The HttpStreamParser object has a pointer to our ClientSocketHandle. Make
// sure it does not touch it again before it is destroyed.
......
......@@ -74,7 +74,7 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream final
void SetPriority(RequestPriority priority) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
HttpStream* RenewStreamForAuth() override;
const std::vector<std::string>& GetDnsAliases() const override;
// This is called from the top level once correct handshake response headers
// have been received. It creates an appropriate subclass of WebSocketStream
......
......@@ -22,6 +22,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/websockets/websocket_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
#include "url/origin.h"
......@@ -85,5 +86,72 @@ TEST(WebSocketBasicHandshakeStreamTest, ConnectionClosedOnFailure) {
EXPECT_FALSE(socket_ptr->IsConnected());
}
TEST(WebSocketBasicHandshakeStreamTest, DnsAliasesCanBeAccessed) {
std::string request = WebSocketStandardRequest(
"/", "www.example.org",
url::Origin::Create(GURL("http://origin.example.org")), "", "");
std::string response = WebSocketStandardResponse("");
MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, request.c_str())};
MockRead reads[] = {MockRead(SYNCHRONOUS, 1, response.c_str()),
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
IPEndPoint end_point(IPAddress(127, 0, 0, 1), 80);
SequencedSocketData sequenced_socket_data(
MockConnect(SYNCHRONOUS, OK, end_point), reads, writes);
auto socket = std::make_unique<MockTCPClientSocket>(
AddressList(end_point), nullptr, &sequenced_socket_data);
const int connect_result = socket->Connect(CompletionOnceCallback());
EXPECT_EQ(connect_result, OK);
std::vector<std::string> aliases({"alias1", "alias2", "www.example.org"});
socket->SetDnsAliases(aliases);
EXPECT_THAT(socket->GetDnsAliases(),
testing::ElementsAre("alias1", "alias2", "www.example.org"));
const MockTCPClientSocket* const socket_ptr = socket.get();
auto handle = std::make_unique<ClientSocketHandle>();
handle->SetSocket(std::move(socket));
EXPECT_THAT(handle->socket()->GetDnsAliases(),
testing::ElementsAre("alias1", "alias2", "www.example.org"));
DummyConnectDelegate delegate;
WebSocketEndpointLockManager endpoint_lock_manager;
TestWebSocketStreamRequestAPI stream_request_api;
std::vector<std::string> extensions = {
"permessage-deflate; client_max_window_bits"};
WebSocketBasicHandshakeStream basic_handshake_stream(
std::move(handle), &delegate, false, {}, extensions, &stream_request_api,
&endpoint_lock_manager);
basic_handshake_stream.SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
HttpRequestInfo request_info;
request_info.url = GURL("ws://www.example.com/");
request_info.method = "GET";
request_info.traffic_annotation =
MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
TestCompletionCallback callback1;
NetLogWithSource net_log;
const int result1 =
callback1.GetResult(basic_handshake_stream.InitializeStream(
&request_info, true, LOWEST, net_log, callback1.callback()));
EXPECT_EQ(result1, OK);
auto request_headers = WebSocketCommonTestHeaders();
HttpResponseInfo response_info;
TestCompletionCallback callback2;
const int result2 = callback2.GetResult(basic_handshake_stream.SendRequest(
request_headers, &response_info, callback2.callback()));
EXPECT_EQ(result2, OK);
TestCompletionCallback callback3;
const int result3 = callback3.GetResult(
basic_handshake_stream.ReadResponseHeaders(callback2.callback()));
EXPECT_EQ(result3, OK);
EXPECT_TRUE(socket_ptr->IsConnected());
EXPECT_THAT(basic_handshake_stream.GetDnsAliases(),
testing::ElementsAre("alias1", "alias2", "www.example.org"));
}
} // namespace
} // namespace net
......@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
......@@ -236,6 +237,12 @@ HttpStream* WebSocketHttp2HandshakeStream::RenewStreamForAuth() {
return nullptr;
}
const std::vector<std::string>& WebSocketHttp2HandshakeStream::GetDnsAliases()
const {
static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
return *emptyvector_result;
}
std::unique_ptr<WebSocketStream> WebSocketHttp2HandshakeStream::Upgrade() {
DCHECK(extension_params_.get());
......
......@@ -86,6 +86,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp2HandshakeStream
void SetPriority(RequestPriority priority) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
HttpStream* RenewStreamForAuth() override;
const std::vector<std::string>& GetDnsAliases() const override;
// WebSocketHandshakeStreamBase methods.
......
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