xref: /aosp_15_r20/external/cronet/net/url_request/url_request_context_builder_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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