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 SetUpURLRequestContextBuilder(builder_);
105 }
106
SetUpURLRequestContextBuilder(URLRequestContextBuilder & builder)107 void SetUpURLRequestContextBuilder(URLRequestContextBuilder& builder) {
108 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
109 builder.set_proxy_config_service(std::make_unique<ProxyConfigServiceFixed>(
110 ProxyConfigWithAnnotation::CreateDirect()));
111 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
112 // BUILDFLAG(IS_ANDROID)
113 }
114
115 std::unique_ptr<HostResolver> host_resolver_ =
116 std::make_unique<MockHostResolver>();
117 EmbeddedTestServer test_server_;
118 URLRequestContextBuilder builder_;
119 };
120
TEST_F(URLRequestContextBuilderTest,DefaultSettings)121 TEST_F(URLRequestContextBuilderTest, DefaultSettings) {
122 ASSERT_TRUE(test_server_.Start());
123
124 std::unique_ptr<URLRequestContext> context(builder_.Build());
125 TestDelegate delegate;
126 std::unique_ptr<URLRequest> request(context->CreateRequest(
127 test_server_.GetURL("/echoheader?Foo"), DEFAULT_PRIORITY, &delegate,
128 TRAFFIC_ANNOTATION_FOR_TESTS));
129 request->set_method("GET");
130 request->SetExtraRequestHeaderByName("Foo", "Bar", false);
131 request->Start();
132 delegate.RunUntilComplete();
133 EXPECT_EQ("Bar", delegate.data_received());
134 }
135
TEST_F(URLRequestContextBuilderTest,UserAgent)136 TEST_F(URLRequestContextBuilderTest, UserAgent) {
137 ASSERT_TRUE(test_server_.Start());
138
139 builder_.set_user_agent("Bar");
140 std::unique_ptr<URLRequestContext> context(builder_.Build());
141 TestDelegate delegate;
142 std::unique_ptr<URLRequest> request(context->CreateRequest(
143 test_server_.GetURL("/echoheader?User-Agent"), DEFAULT_PRIORITY,
144 &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
145 request->set_method("GET");
146 request->Start();
147 delegate.RunUntilComplete();
148 EXPECT_EQ("Bar", delegate.data_received());
149 }
150
TEST_F(URLRequestContextBuilderTest,DefaultHttpAuthHandlerFactory)151 TEST_F(URLRequestContextBuilderTest, DefaultHttpAuthHandlerFactory) {
152 url::SchemeHostPort scheme_host_port(GURL("https://www.google.com"));
153 std::unique_ptr<HttpAuthHandler> handler;
154 std::unique_ptr<URLRequestContext> context(builder_.Build());
155 SSLInfo null_ssl_info;
156
157 // Verify that the default basic handler is present
158 EXPECT_EQ(OK,
159 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
160 "basic", HttpAuth::AUTH_SERVER, null_ssl_info,
161 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
162 host_resolver_.get(), &handler));
163 }
164
TEST_F(URLRequestContextBuilderTest,CustomHttpAuthHandlerFactory)165 TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) {
166 url::SchemeHostPort scheme_host_port(GURL("https://www.google.com"));
167 const int kBasicReturnCode = OK;
168 std::unique_ptr<HttpAuthHandler> handler;
169 builder_.SetHttpAuthHandlerFactory(
170 std::make_unique<MockHttpAuthHandlerFactory>("extrascheme",
171 kBasicReturnCode));
172 std::unique_ptr<URLRequestContext> context(builder_.Build());
173 SSLInfo null_ssl_info;
174 // Verify that a handler is returned for a custom scheme.
175 EXPECT_EQ(kBasicReturnCode,
176 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
177 "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info,
178 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
179 host_resolver_.get(), &handler));
180
181 // Verify that the default basic handler isn't present
182 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
183 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
184 "basic", HttpAuth::AUTH_SERVER, null_ssl_info,
185 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
186 host_resolver_.get(), &handler));
187
188 // Verify that a handler isn't returned for a bogus scheme.
189 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
190 context->http_auth_handler_factory()->CreateAuthHandlerFromString(
191 "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info,
192 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource(),
193 host_resolver_.get(), &handler));
194 }
195
196 #if BUILDFLAG(ENABLE_REPORTING)
197 // See crbug.com/935209. This test ensures that shutdown occurs correctly and
198 // does not crash while destoying the NEL and Reporting services in the process
199 // of destroying the URLRequestContext whilst Reporting has a pending upload.
TEST_F(URLRequestContextBuilderTest,ShutDownNELAndReportingWithPendingUpload)200 TEST_F(URLRequestContextBuilderTest, ShutDownNELAndReportingWithPendingUpload) {
201 std::unique_ptr<MockHostResolver> host_resolver =
202 std::make_unique<MockHostResolver>();
203 host_resolver->set_ondemand_mode(true);
204 MockHostResolver* mock_host_resolver = host_resolver.get();
205 builder_.set_host_resolver(std::move(host_resolver));
206 builder_.set_proxy_resolution_service(
207 ConfiguredProxyResolutionService::CreateDirect());
208 builder_.set_reporting_policy(std::make_unique<ReportingPolicy>());
209 builder_.set_network_error_logging_enabled(true);
210
211 std::unique_ptr<URLRequestContext> context(builder_.Build());
212 ASSERT_TRUE(context->network_error_logging_service());
213 ASSERT_TRUE(context->reporting_service());
214
215 // Queue a pending upload.
216 GURL url("https://www.foo.test");
217 context->reporting_service()->GetContextForTesting()->uploader()->StartUpload(
218 url::Origin::Create(url), url, IsolationInfo::CreateTransient(),
219 "report body", 0,
220 /*eligible_for_credentials=*/false, base::DoNothing());
221 base::RunLoop().RunUntilIdle();
222 ASSERT_EQ(1, context->reporting_service()
223 ->GetContextForTesting()
224 ->uploader()
225 ->GetPendingUploadCountForTesting());
226 ASSERT_TRUE(mock_host_resolver->has_pending_requests());
227
228 // This should shut down and destroy the NEL and Reporting services, including
229 // the PendingUpload, and should not cause a crash.
230 context.reset();
231 }
232
233 #if !BUILDFLAG(CRONET_BUILD)
234 // See crbug.com/935209. This test ensures that shutdown occurs correctly and
235 // does not crash while destoying the NEL and Reporting services in the process
236 // of destroying the URLRequestContext whilst Reporting has a pending upload.
TEST_F(URLRequestContextBuilderTest,ShutDownNELAndReportingWithPendingUploadAndPersistentStorage)237 TEST_F(URLRequestContextBuilderTest,
238 ShutDownNELAndReportingWithPendingUploadAndPersistentStorage) {
239 std::unique_ptr<MockHostResolver> host_resolver =
240 std::make_unique<MockHostResolver>();
241 host_resolver->set_ondemand_mode(true);
242 MockHostResolver* mock_host_resolver = host_resolver.get();
243 builder_.set_host_resolver(std::move(host_resolver));
244 builder_.set_proxy_resolution_service(
245 ConfiguredProxyResolutionService::CreateDirect());
246 builder_.set_reporting_policy(std::make_unique<ReportingPolicy>());
247 builder_.set_network_error_logging_enabled(true);
248 base::ScopedTempDir scoped_temp_dir;
249 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
250 builder_.set_persistent_reporting_and_nel_store(
251 std::make_unique<SQLitePersistentReportingAndNelStore>(
252 scoped_temp_dir.GetPath().Append(
253 FILE_PATH_LITERAL("ReportingAndNelStore")),
254 base::SingleThreadTaskRunner::GetCurrentDefault(),
255 base::ThreadPool::CreateSequencedTaskRunner(
256 {base::MayBlock(),
257 net::GetReportingAndNelStoreBackgroundSequencePriority(),
258 base::TaskShutdownBehavior::BLOCK_SHUTDOWN})));
259
260 std::unique_ptr<URLRequestContext> context(builder_.Build());
261 ASSERT_TRUE(context->network_error_logging_service());
262 ASSERT_TRUE(context->reporting_service());
263 ASSERT_TRUE(context->network_error_logging_service()
264 ->GetPersistentNelStoreForTesting());
265 ASSERT_TRUE(context->reporting_service()->GetContextForTesting()->store());
266
267 // Queue a pending upload.
268 GURL url("https://www.foo.test");
269 context->reporting_service()->GetContextForTesting()->uploader()->StartUpload(
270 url::Origin::Create(url), url, IsolationInfo::CreateTransient(),
271 "report body", 0,
272 /*eligible_for_credentials=*/false, base::DoNothing());
273 base::RunLoop().RunUntilIdle();
274 ASSERT_EQ(1, context->reporting_service()
275 ->GetContextForTesting()
276 ->uploader()
277 ->GetPendingUploadCountForTesting());
278 ASSERT_TRUE(mock_host_resolver->has_pending_requests());
279
280 // This should shut down and destroy the NEL and Reporting services, including
281 // the PendingUpload, and should not cause a crash.
282 context.reset();
283 }
284 #endif // !BUILDFLAG(CRONET_BUILD)
285 #endif // BUILDFLAG(ENABLE_REPORTING)
286
TEST_F(URLRequestContextBuilderTest,ShutdownHostResolverWithPendingRequest)287 TEST_F(URLRequestContextBuilderTest, ShutdownHostResolverWithPendingRequest) {
288 auto mock_host_resolver = std::make_unique<MockHostResolver>();
289 mock_host_resolver->rules()->AddRule("example.com", "1.2.3.4");
290 mock_host_resolver->set_ondemand_mode(true);
291 auto state = mock_host_resolver->state();
292 builder_.set_host_resolver(std::move(mock_host_resolver));
293 std::unique_ptr<URLRequestContext> context(builder_.Build());
294
295 std::unique_ptr<HostResolver::ResolveHostRequest> request =
296 context->host_resolver()->CreateRequest(HostPortPair("example.com", 1234),
297 NetworkAnonymizationKey(),
298 NetLogWithSource(), std::nullopt);
299 TestCompletionCallback callback;
300 int rv = request->Start(callback.callback());
301 ASSERT_TRUE(state->has_pending_requests());
302
303 context.reset();
304
305 EXPECT_FALSE(state->has_pending_requests());
306
307 // Request should never complete.
308 base::RunLoop().RunUntilIdle();
309 EXPECT_THAT(rv, test::IsError(ERR_IO_PENDING));
310 EXPECT_FALSE(callback.have_result());
311 }
312
TEST_F(URLRequestContextBuilderTest,DefaultHostResolver)313 TEST_F(URLRequestContextBuilderTest, DefaultHostResolver) {
314 auto manager = std::make_unique<HostResolverManager>(
315 HostResolver::ManagerOptions(), nullptr /* system_dns_config_notifier */,
316 nullptr /* net_log */);
317
318 // Use a stack allocated builder instead of `builder_` to avoid dangling
319 // pointer of `manager`.
320 URLRequestContextBuilder builder;
321 SetUpURLRequestContextBuilder(builder);
322 builder.set_host_resolver_manager(manager.get());
323 std::unique_ptr<URLRequestContext> context = builder.Build();
324
325 EXPECT_EQ(context.get(), context->host_resolver()->GetContextForTesting());
326 EXPECT_EQ(manager.get(), context->host_resolver()->GetManagerForTesting());
327 }
328
TEST_F(URLRequestContextBuilderTest,CustomHostResolver)329 TEST_F(URLRequestContextBuilderTest, CustomHostResolver) {
330 std::unique_ptr<HostResolver> resolver =
331 HostResolver::CreateStandaloneResolver(nullptr);
332 ASSERT_FALSE(resolver->GetContextForTesting());
333
334 builder_.set_host_resolver(std::move(resolver));
335 std::unique_ptr<URLRequestContext> context = builder_.Build();
336
337 EXPECT_EQ(context.get(), context->host_resolver()->GetContextForTesting());
338 }
339
TEST_F(URLRequestContextBuilderTest,BindToNetworkFinalConfiguration)340 TEST_F(URLRequestContextBuilderTest, BindToNetworkFinalConfiguration) {
341 #if BUILDFLAG(IS_ANDROID)
342 if (base::android::BuildInfo::GetInstance()->sdk_int() <
343 base::android::SDK_VERSION_MARSHMALLOW) {
344 GTEST_SKIP()
345 << "BindToNetwork is supported starting from Android Marshmallow";
346 }
347
348 // The actual network handle doesn't really matter, this test just wants to
349 // check that all the pieces are in place and configured correctly.
350 constexpr handles::NetworkHandle network = 2;
351 auto scoped_mock_network_change_notifier =
352 std::make_unique<test::ScopedMockNetworkChangeNotifier>();
353 test::MockNetworkChangeNotifier* mock_ncn =
354 scoped_mock_network_change_notifier->mock_network_change_notifier();
355 mock_ncn->ForceNetworkHandlesSupported();
356
357 builder_.BindToNetwork(network);
358 std::unique_ptr<URLRequestContext> context = builder_.Build();
359
360 EXPECT_EQ(context->bound_network(), network);
361 EXPECT_EQ(context->host_resolver()->GetTargetNetworkForTesting(), network);
362 EXPECT_EQ(context->host_resolver()
363 ->GetManagerForTesting()
364 ->target_network_for_testing(),
365 network);
366 ASSERT_TRUE(context->GetNetworkSessionContext());
367 // A special factory that bind sockets to `network` is needed. We don't need
368 // to check exactly for that, the fact that we are not using the default one
369 // should be good enough.
370 EXPECT_NE(context->GetNetworkSessionContext()->client_socket_factory,
371 ClientSocketFactory::GetDefaultFactory());
372
373 const auto* quic_params = context->quic_context()->params();
374 EXPECT_FALSE(quic_params->close_sessions_on_ip_change);
375 EXPECT_FALSE(quic_params->goaway_sessions_on_ip_change);
376 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
377
378 const auto* network_session_params = context->GetNetworkSessionParams();
379 EXPECT_TRUE(network_session_params->ignore_ip_address_changes);
380 #else // !BUILDFLAG(IS_ANDROID)
381 GTEST_SKIP() << "BindToNetwork is supported only on Android";
382 #endif // BUILDFLAG(IS_ANDROID)
383 }
384
TEST_F(URLRequestContextBuilderTest,BindToNetworkCustomManagerOptions)385 TEST_F(URLRequestContextBuilderTest, BindToNetworkCustomManagerOptions) {
386 #if BUILDFLAG(IS_ANDROID)
387 if (base::android::BuildInfo::GetInstance()->sdk_int() <
388 base::android::SDK_VERSION_MARSHMALLOW) {
389 GTEST_SKIP()
390 << "BindToNetwork is supported starting from Android Marshmallow";
391 }
392
393 // The actual network handle doesn't really matter, this test just wants to
394 // check that all the pieces are in place and configured correctly.
395 constexpr handles::NetworkHandle network = 2;
396 auto scoped_mock_network_change_notifier =
397 std::make_unique<test::ScopedMockNetworkChangeNotifier>();
398 test::MockNetworkChangeNotifier* mock_ncn =
399 scoped_mock_network_change_notifier->mock_network_change_notifier();
400 mock_ncn->ForceNetworkHandlesSupported();
401
402 // Set non-default value for check_ipv6_on_wifi and check that this is what
403 // HostResolverManager receives.
404 HostResolver::ManagerOptions options;
405 options.check_ipv6_on_wifi = !options.check_ipv6_on_wifi;
406 builder_.BindToNetwork(network, options);
407 std::unique_ptr<URLRequestContext> context = builder_.Build();
408 EXPECT_EQ(context->host_resolver()
409 ->GetManagerForTesting()
410 ->check_ipv6_on_wifi_for_testing(),
411 options.check_ipv6_on_wifi);
412 #else // !BUILDFLAG(IS_ANDROID)
413 GTEST_SKIP() << "BindToNetwork is supported only on Android";
414 #endif // BUILDFLAG(IS_ANDROID)
415 }
416
TEST_F(URLRequestContextBuilderTest,MigrateSessionsOnNetworkChangeV2Default)417 TEST_F(URLRequestContextBuilderTest, MigrateSessionsOnNetworkChangeV2Default) {
418 std::unique_ptr<URLRequestContext> context = builder_.Build();
419
420 const QuicParams* quic_params = context->quic_context()->params();
421 #if BUILDFLAG(IS_ANDROID)
422 EXPECT_TRUE(quic_params->migrate_sessions_on_network_change_v2);
423 #else // !BUILDFLAG(IS_ANDROID)
424 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
425 #endif // BUILDFLAG(IS_ANDROID)
426 }
427
TEST_F(URLRequestContextBuilderTest,MigrateSessionsOnNetworkChangeV2Override)428 TEST_F(URLRequestContextBuilderTest, MigrateSessionsOnNetworkChangeV2Override) {
429 base::test::ScopedFeatureList scoped_list;
430 scoped_list.InitAndDisableFeature(
431 net::features::kMigrateSessionsOnNetworkChangeV2);
432 std::unique_ptr<URLRequestContext> context = builder_.Build();
433
434 const QuicParams* quic_params = context->quic_context()->params();
435 EXPECT_FALSE(quic_params->migrate_sessions_on_network_change_v2);
436 }
437
438 } // namespace
439
440 } // namespace net
441