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.
4
5 #include "net/url_request/url_request_context_builder.h"
6
7 #include <string>
8
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/thread.h"
15 #include "net/base/cache_type.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/network_delegate.h"
18 #include "net/cert/cert_verifier.h"
19 #include "net/cookies/cookie_monster.h"
20 #include "net/dns/host_resolver.h"
21 #include "net/ftp/ftp_network_layer.h"
22 #include "net/http/http_auth_handler_factory.h"
23 #include "net/http/http_cache.h"
24 #include "net/http/http_network_layer.h"
25 #include "net/http/http_network_session.h"
26 #include "net/http/http_server_properties_impl.h"
27 #include "net/http/transport_security_persister.h"
28 #include "net/http/transport_security_state.h"
29 #include "net/ssl/channel_id_service.h"
30 #include "net/ssl/default_channel_id_store.h"
31 #include "net/ssl/ssl_config_service_defaults.h"
32 #include "net/url_request/data_protocol_handler.h"
33 #include "net/url_request/static_http_user_agent_settings.h"
34 #include "net/url_request/url_request_context.h"
35 #include "net/url_request/url_request_context_storage.h"
36 #include "net/url_request/url_request_job_factory_impl.h"
37 #include "net/url_request/url_request_throttler_manager.h"
38
39 #if !defined(DISABLE_FILE_SUPPORT)
40 #include "net/url_request/file_protocol_handler.h"
41 #endif
42
43 #if !defined(DISABLE_FTP_SUPPORT)
44 #include "net/url_request/ftp_protocol_handler.h"
45 #endif
46
47 namespace net {
48
49 namespace {
50
51 class BasicNetworkDelegate : public NetworkDelegate {
52 public:
BasicNetworkDelegate()53 BasicNetworkDelegate() {}
~BasicNetworkDelegate()54 virtual ~BasicNetworkDelegate() {}
55
56 private:
OnBeforeURLRequest(URLRequest * request,const CompletionCallback & callback,GURL * new_url)57 virtual int OnBeforeURLRequest(URLRequest* request,
58 const CompletionCallback& callback,
59 GURL* new_url) OVERRIDE {
60 return OK;
61 }
62
OnBeforeSendHeaders(URLRequest * request,const CompletionCallback & callback,HttpRequestHeaders * headers)63 virtual int OnBeforeSendHeaders(URLRequest* request,
64 const CompletionCallback& callback,
65 HttpRequestHeaders* headers) OVERRIDE {
66 return OK;
67 }
68
OnSendHeaders(URLRequest * request,const HttpRequestHeaders & headers)69 virtual void OnSendHeaders(URLRequest* request,
70 const HttpRequestHeaders& headers) OVERRIDE {}
71
OnHeadersReceived(URLRequest * request,const CompletionCallback & callback,const HttpResponseHeaders * original_response_headers,scoped_refptr<HttpResponseHeaders> * override_response_headers,GURL * allowed_unsafe_redirect_url)72 virtual int OnHeadersReceived(
73 URLRequest* request,
74 const CompletionCallback& callback,
75 const HttpResponseHeaders* original_response_headers,
76 scoped_refptr<HttpResponseHeaders>* override_response_headers,
77 GURL* allowed_unsafe_redirect_url) OVERRIDE {
78 return OK;
79 }
80
OnBeforeRedirect(URLRequest * request,const GURL & new_location)81 virtual void OnBeforeRedirect(URLRequest* request,
82 const GURL& new_location) OVERRIDE {}
83
OnResponseStarted(URLRequest * request)84 virtual void OnResponseStarted(URLRequest* request) OVERRIDE {}
85
OnRawBytesRead(const URLRequest & request,int bytes_read)86 virtual void OnRawBytesRead(const URLRequest& request,
87 int bytes_read) OVERRIDE {}
88
OnCompleted(URLRequest * request,bool started)89 virtual void OnCompleted(URLRequest* request, bool started) OVERRIDE {}
90
OnURLRequestDestroyed(URLRequest * request)91 virtual void OnURLRequestDestroyed(URLRequest* request) OVERRIDE {}
92
OnPACScriptError(int line_number,const base::string16 & error)93 virtual void OnPACScriptError(int line_number,
94 const base::string16& error) OVERRIDE {}
95
OnAuthRequired(URLRequest * request,const AuthChallengeInfo & auth_info,const AuthCallback & callback,AuthCredentials * credentials)96 virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired(
97 URLRequest* request,
98 const AuthChallengeInfo& auth_info,
99 const AuthCallback& callback,
100 AuthCredentials* credentials) OVERRIDE {
101 return NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
102 }
103
OnCanGetCookies(const URLRequest & request,const CookieList & cookie_list)104 virtual bool OnCanGetCookies(const URLRequest& request,
105 const CookieList& cookie_list) OVERRIDE {
106 return true;
107 }
108
OnCanSetCookie(const URLRequest & request,const std::string & cookie_line,CookieOptions * options)109 virtual bool OnCanSetCookie(const URLRequest& request,
110 const std::string& cookie_line,
111 CookieOptions* options) OVERRIDE {
112 return true;
113 }
114
OnCanAccessFile(const net::URLRequest & request,const base::FilePath & path) const115 virtual bool OnCanAccessFile(const net::URLRequest& request,
116 const base::FilePath& path) const OVERRIDE {
117 return true;
118 }
119
OnCanThrottleRequest(const URLRequest & request) const120 virtual bool OnCanThrottleRequest(const URLRequest& request) const OVERRIDE {
121 // Returning true will only enable throttling if there's also a
122 // URLRequestThrottlerManager, which there isn't, by default.
123 return true;
124 }
125
OnBeforeSocketStreamConnect(SocketStream * stream,const CompletionCallback & callback)126 virtual int OnBeforeSocketStreamConnect(
127 SocketStream* stream,
128 const CompletionCallback& callback) OVERRIDE {
129 return OK;
130 }
131
132 DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
133 };
134
135 class BasicURLRequestContext : public URLRequestContext {
136 public:
BasicURLRequestContext()137 BasicURLRequestContext()
138 : storage_(this) {}
139
storage()140 URLRequestContextStorage* storage() {
141 return &storage_;
142 }
143
GetCacheThread()144 base::Thread* GetCacheThread() {
145 if (!cache_thread_) {
146 cache_thread_.reset(new base::Thread("Network Cache Thread"));
147 cache_thread_->StartWithOptions(
148 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
149 }
150 return cache_thread_.get();
151 }
152
GetFileThread()153 base::Thread* GetFileThread() {
154 if (!file_thread_) {
155 file_thread_.reset(new base::Thread("Network File Thread"));
156 file_thread_->StartWithOptions(
157 base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
158 }
159 return file_thread_.get();
160 }
161
set_transport_security_persister(scoped_ptr<TransportSecurityPersister> transport_security_persister)162 void set_transport_security_persister(
163 scoped_ptr<TransportSecurityPersister> transport_security_persister) {
164 transport_security_persister = transport_security_persister.Pass();
165 }
166
167 protected:
~BasicURLRequestContext()168 virtual ~BasicURLRequestContext() {
169 AssertNoURLRequests();
170 }
171
172 private:
173 // Threads should be torn down last.
174 scoped_ptr<base::Thread> cache_thread_;
175 scoped_ptr<base::Thread> file_thread_;
176
177 URLRequestContextStorage storage_;
178 scoped_ptr<TransportSecurityPersister> transport_security_persister_;
179
180 DISALLOW_COPY_AND_ASSIGN(BasicURLRequestContext);
181 };
182
183 } // namespace
184
HttpCacheParams()185 URLRequestContextBuilder::HttpCacheParams::HttpCacheParams()
186 : type(IN_MEMORY),
187 max_size(0) {}
~HttpCacheParams()188 URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {}
189
HttpNetworkSessionParams()190 URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
191 : ignore_certificate_errors(false),
192 host_mapping_rules(NULL),
193 testing_fixed_http_port(0),
194 testing_fixed_https_port(0),
195 next_protos(NextProtosDefaults()),
196 use_alternate_protocols(true),
197 enable_quic(false) {
198 }
199
~HttpNetworkSessionParams()200 URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
201 {}
202
SchemeFactory(const std::string & auth_scheme,net::HttpAuthHandlerFactory * auth_handler_factory)203 URLRequestContextBuilder::SchemeFactory::SchemeFactory(
204 const std::string& auth_scheme,
205 net::HttpAuthHandlerFactory* auth_handler_factory)
206 : scheme(auth_scheme), factory(auth_handler_factory) {
207 }
208
~SchemeFactory()209 URLRequestContextBuilder::SchemeFactory::~SchemeFactory() {
210 }
211
URLRequestContextBuilder()212 URLRequestContextBuilder::URLRequestContextBuilder()
213 : data_enabled_(false),
214 #if !defined(DISABLE_FILE_SUPPORT)
215 file_enabled_(false),
216 #endif
217 #if !defined(DISABLE_FTP_SUPPORT)
218 ftp_enabled_(false),
219 #endif
220 http_cache_enabled_(true),
221 throttling_enabled_(false),
222 channel_id_enabled_(true) {
223 }
224
~URLRequestContextBuilder()225 URLRequestContextBuilder::~URLRequestContextBuilder() {}
226
EnableHttpCache(const HttpCacheParams & params)227 void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams& params) {
228 http_cache_enabled_ = true;
229 http_cache_params_ = params;
230 }
231
DisableHttpCache()232 void URLRequestContextBuilder::DisableHttpCache() {
233 http_cache_enabled_ = false;
234 http_cache_params_ = HttpCacheParams();
235 }
236
SetSpdyAndQuicEnabled(bool spdy_enabled,bool quic_enabled)237 void URLRequestContextBuilder::SetSpdyAndQuicEnabled(bool spdy_enabled,
238 bool quic_enabled) {
239 http_network_session_params_.next_protos =
240 NextProtosWithSpdyAndQuic(spdy_enabled, quic_enabled);
241 http_network_session_params_.enable_quic = quic_enabled;
242 }
243
Build()244 URLRequestContext* URLRequestContextBuilder::Build() {
245 BasicURLRequestContext* context = new BasicURLRequestContext;
246 URLRequestContextStorage* storage = context->storage();
247
248 storage->set_http_user_agent_settings(new StaticHttpUserAgentSettings(
249 accept_language_, user_agent_));
250
251 if (!network_delegate_)
252 network_delegate_.reset(new BasicNetworkDelegate);
253 NetworkDelegate* network_delegate = network_delegate_.release();
254 storage->set_network_delegate(network_delegate);
255
256 if (net_log_) {
257 storage->set_net_log(net_log_.release());
258 } else {
259 storage->set_net_log(new net::NetLog);
260 }
261
262 if (!host_resolver_) {
263 host_resolver_ = net::HostResolver::CreateDefaultResolver(
264 context->net_log());
265 }
266 storage->set_host_resolver(host_resolver_.Pass());
267
268 if (!proxy_service_) {
269 // TODO(willchan): Switch to using this code when
270 // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
271 #if defined(OS_LINUX) || defined(OS_ANDROID)
272 ProxyConfigService* proxy_config_service = proxy_config_service_.release();
273 #else
274 ProxyConfigService* proxy_config_service = NULL;
275 if (proxy_config_service_) {
276 proxy_config_service = proxy_config_service_.release();
277 } else {
278 proxy_config_service =
279 ProxyService::CreateSystemProxyConfigService(
280 base::ThreadTaskRunnerHandle::Get().get(),
281 context->GetFileThread()->task_runner());
282 }
283 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
284 proxy_service_.reset(
285 ProxyService::CreateUsingSystemProxyResolver(
286 proxy_config_service,
287 0, // This results in using the default value.
288 context->net_log()));
289 }
290 storage->set_proxy_service(proxy_service_.release());
291
292 storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
293 HttpAuthHandlerRegistryFactory* http_auth_handler_registry_factory =
294 net::HttpAuthHandlerRegistryFactory::CreateDefault(
295 context->host_resolver());
296 for (size_t i = 0; i < extra_http_auth_handlers_.size(); ++i) {
297 http_auth_handler_registry_factory->RegisterSchemeFactory(
298 extra_http_auth_handlers_[i].scheme,
299 extra_http_auth_handlers_[i].factory);
300 }
301 storage->set_http_auth_handler_factory(http_auth_handler_registry_factory);
302 storage->set_cookie_store(new CookieMonster(NULL, NULL));
303
304 if (channel_id_enabled_) {
305 // TODO(mmenke): This always creates a file thread, even when it ends up
306 // not being used. Consider lazily creating the thread.
307 storage->set_channel_id_service(
308 new ChannelIDService(
309 new DefaultChannelIDStore(NULL),
310 context->GetFileThread()->message_loop_proxy()));
311 }
312
313 storage->set_transport_security_state(new net::TransportSecurityState());
314 if (!transport_security_persister_path_.empty()) {
315 context->set_transport_security_persister(
316 make_scoped_ptr<TransportSecurityPersister>(
317 new TransportSecurityPersister(
318 context->transport_security_state(),
319 transport_security_persister_path_,
320 context->GetFileThread()->message_loop_proxy(),
321 false)));
322 }
323
324 storage->set_http_server_properties(
325 scoped_ptr<net::HttpServerProperties>(
326 new net::HttpServerPropertiesImpl()));
327 storage->set_cert_verifier(CertVerifier::CreateDefault());
328
329 if (throttling_enabled_)
330 storage->set_throttler_manager(new URLRequestThrottlerManager());
331
332 net::HttpNetworkSession::Params network_session_params;
333 network_session_params.host_resolver = context->host_resolver();
334 network_session_params.cert_verifier = context->cert_verifier();
335 network_session_params.transport_security_state =
336 context->transport_security_state();
337 network_session_params.proxy_service = context->proxy_service();
338 network_session_params.ssl_config_service =
339 context->ssl_config_service();
340 network_session_params.http_auth_handler_factory =
341 context->http_auth_handler_factory();
342 network_session_params.network_delegate = network_delegate;
343 network_session_params.http_server_properties =
344 context->http_server_properties();
345 network_session_params.net_log = context->net_log();
346
347 network_session_params.ignore_certificate_errors =
348 http_network_session_params_.ignore_certificate_errors;
349 network_session_params.host_mapping_rules =
350 http_network_session_params_.host_mapping_rules;
351 network_session_params.testing_fixed_http_port =
352 http_network_session_params_.testing_fixed_http_port;
353 network_session_params.testing_fixed_https_port =
354 http_network_session_params_.testing_fixed_https_port;
355 network_session_params.use_alternate_protocols =
356 http_network_session_params_.use_alternate_protocols;
357 network_session_params.trusted_spdy_proxy =
358 http_network_session_params_.trusted_spdy_proxy;
359 network_session_params.next_protos = http_network_session_params_.next_protos;
360 network_session_params.enable_quic = http_network_session_params_.enable_quic;
361
362 HttpTransactionFactory* http_transaction_factory = NULL;
363 if (http_cache_enabled_) {
364 network_session_params.channel_id_service =
365 context->channel_id_service();
366 HttpCache::BackendFactory* http_cache_backend = NULL;
367 if (http_cache_params_.type == HttpCacheParams::DISK) {
368 http_cache_backend = new HttpCache::DefaultBackend(
369 DISK_CACHE,
370 net::CACHE_BACKEND_DEFAULT,
371 http_cache_params_.path,
372 http_cache_params_.max_size,
373 context->GetCacheThread()->task_runner());
374 } else {
375 http_cache_backend =
376 HttpCache::DefaultBackend::InMemory(http_cache_params_.max_size);
377 }
378
379 http_transaction_factory = new HttpCache(
380 network_session_params, http_cache_backend);
381 } else {
382 scoped_refptr<net::HttpNetworkSession> network_session(
383 new net::HttpNetworkSession(network_session_params));
384
385 http_transaction_factory = new HttpNetworkLayer(network_session.get());
386 }
387 storage->set_http_transaction_factory(http_transaction_factory);
388
389 URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl;
390 if (data_enabled_)
391 job_factory->SetProtocolHandler("data", new DataProtocolHandler);
392
393 #if !defined(DISABLE_FILE_SUPPORT)
394 if (file_enabled_) {
395 job_factory->SetProtocolHandler(
396 "file",
397 new FileProtocolHandler(context->GetFileThread()->message_loop_proxy()));
398 }
399 #endif // !defined(DISABLE_FILE_SUPPORT)
400
401 #if !defined(DISABLE_FTP_SUPPORT)
402 if (ftp_enabled_) {
403 ftp_transaction_factory_.reset(
404 new FtpNetworkLayer(context->host_resolver()));
405 job_factory->SetProtocolHandler("ftp",
406 new FtpProtocolHandler(ftp_transaction_factory_.get()));
407 }
408 #endif // !defined(DISABLE_FTP_SUPPORT)
409
410 storage->set_job_factory(job_factory);
411
412 // TODO(willchan): Support sdch.
413
414 return context;
415 }
416
417 } // namespace net
418