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 47namespace net { 48 49namespace { 50 51class BasicNetworkDelegate : public NetworkDelegate { 52 public: 53 BasicNetworkDelegate() {} 54 virtual ~BasicNetworkDelegate() {} 55 56 private: 57 virtual int OnBeforeURLRequest(URLRequest* request, 58 const CompletionCallback& callback, 59 GURL* new_url) OVERRIDE { 60 return OK; 61 } 62 63 virtual int OnBeforeSendHeaders(URLRequest* request, 64 const CompletionCallback& callback, 65 HttpRequestHeaders* headers) OVERRIDE { 66 return OK; 67 } 68 69 virtual void OnSendHeaders(URLRequest* request, 70 const HttpRequestHeaders& headers) OVERRIDE {} 71 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 81 virtual void OnBeforeRedirect(URLRequest* request, 82 const GURL& new_location) OVERRIDE {} 83 84 virtual void OnResponseStarted(URLRequest* request) OVERRIDE {} 85 86 virtual void OnRawBytesRead(const URLRequest& request, 87 int bytes_read) OVERRIDE {} 88 89 virtual void OnCompleted(URLRequest* request, bool started) OVERRIDE {} 90 91 virtual void OnURLRequestDestroyed(URLRequest* request) OVERRIDE {} 92 93 virtual void OnPACScriptError(int line_number, 94 const base::string16& error) OVERRIDE {} 95 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 104 virtual bool OnCanGetCookies(const URLRequest& request, 105 const CookieList& cookie_list) OVERRIDE { 106 return true; 107 } 108 109 virtual bool OnCanSetCookie(const URLRequest& request, 110 const std::string& cookie_line, 111 CookieOptions* options) OVERRIDE { 112 return true; 113 } 114 115 virtual bool OnCanAccessFile(const net::URLRequest& request, 116 const base::FilePath& path) const OVERRIDE { 117 return true; 118 } 119 120 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 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 135class BasicURLRequestContext : public URLRequestContext { 136 public: 137 BasicURLRequestContext() 138 : storage_(this) {} 139 140 URLRequestContextStorage* storage() { 141 return &storage_; 142 } 143 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 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 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: 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 185URLRequestContextBuilder::HttpCacheParams::HttpCacheParams() 186 : type(IN_MEMORY), 187 max_size(0) {} 188URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {} 189 190URLRequestContextBuilder::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 200URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams() 201{} 202 203URLRequestContextBuilder::SchemeFactory::SchemeFactory( 204 const std::string& auth_scheme, 205 net::HttpAuthHandlerFactory* auth_handler_factory) 206 : scheme(auth_scheme), factory(auth_handler_factory) { 207} 208 209URLRequestContextBuilder::SchemeFactory::~SchemeFactory() { 210} 211 212URLRequestContextBuilder::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 225URLRequestContextBuilder::~URLRequestContextBuilder() {} 226 227void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams& params) { 228 http_cache_enabled_ = true; 229 http_cache_params_ = params; 230} 231 232void URLRequestContextBuilder::DisableHttpCache() { 233 http_cache_enabled_ = false; 234 http_cache_params_ = HttpCacheParams(); 235} 236 237void 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 244URLRequestContext* 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