1 // Copyright 2012 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 "net/url_request/url_request_context_builder.h"
6
7 #include "base/functional/callback_helpers.h"
8 #include "base/run_loop.h"
9 #include "base/task/single_thread_task_runner.h"
10 #include "base/task/thread_pool.h"
11 #include "base/test/scoped_feature_list.h"
12 #include "build/build_config.h"
13 #include "net/base/cronet_buildflags.h"
14 #include "net/base/mock_network_change_notifier.h"
15 #include "net/base/network_anonymization_key.h"
16 #include "net/base/request_priority.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/dns/host_resolver.h"
19 #include "net/dns/host_resolver_manager.h"
20 #include "net/dns/mock_host_resolver.h"
21 #include "net/http/http_auth_challenge_tokenizer.h"
22 #include "net/http/http_auth_handler.h"
23 #include "net/http/http_auth_handler_factory.h"
24 #include "net/log/net_log_with_source.h"
25 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
26 #include "net/socket/client_socket_factory.h"
27 #include "net/ssl/ssl_info.h"
28 #include "net/test/embedded_test_server/embedded_test_server.h"
29 #include "net/test/gtest_util.h"
30 #include "net/test/test_with_task_environment.h"
31 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
32 #include "net/url_request/url_request.h"
33 #include "net/url_request/url_request_test_util.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "testing/platform_test.h"
36 #include "url/gurl.h"
37 #include "url/scheme_host_port.h"
38
39 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
40 #include "net/proxy_resolution/proxy_config.h"
41 #include "net/proxy_resolution/proxy_config_service_fixed.h"
42 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
43 // BUILDFLAG(IS_ANDROID)
44
45 #if BUILDFLAG(IS_ANDROID)
46 #include "base/android/build_info.h"
47 #endif // BUILDFLAG(IS_ANDROID)
48
49 #if BUILDFLAG(ENABLE_REPORTING)
50 #include "base/files/scoped_temp_dir.h"
51
52 #if !BUILDFLAG(CRONET_BUILD)
53 // gn check does not account for BUILDFLAG(). So, for Cronet builds, it will
54 // complain about a missing dependency on the target exposing this header. Add a
55 // nogncheck to stop it from yelling.
56 #include "net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h" // nogncheck
57 #endif // !BUILDFLAG(CRONET_BUILD)
58
59 #include "net/reporting/reporting_context.h"
60 #include "net/reporting/reporting_policy.h"
61 #include "net/reporting/reporting_service.h"
62 #include "net/reporting/reporting_uploader.h"
63 #endif // BUILDFLAG(ENABLE_REPORTING)
64
65 namespace net {
66
67 namespace {
68
69 class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
70 public:
MockHttpAuthHandlerFactory(std::string supported_scheme,int return_code)71 MockHttpAuthHandlerFactory(std::string supported_scheme, int return_code)
72 : return_code_(return_code), supported_scheme_(supported_scheme) {}
73 ~MockHttpAuthHandlerFactory() override = default;
74
CreateAuthHandler(HttpAuthChallengeTokenizer * challenge,HttpAuth::Target target,const SSLInfo & ssl_info,const NetworkAnonymizationKey & network_anonymization_key,const url::SchemeHostPort & scheme_host_port,CreateReason reason,int nonce_count,const NetLogWithSource & net_log,HostResolver * host_resolver,std::unique_ptr<HttpAuthHandler> * handler)75 int CreateAuthHandler(
76 HttpAuthChallengeTokenizer* challenge,
77 HttpAuth::Target target,
78 const SSLInfo& ssl_info,
79 const NetworkAnonymizationKey& network_anonymization_key,
80 const url::SchemeHostPort& scheme_host_port,
81 CreateReason reason,
82 int nonce_count,
83 const NetLogWithSource& net_log,
84 HostResolver* host_resolver,
85 std::unique_ptr<HttpAuthHandler>* handler) override {
86 handler->reset();
87
88 return challenge->auth_scheme() == supported_scheme_
89 ? return_code_
90 : ERR_UNSUPPORTED_AUTH_SCHEME;
91 }
92
93 private:
94 int return_code_;
95 std::string supported_scheme_;
96 };
97
98 class URLRequestContextBuilderTest : public PlatformTest,
99 public WithTaskEnvironment {
100 protected:
URLRequestContextBuilderTest()101 URLRequestContextBuilderTest() {
102 test_server_.AddDefaultHandlers(
103 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
104 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
105 builder_.set_proxy_config_service(std::make_unique<ProxyConfigServiceFixed>(
106 ProxyConfigWithAnnotation::CreateDirect()));
107 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
108 // BUILDFLAG(IS_ANDROID)
109 }
110
111 std::unique_ptr<HostResolver> host_resolver_ =
112 std::make_unique<MockHostResolver>();
113 EmbeddedTestServer test_server_;
114 URLRequestContextBuilder builder_;
115 };
116
TEST_F(URLRequestContextBuilderTest,DefaultSettings)117 TEST_F(URLRequestContextBuilderTest, DefaultSettings) {
118 ASSERT_TRUE(test_server_.Start());
119
120 std::unique_ptr<URLRequestContext> context(builder_.Build());
121 TestDelegate delegate;
122 std::unique_ptr<URLRequest> request(context->CreateRequest(
123 test_server_.GetURL("/echoheader?Foo"), DEFAULT_PRIORITY, &delegate,
124 TRAFFIC_ANNOTATION_FOR_TESTS));
125 request->set_method("GET");
126 request->SetExtraRequestHeaderByName("Foo", "Bar", false);
127 request->Start();
128 base::RunLoop().Run();
129 EXPECT_EQ("Bar", delegate.data_received());
130 }
131
TEST_F(URLRequestContextBuilderTest,UserAgent)132 TEST_F(URLRequestContextBuilderTest, UserAgent) {
133 ASSERT_TRUE(test_server_.Start());
134
135 builder_.set_user_agent("Bar");
136 std::unique_ptr<URLRequestContext> context(builder_.Build());
137 TestDelegate delegate;
138 std::unique_ptr<URLRequest> request(context->CreateRequest(
139 test_server_.GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
140 &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
141 request->set_method("GET");
142 request->Start();
143 base::RunLoop().Run();
144 EXPECT_EQ("Bar", delegate.data_received());
145 }
146
TEST_F(URLRequestContextBuilderTest,DefaultHttpAuthHandlerFactory)147 TEST_F(URLRequestContextBuilderTest, DefaultHttpAuthHandlerFactory) {
148 url::SchemeHostPort scheme_host_port(GURL("https://www.google.com"));
149 std::unique_ptr<HttpAuthHandler> handler;
150 std::unique_ptr<URLRequestContext> context(builder_.Build());
151 SSLInfo null_ssl_info;
152
153 // Verify that the default basic handler is present
154 EXPECT_EQ(OK,
155 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
156 "basic", HttpAuth::AUTH_SERVER, null_ssl_info,
157 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
158 host_resolver_.get(), &handler));
159 }
160
TEST_F(URLRequestContextBuilderTest,CustomHttpAuthHandlerFactory)161 TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) {
162 url::SchemeHostPort scheme_host_port(GURL("https://www.google.com"));
163 const int kBasicReturnCode = OK;
164 std::unique_ptr<HttpAuthHandler> handler;
165 builder_.SetHttpAuthHandlerFactory(
166 std::make_unique<MockHttpAuthHandlerFactory>("extrascheme",
167 kBasicReturnCode));
168 std::unique_ptr<URLRequestContext> context(builder_.Build());
169 SSLInfo null_ssl_info;
170 // Verify that a handler is returned for a custom scheme.
171 EXPECT_EQ(kBasicReturnCode,
172 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
173 "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info,
174 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
175 host_resolver_.get(), &handler));
176
177 // Verify that the default basic handler isn't present
178 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
179 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
180 "basic", HttpAuth::AUTH_SERVER, null_ssl_info,
181 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
182 host_resolver_.get(), &handler));
183
184 // Verify that a handler isn't returned for a bogus scheme.
185 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
186 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
187 "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info,
188 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
189 host_resolver_.get(), &handler));
190 }
191
192 #if BUILDFLAG(ENABLE_REPORTING)
193 // See crbug.com/935209. This test ensures that shutdown occurs correctly and
194 // does not crash while destoying the NEL and Reporting services in the process
195 // of destroying the URLRequestContext whilst Reporting has a pending upload.
TEST_F(URLRequestContextBuilderTest,ShutDownNELAndReportingWithPendingUpload)196 TEST_F(URLRequestContextBuilderTest, ShutDownNELAndReportingWithPendingUpload) {
197 std::unique_ptr<MockHostResolver> host_resolver =
198 std::make_unique<MockHostResolver>();
199 host_resolver->set_ondemand_mode(true);
200 MockHostResolver* mock_host_resolver = host_resolver.get();
201 builder_.set_host_resolver(std::move(host_resolver));
202 builder_.set_proxy_resolution_service(
203 ConfiguredProxyResolutionService::CreateDirect());
204 builder_.set_reporting_policy(std::make_unique<ReportingPolicy>());
205 builder_.set_network_error_logging_enabled(true);
206
207 std::unique_ptr<URLRequestContext> context(builder_.Build());
208 ASSERT_TRUE(context->network_error_logging_service());
209 ASSERT_TRUE(context->reporting_service());
210
211 // Queue a pending upload.
212 GURL url("https://www.foo.test");
213 context->reporting_service()->GetContextForTesting()->uploader()->StartUpload(
214 url::Origin::Create(url), url, IsolationInfo::CreateTransient(),
215 "report body", 0,
216 /*eligible_for_credentials=*/false, base::DoNothing());
217 base::RunLoop().RunUntilIdle();
218 ASSERT_EQ(1, context->reporting_service()
219 ->GetContextForTesting()
220 ->uploader()
221 ->GetPendingUploadCountForTesting());
222 ASSERT_TRUE(mock_host_resolver->has_pending_requests());
223
224 // This should shut down and destroy the NEL and Reporting services, including
225 // the PendingUpload, and should not cause a crash.
226 context.reset();
227 }
228
229 #if !BUILDFLAG(CRONET_BUILD)
230 // See crbug.com/935209. This test ensures that shutdown occurs correctly and
231 // does not crash while destoying the NEL and Reporting services in the process
232 // of destroying the URLRequestContext whilst Reporting has a pending upload.
TEST_F(URLRequestContextBuilderTest,ShutDownNELAndReportingWithPendingUploadAndPersistentStorage)233 TEST_F(URLRequestContextBuilderTest,
234 ShutDownNELAndReportingWithPendingUploadAndPersistentStorage) {
235 std::unique_ptr<MockHostResolver> host_resolver =
236 std::make_unique<MockHostResolver>();
237 host_resolver->set_ondemand_mode(true);
238 MockHostResolver* mock_host_resolver = host_resolver.get();
239 builder_.set_host_resolver(std::move(host_resolver));
240 builder_.set_proxy_resolution_service(
241 ConfiguredProxyResolutionService::CreateDirect());
242 builder_.set_reporting_policy(std::make_unique<ReportingPolicy>());
243 builder_.set_network_error_logging_enabled(true);
244 base::ScopedTempDir scoped_temp_dir;
245 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
246 builder_.set_persistent_reporting_and_nel_store(
247 std::make_unique<SQLitePersistentReportingAndNelStore>(
248 scoped_temp_dir.GetPath().Append(
249 FILE_PATH_LITERAL("ReportingAndNelStore")),
250 base::SingleThreadTaskRunner::GetCurrentDefault(),
251 base::ThreadPool::CreateSequencedTaskRunner(
252 {base::MayBlock(),
253 net::GetReportingAndNelStoreBackgroundSequencePriority(),
254 base::TaskShutdownBehavior::BLOCK_SHUTDOWN})));
255
256 std::unique_ptr<URLRequestContext> context(builder_.Build());
257 ASSERT_TRUE(context->network_error_logging_service());
258 ASSERT_TRUE(context->reporting_service());
259 ASSERT_TRUE(context->network_error_logging_service()
260 ->GetPersistentNelStoreForTesting());
261 ASSERT_TRUE(context->reporting_service()->GetContextForTesting()->store());
262
263 // Queue a pending upload.
264 GURL url("https://www.foo.test");
265 context->reporting_service()->GetContextForTesting()->uploader()->StartUpload(
266 url::Origin::Create(url), url, IsolationInfo::CreateTransient(),
267 "report body", 0,
268 /*eligible_for_credentials=*/false, base::DoNothing());
269 base::RunLoop().RunUntilIdle();
270 ASSERT_EQ(1, context->reporting_service()
271 ->GetContextForTesting()
272 ->uploader()
273 ->GetPendingUploadCountForTesting());
274 ASSERT_TRUE(mock_host_resolver->has_pending_requests());
275
276 // This should shut down and destroy the NEL and Reporting services, including
277 // the PendingUpload, and should not cause a crash.
278 context.reset();
279 }
280 #endif // !BUILDFLAG(CRONET_BUILD)
281 #endif // BUILDFLAG(ENABLE_REPORTING)
282
TEST_F(URLRequestContextBuilderTest,ShutdownHostResolverWithPendingRequest)283 TEST_F(URLRequestContextBuilderTest, ShutdownHostResolverWithPendingRequest) {
284 auto mock_host_resolver = std::make_unique<MockHostResolver>();
285 mock_host_resolver->rules()->AddRule("example.com", "1.2.3.4");
286 mock_host_resolver->set_ondemand_mode(true);
287 auto state = mock_host_resolver->state();
288 builder_.set_host_resolver(std::move(mock_host_resolver));
289 std::unique_ptr<URLRequestContext> context(builder_.Build());
290
291 std::unique_ptr<HostResolver::ResolveHostRequest> request =
292 context->host_resolver()->CreateRequest(
293 HostPortPair("example.com", 1234), NetworkAnonymizationKey(),
294 NetLogWithSource(), absl::nullopt);
295 TestCompletionCallback callback;
296 int rv = request->Start(callback.callback());
297 ASSERT_TRUE(state->has_pending_requests());
298
299 context.reset();
300
301 EXPECT_FALSE(state->has_pending_requests());
302
303 // Request should never complete.
304 base::RunLoop().RunUntilIdle();
305 EXPECT_THAT(rv, test::IsError(ERR_IO_PENDING));
306 EXPECT_FALSE(callback.have_result());
307 }
308
TEST_F(URLRequestContextBuilderTest,DefaultHostResolver)309 TEST_F(URLRequestContextBuilderTest, DefaultHostResolver) {
310 auto manager = std::make_unique<HostResolverManager>(
311 HostResolver::ManagerOptions(), nullptr /* system_dns_config_notifier */,
312 nullptr /* net_log */);
313
314 builder_.set_host_resolver_manager(manager.get());
315 std::unique_ptr<URLRequestContext> context = builder_.Build();
316
317 EXPECT_EQ(context.get(), context->host_resolver()->GetContextForTesting());
318 EXPECT_EQ(manager.get(), context->host_resolver()->GetManagerForTesting());
319 }
320
TEST_F(URLRequestContextBuilderTest,CustomHostResolver)321 TEST_F(URLRequestContextBuilderTest, CustomHostResolver) {
322 std::unique_ptr<HostResolver> resolver =
323 HostResolver::CreateStandaloneResolver(nullptr);
324 ASSERT_FALSE(resolver->GetContextForTesting());
325
326 builder_.set_host_resolver(std::move(resolver));
327 std::unique_ptr<URLRequestContext> context = builder_.Build();
328
329 EXPECT_EQ(context.get(), context->host_resolver()->GetContextForTesting());
330 }
331
TEST_F(URLRequestContextBuilderTest,BindToNetworkFinalConfiguration)332 TEST_F(URLRequestContextBuilderTest, BindToNetworkFinalConfiguration) {
333 #if BUILDFLAG(IS_ANDROID)
334 if (base::android::BuildInfo::GetInstance()->sdk_int() <
335 base::android::SDK_VERSION_MARSHMALLOW) {
336 GTEST_SKIP()
337 << "BindToNetwork is supported starting from Android Marshmallow";
338 }
339
340 // The actual network handle doesn't really matter, this test just wants to
341 // check that all the pieces are in place and configured correctly.
342 constexpr handles::NetworkHandle network = 2;
343 auto scoped_mock_network_change_notifier =
344 std::make_unique<test::ScopedMockNetworkChangeNotifier>();
345 test::MockNetworkChangeNotifier* mock_ncn =
346 scoped_mock_network_change_notifier->mock_network_change_notifier();
347 mock_ncn->ForceNetworkHandlesSupported();
348
349 builder_.BindToNetwork(network);
350 std::unique_ptr<URLRequestContext> context = builder_.Build();
351
352 EXPECT_EQ(context->bound_network(), network);
353 EXPECT_EQ(context->host_resolver()->GetTargetNetworkForTesting(), network);
354 EXPECT_EQ(context->host_resolver()
355 ->GetManagerForTesting()
356 ->target_network_for_testing(),
357 network);
358 ASSERT_TRUE(context->GetNetworkSessionContext());
359 // A special factory that bind sockets to `network` is needed. We don't need
360 // to check exactly for that, the fact that we are not using the default one
361 // should be good enough.
362 EXPECT_NE(context->GetNetworkSessionContext()->client_socket_factory,
363 ClientSocketFactory::GetDefaultFactory());
364
365 const auto* quic_params = context->quic_context()->params();
366 EXPECT_FALSE(quic_params->close_sessions_on_ip_change);
367 EXPECT_FALSE(quic_params->goaway_sessions_on_ip_change);
368 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
369
370 const auto* network_session_params = context->GetNetworkSessionParams();
371 EXPECT_TRUE(network_session_params->ignore_ip_address_changes);
372 #else // !BUILDFLAG(IS_ANDROID)
373 GTEST_SKIP() << "BindToNetwork is supported only on Android";
374 #endif // BUILDFLAG(IS_ANDROID)
375 }
376
TEST_F(URLRequestContextBuilderTest,BindToNetworkCustomManagerOptions)377 TEST_F(URLRequestContextBuilderTest, BindToNetworkCustomManagerOptions) {
378 #if BUILDFLAG(IS_ANDROID)
379 if (base::android::BuildInfo::GetInstance()->sdk_int() <
380 base::android::SDK_VERSION_MARSHMALLOW) {
381 GTEST_SKIP()
382 << "BindToNetwork is supported starting from Android Marshmallow";
383 }
384
385 // The actual network handle doesn't really matter, this test just wants to
386 // check that all the pieces are in place and configured correctly.
387 constexpr handles::NetworkHandle network = 2;
388 auto scoped_mock_network_change_notifier =
389 std::make_unique<test::ScopedMockNetworkChangeNotifier>();
390 test::MockNetworkChangeNotifier* mock_ncn =
391 scoped_mock_network_change_notifier->mock_network_change_notifier();
392 mock_ncn->ForceNetworkHandlesSupported();
393
394 // Set non-default value for check_ipv6_on_wifi and check that this is what
395 // HostResolverManager receives.
396 HostResolver::ManagerOptions options;
397 options.check_ipv6_on_wifi = !options.check_ipv6_on_wifi;
398 builder_.BindToNetwork(network, options);
399 std::unique_ptr<URLRequestContext> context = builder_.Build();
400 EXPECT_EQ(context->host_resolver()
401 ->GetManagerForTesting()
402 ->check_ipv6_on_wifi_for_testing(),
403 options.check_ipv6_on_wifi);
404 #else // !BUILDFLAG(IS_ANDROID)
405 GTEST_SKIP() << "BindToNetwork is supported only on Android";
406 #endif // BUILDFLAG(IS_ANDROID)
407 }
408
TEST_F(URLRequestContextBuilderTest,MigrateSessionsOnNetworkChangeV2Default)409 TEST_F(URLRequestContextBuilderTest, MigrateSessionsOnNetworkChangeV2Default) {
410 std::unique_ptr<URLRequestContext> context = builder_.Build();
411
412 const QuicParams* quic_params = context->quic_context()->params();
413 #if BUILDFLAG(IS_ANDROID)
414 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
415 #else // !BUILDFLAG(IS_ANDROID)
416 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
417 #endif // BUILDFLAG(IS_ANDROID)
418 }
419
TEST_F(URLRequestContextBuilderTest,MigrateSessionsOnNetworkChangeV2Override)420 TEST_F(URLRequestContextBuilderTest, MigrateSessionsOnNetworkChangeV2Override) {
421 base::test::ScopedFeatureList scoped_list;
422 scoped_list.InitAndDisableFeature(
423 net::features::kMigrateSessionsOnNetworkChangeV2);
424 std::unique_ptr<URLRequestContext> context = builder_.Build();
425
426 const QuicParams* quic_params = context->quic_context()->params();
427 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
428 }
429
430 } // namespace
431
432 } // namespace net
433