• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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