• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <memory>
6 
7 #include "base/feature_list.h"
8 #include "base/files/file_path.h"
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/bind.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16 #include "net/base/features.h"
17 #include "net/base/isolation_info.h"
18 #include "net/base/load_timing_info.h"
19 #include "net/base/network_delegate.h"
20 #include "net/cert/ct_policy_enforcer.h"
21 #include "net/cert/ct_policy_status.h"
22 #include "net/cert/mock_cert_verifier.h"
23 #include "net/dns/mapped_host_resolver.h"
24 #include "net/dns/mock_host_resolver.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/log/net_log_event_type.h"
27 #include "net/log/test_net_log_util.h"
28 #include "net/quic/crypto_test_utils_chromium.h"
29 #include "net/quic/quic_context.h"
30 #include "net/test/cert_test_util.h"
31 #include "net/test/gtest_util.h"
32 #include "net/test/test_data_directory.h"
33 #include "net/test/test_with_task_environment.h"
34 #include "net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h"
35 #include "net/third_party/quiche/src/quiche/quic/core/quic_time.h"
36 #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
37 #include "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h"
38 #include "net/third_party/quiche/src/quiche/quic/tools/quic_simple_dispatcher.h"
39 #include "net/tools/quic/quic_simple_server.h"
40 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
41 #include "net/url_request/url_request.h"
42 #include "net/url_request/url_request_context.h"
43 #include "net/url_request/url_request_context_builder.h"
44 #include "net/url_request/url_request_test_util.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 #include "url/gurl.h"
48 #include "url/origin.h"
49 
50 namespace net {
51 
52 namespace {
53 
54 // This must match the certificate used (quic-chain.pem and quic-leaf-cert.key).
55 const char kTestServerHost[] = "test.example.com";
56 // Used as a simple response from the server.
57 const char kHelloPath[] = "/hello.txt";
58 const char kHelloBodyValue[] = "Hello from QUIC Server";
59 const int kHelloStatus = 200;
60 
61 class MockCTPolicyEnforcerNonCompliant : public CTPolicyEnforcer {
62  public:
63   MockCTPolicyEnforcerNonCompliant() = default;
64   ~MockCTPolicyEnforcerNonCompliant() override = default;
65 
CheckCompliance(X509Certificate * cert,const ct::SCTList & verified_scts,const NetLogWithSource & net_log)66   ct::CTPolicyCompliance CheckCompliance(
67       X509Certificate* cert,
68       const ct::SCTList& verified_scts,
69       const NetLogWithSource& net_log) override {
70     return ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS;
71   }
72 };
73 
74 class URLRequestQuicTest
75     : public TestWithTaskEnvironment,
76       public ::testing::WithParamInterface<quic::ParsedQuicVersion> {
77  protected:
URLRequestQuicTest()78   URLRequestQuicTest()
79       : context_builder_(CreateTestURLRequestContextBuilder()) {
80     QuicEnableVersion(version());
81     StartQuicServer(version());
82 
83     HttpNetworkSessionParams params;
84     CertVerifyResult verify_result;
85     verify_result.verified_cert = ImportCertFromFile(
86         GetTestCertsDirectory(), "quic-chain.pem");
87     auto cert_verifier = std::make_unique<MockCertVerifier>();
88     cert_verifier->AddResultForCertAndHost(verify_result.verified_cert.get(),
89                                            kTestServerHost, verify_result, OK);
90     // To simplify the test, and avoid the race with the HTTP request, we force
91     // QUIC for these requests.
92     auto quic_context = std::make_unique<QuicContext>();
93     quic_context->params()->supported_versions = {version()};
94     quic_context->params()->origins_to_force_quic_on.insert(
95         HostPortPair(kTestServerHost, 443));
96     context_builder_->set_quic_context(std::move(quic_context));
97     params.enable_quic = true;
98     context_builder_->set_host_resolver(std::move(host_resolver_));
99     context_builder_->set_http_network_session_params(params);
100     context_builder_->SetCertVerifier(std::move(cert_verifier));
101     context_builder_->set_net_log(NetLog::Get());
102   }
103 
TearDown()104   void TearDown() override {
105     if (server_) {
106       server_->Shutdown();
107       base::RunLoop().RunUntilIdle();
108     }
109   }
110 
context_builder()111   URLRequestContextBuilder* context_builder() { return context_builder_.get(); }
112 
BuildContext()113   std::unique_ptr<URLRequestContext> BuildContext() {
114     auto context = context_builder_->Build();
115     return context;
116   }
117 
CreateRequest(URLRequestContext * context,const GURL & url,URLRequest::Delegate * delegate)118   static std::unique_ptr<URLRequest> CreateRequest(
119       URLRequestContext* context,
120       const GURL& url,
121       URLRequest::Delegate* delegate) {
122     return context->CreateRequest(url, DEFAULT_PRIORITY, delegate,
123                                   TRAFFIC_ANNOTATION_FOR_TESTS);
124   }
125 
GetRstErrorCountReceivedByServer(quic::QuicRstStreamErrorCode error_code) const126   unsigned int GetRstErrorCountReceivedByServer(
127       quic::QuicRstStreamErrorCode error_code) const {
128     return (static_cast<quic::QuicSimpleDispatcher*>(server_->dispatcher()))
129         ->GetRstErrorCount(error_code);
130   }
131 
FindEndBySource(const std::vector<NetLogEntry> & entries,const NetLogSource & source)132   static const NetLogEntry* FindEndBySource(
133       const std::vector<NetLogEntry>& entries,
134       const NetLogSource& source) {
135     for (const auto& entry : entries) {
136       if (entry.phase == NetLogEventPhase::END &&
137           entry.source.type == source.type && entry.source.id == source.id)
138         return &entry;
139     }
140     return nullptr;
141   }
142 
version()143   quic::ParsedQuicVersion version() { return GetParam(); }
144 
145  protected:
146   // Returns a fully-qualified URL for |path| on the test server.
UrlFromPath(base::StringPiece path)147   std::string UrlFromPath(base::StringPiece path) {
148     return std::string("https://") + std::string(kTestServerHost) +
149            std::string(path);
150   }
151 
SetDelay(std::string_view host,std::string_view path,base::TimeDelta delay)152   void SetDelay(std::string_view host,
153                 std::string_view path,
154                 base::TimeDelta delay) {
155     memory_cache_backend_.SetResponseDelay(
156         host, path,
157         quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
158   }
159 
160  private:
StartQuicServer(quic::ParsedQuicVersion version)161   void StartQuicServer(quic::ParsedQuicVersion version) {
162     // Set up in-memory cache.
163 
164     // Add the simply hello response.
165     memory_cache_backend_.AddSimpleResponse(kTestServerHost, kHelloPath,
166                                             kHelloStatus, kHelloBodyValue);
167 
168     quic::QuicConfig config;
169     // Set up server certs.
170     server_ = std::make_unique<QuicSimpleServer>(
171         net::test::ProofSourceForTestingChromium(), config,
172         quic::QuicCryptoServerConfig::ConfigOptions(),
173         quic::ParsedQuicVersionVector{version}, &memory_cache_backend_);
174     int rv =
175         server_->Listen(net::IPEndPoint(net::IPAddress::IPv4AllZeros(), 0));
176     EXPECT_GE(rv, 0) << "Quic server fails to start";
177 
178     auto resolver = std::make_unique<MockHostResolver>();
179     resolver->rules()->AddRule("test.example.com", "127.0.0.1");
180     host_resolver_ = std::make_unique<MappedHostResolver>(std::move(resolver));
181     // Use a mapped host resolver so that request for test.example.com
182     // reach the server running on localhost.
183     std::string map_rule =
184         "MAP test.example.com test.example.com:" +
185         base::NumberToString(server_->server_address().port());
186     EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule));
187   }
188 
189   std::unique_ptr<MappedHostResolver> host_resolver_;
190   std::unique_ptr<QuicSimpleServer> server_;
191   quic::QuicMemoryCacheBackend memory_cache_backend_;
192   std::unique_ptr<URLRequestContextBuilder> context_builder_;
193   quic::test::QuicFlagSaver flags_;  // Save/restore all QUIC flag values.
194 };
195 
196 // A URLRequest::Delegate that checks LoadTimingInfo when response headers are
197 // received.
198 class CheckLoadTimingDelegate : public TestDelegate {
199  public:
CheckLoadTimingDelegate(bool session_reused)200   explicit CheckLoadTimingDelegate(bool session_reused)
201       : session_reused_(session_reused) {}
202 
203   CheckLoadTimingDelegate(const CheckLoadTimingDelegate&) = delete;
204   CheckLoadTimingDelegate& operator=(const CheckLoadTimingDelegate&) = delete;
205 
OnResponseStarted(URLRequest * request,int error)206   void OnResponseStarted(URLRequest* request, int error) override {
207     TestDelegate::OnResponseStarted(request, error);
208     LoadTimingInfo load_timing_info;
209     request->GetLoadTimingInfo(&load_timing_info);
210     assertLoadTimingValid(load_timing_info, session_reused_);
211   }
212 
213  private:
assertLoadTimingValid(const LoadTimingInfo & load_timing_info,bool session_reused)214   void assertLoadTimingValid(const LoadTimingInfo& load_timing_info,
215                              bool session_reused) {
216     EXPECT_EQ(session_reused, load_timing_info.socket_reused);
217 
218     // If |session_reused| is true, these fields should all be null, non-null
219     // otherwise.
220     EXPECT_EQ(session_reused,
221               load_timing_info.connect_timing.connect_start.is_null());
222     EXPECT_EQ(session_reused,
223               load_timing_info.connect_timing.connect_end.is_null());
224     EXPECT_EQ(session_reused,
225               load_timing_info.connect_timing.ssl_start.is_null());
226     EXPECT_EQ(session_reused,
227               load_timing_info.connect_timing.ssl_end.is_null());
228     EXPECT_EQ(load_timing_info.connect_timing.connect_start,
229               load_timing_info.connect_timing.ssl_start);
230     EXPECT_EQ(load_timing_info.connect_timing.connect_end,
231               load_timing_info.connect_timing.ssl_end);
232     EXPECT_EQ(session_reused,
233               load_timing_info.connect_timing.domain_lookup_start.is_null());
234     EXPECT_EQ(session_reused,
235               load_timing_info.connect_timing.domain_lookup_end.is_null());
236   }
237 
238   bool session_reused_;
239 };
240 
241 // A TestNetworkDelegate that invokes |all_requests_completed_callback| when
242 // |num_expected_requests| requests are completed.
243 class WaitForCompletionNetworkDelegate : public net::TestNetworkDelegate {
244  public:
WaitForCompletionNetworkDelegate(base::OnceClosure all_requests_completed_callback,size_t num_expected_requests)245   WaitForCompletionNetworkDelegate(
246       base::OnceClosure all_requests_completed_callback,
247       size_t num_expected_requests)
248       : all_requests_completed_callback_(
249             std::move(all_requests_completed_callback)),
250         num_expected_requests_(num_expected_requests) {}
251 
252   WaitForCompletionNetworkDelegate(const WaitForCompletionNetworkDelegate&) =
253       delete;
254   WaitForCompletionNetworkDelegate& operator=(
255       const WaitForCompletionNetworkDelegate&) = delete;
256 
OnCompleted(URLRequest * request,bool started,int net_error)257   void OnCompleted(URLRequest* request, bool started, int net_error) override {
258     net::TestNetworkDelegate::OnCompleted(request, started, net_error);
259     num_expected_requests_--;
260     if (num_expected_requests_ == 0)
261       std::move(all_requests_completed_callback_).Run();
262   }
263 
264  private:
265   base::OnceClosure all_requests_completed_callback_;
266   size_t num_expected_requests_;
267 };
268 
269 }  // namespace
270 
271 // Used by ::testing::PrintToStringParamName().
PrintToString(const quic::ParsedQuicVersion & v)272 std::string PrintToString(const quic::ParsedQuicVersion& v) {
273   return quic::ParsedQuicVersionToString(v);
274 }
275 
276 INSTANTIATE_TEST_SUITE_P(Version,
277                          URLRequestQuicTest,
278                          ::testing::ValuesIn(AllSupportedQuicVersions()),
279                          ::testing::PrintToStringParamName());
280 
TEST_P(URLRequestQuicTest,TestGetRequest)281 TEST_P(URLRequestQuicTest, TestGetRequest) {
282   auto context = BuildContext();
283   CheckLoadTimingDelegate delegate(false);
284   std::unique_ptr<URLRequest> request =
285       CreateRequest(context.get(), GURL(UrlFromPath(kHelloPath)), &delegate);
286 
287   request->Start();
288   ASSERT_TRUE(request->is_pending());
289   delegate.RunUntilComplete();
290 
291   EXPECT_EQ(OK, delegate.request_status());
292   EXPECT_EQ(kHelloBodyValue, delegate.data_received());
293   EXPECT_TRUE(request->ssl_info().is_valid());
294 }
295 
296 // Tests that if two requests use the same QUIC session, the second request
297 // should not have |LoadTimingInfo::connect_timing|.
TEST_P(URLRequestQuicTest,TestTwoRequests)298 TEST_P(URLRequestQuicTest, TestTwoRequests) {
299   base::RunLoop run_loop;
300   context_builder()->set_network_delegate(
301       std::make_unique<WaitForCompletionNetworkDelegate>(
302           run_loop.QuitClosure(), /*num_expected_requests=*/2));
303   auto context = BuildContext();
304 
305   GURL url = GURL(UrlFromPath(kHelloPath));
306   auto isolation_info =
307       IsolationInfo::CreateForInternalRequest(url::Origin::Create(url));
308 
309   CheckLoadTimingDelegate delegate(false);
310   delegate.set_on_complete(base::DoNothing());
311   std::unique_ptr<URLRequest> request =
312       CreateRequest(context.get(), url, &delegate);
313   request->set_isolation_info(isolation_info);
314 
315   CheckLoadTimingDelegate delegate2(true);
316   delegate2.set_on_complete(base::DoNothing());
317   std::unique_ptr<URLRequest> request2 =
318       CreateRequest(context.get(), url, &delegate2);
319   request2->set_isolation_info(isolation_info);
320 
321   request->Start();
322   request2->Start();
323   ASSERT_TRUE(request->is_pending());
324   ASSERT_TRUE(request2->is_pending());
325   run_loop.Run();
326 
327   EXPECT_EQ(OK, delegate.request_status());
328   EXPECT_EQ(OK, delegate2.request_status());
329   EXPECT_EQ(kHelloBodyValue, delegate.data_received());
330   EXPECT_EQ(kHelloBodyValue, delegate2.data_received());
331 }
332 
TEST_P(URLRequestQuicTest,RequestHeadersCallback)333 TEST_P(URLRequestQuicTest, RequestHeadersCallback) {
334   auto context = BuildContext();
335   HttpRawRequestHeaders raw_headers;
336   TestDelegate delegate;
337   HttpRequestHeaders extra_headers;
338   extra_headers.SetHeader("X-Foo", "bar");
339 
340   std::unique_ptr<URLRequest> request =
341       CreateRequest(context.get(), GURL(UrlFromPath(kHelloPath)), &delegate);
342 
343   request->SetExtraRequestHeaders(extra_headers);
344   request->SetRequestHeadersCallback(
345       base::BindLambdaForTesting([&](HttpRawRequestHeaders raw_headers) {
346         // This should be invoked before the request is completed, or any bytes
347         // are read.
348         EXPECT_FALSE(delegate.response_completed());
349         EXPECT_FALSE(delegate.bytes_received());
350 
351         EXPECT_FALSE(raw_headers.headers().empty());
352         std::string value;
353         EXPECT_TRUE(raw_headers.FindHeaderForTest("x-foo", &value));
354         EXPECT_EQ("bar", value);
355         EXPECT_TRUE(raw_headers.FindHeaderForTest("accept-encoding", &value));
356         EXPECT_EQ("gzip, deflate", value);
357         EXPECT_TRUE(raw_headers.FindHeaderForTest(":path", &value));
358         EXPECT_EQ("/hello.txt", value);
359         EXPECT_TRUE(raw_headers.FindHeaderForTest(":authority", &value));
360         EXPECT_EQ("test.example.com", value);
361         EXPECT_TRUE(raw_headers.request_line().empty());
362       }));
363   request->Start();
364   ASSERT_TRUE(request->is_pending());
365   delegate.RunUntilComplete();
366   EXPECT_EQ(OK, delegate.request_status());
367 }
368 
TEST_P(URLRequestQuicTest,DelayedResponseStart)369 TEST_P(URLRequestQuicTest, DelayedResponseStart) {
370   auto context = BuildContext();
371   TestDelegate delegate;
372   std::unique_ptr<URLRequest> request =
373       CreateRequest(context.get(), GURL(UrlFromPath(kHelloPath)), &delegate);
374 
375   constexpr auto delay = base::Milliseconds(300);
376 
377   this->SetDelay(kTestServerHost, kHelloPath, delay);
378   request->Start();
379   ASSERT_TRUE(request->is_pending());
380   delegate.RunUntilComplete();
381   LoadTimingInfo timing_info;
382   request->GetLoadTimingInfo(&timing_info);
383   EXPECT_EQ(OK, delegate.request_status());
384   EXPECT_GE((timing_info.receive_headers_start - timing_info.request_start),
385             delay);
386   EXPECT_GE(timing_info.receive_non_informational_headers_start,
387             timing_info.receive_headers_start);
388 }
389 
390 }  // namespace net
391