1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/url_request/url_request_context_builder.h"
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_util.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/thread.h"
16 #include "net/base/cache_type.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/network_delegate_impl.h"
19 #include "net/base/sdch_manager.h"
20 #include "net/cert/cert_verifier.h"
21 #include "net/cookies/cookie_monster.h"
22 #include "net/dns/host_resolver.h"
23 #include "net/ftp/ftp_network_layer.h"
24 #include "net/http/http_auth_handler_factory.h"
25 #include "net/http/http_cache.h"
26 #include "net/http/http_network_layer.h"
27 #include "net/http/http_server_properties_impl.h"
28 #include "net/http/http_server_properties_manager.h"
29 #include "net/http/transport_security_persister.h"
30 #include "net/http/transport_security_state.h"
31 #include "net/ssl/channel_id_service.h"
32 #include "net/ssl/default_channel_id_store.h"
33 #include "net/ssl/ssl_config_service_defaults.h"
34 #include "net/url_request/data_protocol_handler.h"
35 #include "net/url_request/static_http_user_agent_settings.h"
36 #include "net/url_request/url_request_backoff_manager.h"
37 #include "net/url_request/url_request_context.h"
38 #include "net/url_request/url_request_context_storage.h"
39 #include "net/url_request/url_request_intercepting_job_factory.h"
40 #include "net/url_request/url_request_interceptor.h"
41 #include "net/url_request/url_request_job_factory_impl.h"
42 #include "net/url_request/url_request_throttler_manager.h"
44 #if !defined(DISABLE_FILE_SUPPORT)
45 #include "net/url_request/file_protocol_handler.h"
48 #if !defined(DISABLE_FTP_SUPPORT)
49 #include "net/url_request/ftp_protocol_handler.h"
56 class BasicNetworkDelegate
: public NetworkDelegateImpl
{
58 BasicNetworkDelegate() {}
59 ~BasicNetworkDelegate() override
{}
62 int OnBeforeURLRequest(URLRequest
* request
,
63 const CompletionCallback
& callback
,
64 GURL
* new_url
) override
{
68 int OnBeforeSendHeaders(URLRequest
* request
,
69 const CompletionCallback
& callback
,
70 HttpRequestHeaders
* headers
) override
{
74 void OnSendHeaders(URLRequest
* request
,
75 const HttpRequestHeaders
& headers
) override
{}
77 int OnHeadersReceived(
79 const CompletionCallback
& callback
,
80 const HttpResponseHeaders
* original_response_headers
,
81 scoped_refptr
<HttpResponseHeaders
>* override_response_headers
,
82 GURL
* allowed_unsafe_redirect_url
) override
{
86 void OnBeforeRedirect(URLRequest
* request
,
87 const GURL
& new_location
) override
{}
89 void OnResponseStarted(URLRequest
* request
) override
{}
91 void OnCompleted(URLRequest
* request
, bool started
) override
{}
93 void OnURLRequestDestroyed(URLRequest
* request
) override
{}
95 void OnPACScriptError(int line_number
, const base::string16
& error
) override
{
98 NetworkDelegate::AuthRequiredResponse
OnAuthRequired(
100 const AuthChallengeInfo
& auth_info
,
101 const AuthCallback
& callback
,
102 AuthCredentials
* credentials
) override
{
103 return NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION
;
106 bool OnCanGetCookies(const URLRequest
& request
,
107 const CookieList
& cookie_list
) override
{
111 bool OnCanSetCookie(const URLRequest
& request
,
112 const std::string
& cookie_line
,
113 CookieOptions
* options
) override
{
117 bool OnCanAccessFile(const URLRequest
& request
,
118 const base::FilePath
& path
) const override
{
122 DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate
);
125 // Define a context class that can self-manage the ownership of its components
126 // via a UrlRequestContextStorage object.
127 class ContainerURLRequestContext
: public URLRequestContext
{
129 explicit ContainerURLRequestContext(
130 const scoped_refptr
<base::SingleThreadTaskRunner
>& file_task_runner
)
131 : file_task_runner_(file_task_runner
), storage_(this) {}
132 ~ContainerURLRequestContext() override
{ AssertNoURLRequests(); }
134 URLRequestContextStorage
* storage() {
138 scoped_refptr
<base::SingleThreadTaskRunner
>& GetFileTaskRunner() {
139 // Create a new thread to run file tasks, if needed.
140 if (!file_task_runner_
) {
141 DCHECK(!file_thread_
);
142 file_thread_
.reset(new base::Thread("Network File Thread"));
143 file_thread_
->StartWithOptions(
144 base::Thread::Options(base::MessageLoop::TYPE_DEFAULT
, 0));
145 file_task_runner_
= file_thread_
->task_runner();
147 return file_task_runner_
;
150 void set_transport_security_persister(
151 scoped_ptr
<TransportSecurityPersister
> transport_security_persister
) {
152 transport_security_persister
= transport_security_persister
.Pass();
156 // The thread should be torn down last.
157 scoped_ptr
<base::Thread
> file_thread_
;
158 scoped_refptr
<base::SingleThreadTaskRunner
> file_task_runner_
;
160 URLRequestContextStorage storage_
;
161 scoped_ptr
<TransportSecurityPersister
> transport_security_persister_
;
163 DISALLOW_COPY_AND_ASSIGN(ContainerURLRequestContext
);
168 URLRequestContextBuilder::HttpCacheParams::HttpCacheParams()
171 URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {}
173 URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
174 : ignore_certificate_errors(false),
175 host_mapping_rules(NULL
),
176 testing_fixed_http_port(0),
177 testing_fixed_https_port(0),
178 next_protos(NextProtosDefaults()),
179 use_alternative_services(true),
181 enable_insecure_quic(false) {}
183 URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
186 URLRequestContextBuilder::SchemeFactory::SchemeFactory(
187 const std::string
& auth_scheme
,
188 HttpAuthHandlerFactory
* auth_handler_factory
)
189 : scheme(auth_scheme
), factory(auth_handler_factory
) {
192 URLRequestContextBuilder::SchemeFactory::~SchemeFactory() {
195 URLRequestContextBuilder::URLRequestContextBuilder()
196 : data_enabled_(false),
197 #if !defined(DISABLE_FILE_SUPPORT)
198 file_enabled_(false),
200 #if !defined(DISABLE_FTP_SUPPORT)
203 http_cache_enabled_(true),
204 throttling_enabled_(false),
205 backoff_enabled_(false),
206 sdch_enabled_(false),
210 URLRequestContextBuilder::~URLRequestContextBuilder() {}
212 void URLRequestContextBuilder::SetHttpNetworkSessionComponents(
213 const URLRequestContext
* context
,
214 HttpNetworkSession::Params
* params
) {
215 params
->host_resolver
= context
->host_resolver();
216 params
->cert_verifier
= context
->cert_verifier();
217 params
->transport_security_state
= context
->transport_security_state();
218 params
->cert_transparency_verifier
= context
->cert_transparency_verifier();
219 params
->proxy_service
= context
->proxy_service();
220 params
->ssl_config_service
= context
->ssl_config_service();
221 params
->http_auth_handler_factory
= context
->http_auth_handler_factory();
222 params
->network_delegate
= context
->network_delegate();
223 params
->http_server_properties
= context
->http_server_properties();
224 params
->net_log
= context
->net_log();
225 params
->channel_id_service
= context
->channel_id_service();
228 void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams
& params
) {
229 http_cache_enabled_
= true;
230 http_cache_params_
= params
;
233 void URLRequestContextBuilder::DisableHttpCache() {
234 http_cache_enabled_
= false;
235 http_cache_params_
= HttpCacheParams();
238 void URLRequestContextBuilder::SetSpdyAndQuicEnabled(bool spdy_enabled
,
240 http_network_session_params_
.next_protos
=
241 NextProtosWithSpdyAndQuic(spdy_enabled
, quic_enabled
);
242 http_network_session_params_
.enable_quic
= quic_enabled
;
245 void URLRequestContextBuilder::SetInterceptors(
246 ScopedVector
<URLRequestInterceptor
> url_request_interceptors
) {
247 url_request_interceptors_
= url_request_interceptors
.Pass();
250 void URLRequestContextBuilder::SetCookieAndChannelIdStores(
251 const scoped_refptr
<CookieStore
>& cookie_store
,
252 scoped_ptr
<ChannelIDService
> channel_id_service
) {
253 DCHECK(cookie_store
);
254 cookie_store_
= cookie_store
;
255 channel_id_service_
= channel_id_service
.Pass();
258 void URLRequestContextBuilder::SetFileTaskRunner(
259 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
) {
260 file_task_runner_
= task_runner
;
263 void URLRequestContextBuilder::SetHttpServerProperties(
264 scoped_ptr
<HttpServerProperties
> http_server_properties
) {
265 http_server_properties_
= http_server_properties
.Pass();
268 scoped_ptr
<URLRequestContext
> URLRequestContextBuilder::Build() {
269 scoped_ptr
<ContainerURLRequestContext
> context(
270 new ContainerURLRequestContext(file_task_runner_
));
271 URLRequestContextStorage
* storage
= context
->storage();
273 storage
->set_http_user_agent_settings(new StaticHttpUserAgentSettings(
274 accept_language_
, user_agent_
));
276 if (!network_delegate_
)
277 network_delegate_
.reset(new BasicNetworkDelegate
);
278 NetworkDelegate
* network_delegate
= network_delegate_
.release();
279 storage
->set_network_delegate(network_delegate
);
282 // Unlike the other builder parameters, |net_log_| is not owned by the
283 // builder or resulting context.
284 context
->set_net_log(net_log_
);
286 storage
->set_net_log(new NetLog
);
289 if (!host_resolver_
) {
290 host_resolver_
= HostResolver::CreateDefaultResolver(context
->net_log());
292 storage
->set_host_resolver(host_resolver_
.Pass());
294 if (!proxy_service_
) {
295 // TODO(willchan): Switch to using this code when
296 // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
297 #if defined(OS_LINUX) || defined(OS_ANDROID)
298 ProxyConfigService
* proxy_config_service
= proxy_config_service_
.release();
300 ProxyConfigService
* proxy_config_service
= NULL
;
301 if (proxy_config_service_
) {
302 proxy_config_service
= proxy_config_service_
.release();
304 proxy_config_service
= ProxyService::CreateSystemProxyConfigService(
305 base::ThreadTaskRunnerHandle::Get().get(),
306 context
->GetFileTaskRunner());
308 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
309 proxy_service_
.reset(
310 ProxyService::CreateUsingSystemProxyResolver(
311 proxy_config_service
,
312 0, // This results in using the default value.
313 context
->net_log()));
315 storage
->set_proxy_service(proxy_service_
.release());
317 storage
->set_ssl_config_service(new SSLConfigServiceDefaults
);
318 HttpAuthHandlerRegistryFactory
* http_auth_handler_registry_factory
=
319 HttpAuthHandlerRegistryFactory::CreateDefault(context
->host_resolver());
320 for (size_t i
= 0; i
< extra_http_auth_handlers_
.size(); ++i
) {
321 http_auth_handler_registry_factory
->RegisterSchemeFactory(
322 extra_http_auth_handlers_
[i
].scheme
,
323 extra_http_auth_handlers_
[i
].factory
);
325 storage
->set_http_auth_handler_factory(http_auth_handler_registry_factory
);
328 storage
->set_cookie_store(cookie_store_
.get());
329 storage
->set_channel_id_service(channel_id_service_
.Pass());
331 storage
->set_cookie_store(new CookieMonster(NULL
, NULL
));
332 // TODO(mmenke): This always creates a file thread, even when it ends up
333 // not being used. Consider lazily creating the thread.
334 storage
->set_channel_id_service(make_scoped_ptr(new ChannelIDService(
335 new DefaultChannelIDStore(NULL
), context
->GetFileTaskRunner())));
339 storage
->set_sdch_manager(
340 scoped_ptr
<net::SdchManager
>(new SdchManager()).Pass());
343 storage
->set_transport_security_state(new TransportSecurityState());
344 if (!transport_security_persister_path_
.empty()) {
345 context
->set_transport_security_persister(
346 make_scoped_ptr
<TransportSecurityPersister
>(
347 new TransportSecurityPersister(context
->transport_security_state(),
348 transport_security_persister_path_
,
349 context
->GetFileTaskRunner(),
353 if (http_server_properties_
) {
354 storage
->set_http_server_properties(http_server_properties_
.Pass());
356 storage
->set_http_server_properties(
357 scoped_ptr
<HttpServerProperties
>(new HttpServerPropertiesImpl()));
360 storage
->set_cert_verifier(CertVerifier::CreateDefault());
362 if (throttling_enabled_
)
363 storage
->set_throttler_manager(new URLRequestThrottlerManager());
365 if (backoff_enabled_
)
366 storage
->set_backoff_manager(new URLRequestBackoffManager());
368 HttpNetworkSession::Params network_session_params
;
369 SetHttpNetworkSessionComponents(context
.get(), &network_session_params
);
371 network_session_params
.ignore_certificate_errors
=
372 http_network_session_params_
.ignore_certificate_errors
;
373 network_session_params
.host_mapping_rules
=
374 http_network_session_params_
.host_mapping_rules
;
375 network_session_params
.testing_fixed_http_port
=
376 http_network_session_params_
.testing_fixed_http_port
;
377 network_session_params
.testing_fixed_https_port
=
378 http_network_session_params_
.testing_fixed_https_port
;
379 network_session_params
.use_alternative_services
=
380 http_network_session_params_
.use_alternative_services
;
381 network_session_params
.trusted_spdy_proxy
=
382 http_network_session_params_
.trusted_spdy_proxy
;
383 network_session_params
.next_protos
= http_network_session_params_
.next_protos
;
384 network_session_params
.enable_quic
= http_network_session_params_
.enable_quic
;
385 network_session_params
.enable_insecure_quic
=
386 http_network_session_params_
.enable_insecure_quic
;
387 network_session_params
.quic_connection_options
=
388 http_network_session_params_
.quic_connection_options
;
390 HttpTransactionFactory
* http_transaction_factory
= NULL
;
391 if (http_cache_enabled_
) {
392 HttpCache::BackendFactory
* http_cache_backend
= NULL
;
393 if (http_cache_params_
.type
== HttpCacheParams::DISK
) {
394 http_cache_backend
= new HttpCache::DefaultBackend(
395 DISK_CACHE
, CACHE_BACKEND_DEFAULT
, http_cache_params_
.path
,
396 http_cache_params_
.max_size
, context
->GetFileTaskRunner());
399 HttpCache::DefaultBackend::InMemory(http_cache_params_
.max_size
);
402 http_transaction_factory
= new HttpCache(
403 network_session_params
, http_cache_backend
);
405 scoped_refptr
<HttpNetworkSession
> network_session(
406 new HttpNetworkSession(network_session_params
));
408 http_transaction_factory
= new HttpNetworkLayer(network_session
.get());
410 storage
->set_http_transaction_factory(http_transaction_factory
);
412 URLRequestJobFactoryImpl
* job_factory
= new URLRequestJobFactoryImpl
;
414 job_factory
->SetProtocolHandler("data",
415 make_scoped_ptr(new DataProtocolHandler
));
417 #if !defined(DISABLE_FILE_SUPPORT)
419 job_factory
->SetProtocolHandler(
421 make_scoped_ptr(new FileProtocolHandler(context
->GetFileTaskRunner())));
423 #endif // !defined(DISABLE_FILE_SUPPORT)
425 #if !defined(DISABLE_FTP_SUPPORT)
427 ftp_transaction_factory_
.reset(
428 new FtpNetworkLayer(context
->host_resolver()));
429 job_factory
->SetProtocolHandler(
430 "ftp", make_scoped_ptr(
431 new FtpProtocolHandler(ftp_transaction_factory_
.get())));
433 #endif // !defined(DISABLE_FTP_SUPPORT)
435 scoped_ptr
<net::URLRequestJobFactory
> top_job_factory(job_factory
);
436 if (!url_request_interceptors_
.empty()) {
437 // Set up interceptors in the reverse order.
439 for (ScopedVector
<net::URLRequestInterceptor
>::reverse_iterator i
=
440 url_request_interceptors_
.rbegin();
441 i
!= url_request_interceptors_
.rend(); ++i
) {
442 top_job_factory
.reset(new net::URLRequestInterceptingJobFactory(
443 top_job_factory
.Pass(), make_scoped_ptr(*i
)));
445 url_request_interceptors_
.weak_clear();
447 storage
->set_job_factory(top_job_factory
.release());
448 // TODO(willchan): Support sdch.
450 return context
.Pass();