url_request_context_factory.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright 2014 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 "chromecast/shell/browser/url_request_context_factory.h" 6 7#include "base/command_line.h" 8#include "base/files/file_path.h" 9#include "base/macros.h" 10#include "base/path_service.h" 11#include "base/threading/worker_pool.h" 12#include "chromecast/shell/browser/cast_http_user_agent_settings.h" 13#include "content/public/browser/browser_context.h" 14#include "content/public/browser/browser_thread.h" 15#include "content/public/browser/cookie_store_factory.h" 16#include "content/public/common/content_switches.h" 17#include "content/public/common/url_constants.h" 18#include "net/cert/cert_verifier.h" 19#include "net/cookies/cookie_store.h" 20#include "net/dns/host_resolver.h" 21#include "net/http/http_auth_handler_factory.h" 22#include "net/http/http_cache.h" 23#include "net/http/http_network_layer.h" 24#include "net/http/http_server_properties_impl.h" 25#include "net/http/http_stream_factory.h" 26#include "net/ocsp/nss_ocsp.h" 27#include "net/proxy/proxy_service.h" 28#include "net/socket/next_proto.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/url_request_context.h" 34#include "net/url_request/url_request_context_getter.h" 35#include "net/url_request/url_request_intercepting_job_factory.h" 36#include "net/url_request/url_request_job_factory_impl.h" 37 38namespace chromecast { 39namespace shell { 40 41namespace { 42 43const char kCookieStoreFile[] = "Cookies"; 44 45} // namespace 46 47// Private classes to expose URLRequestContextGetter that call back to the 48// URLRequestContextFactory to create the URLRequestContext on demand. 49// 50// The URLRequestContextFactory::URLRequestContextGetter class is used for both 51// the system and media URLRequestCotnexts. 52class URLRequestContextFactory::URLRequestContextGetter 53 : public net::URLRequestContextGetter { 54 public: 55 URLRequestContextGetter(URLRequestContextFactory* factory, bool is_media) 56 : is_media_(is_media), 57 factory_(factory) { 58 } 59 60 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { 61 if (!request_context_) { 62 if (is_media_) { 63 request_context_.reset(factory_->CreateMediaRequestContext()); 64 } else { 65 request_context_.reset(factory_->CreateSystemRequestContext()); 66 // Set request context used by NSS for Crl requests. 67 net::SetURLRequestContextForNSSHttpIO(request_context_.get()); 68 } 69 } 70 return request_context_.get(); 71 } 72 73 virtual scoped_refptr<base::SingleThreadTaskRunner> 74 GetNetworkTaskRunner() const OVERRIDE { 75 return content::BrowserThread::GetMessageLoopProxyForThread( 76 content::BrowserThread::IO); 77 } 78 79 private: 80 virtual ~URLRequestContextGetter() {} 81 82 const bool is_media_; 83 URLRequestContextFactory* const factory_; 84 scoped_ptr<net::URLRequestContext> request_context_; 85 86 DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter); 87}; 88 89// The URLRequestContextFactory::MainURLRequestContextGetter class is used for 90// the main URLRequestContext. 91class URLRequestContextFactory::MainURLRequestContextGetter 92 : public net::URLRequestContextGetter { 93 public: 94 MainURLRequestContextGetter( 95 URLRequestContextFactory* factory, 96 content::BrowserContext* browser_context, 97 content::ProtocolHandlerMap* protocol_handlers, 98 content::URLRequestInterceptorScopedVector request_interceptors) 99 : browser_context_(browser_context), 100 factory_(factory), 101 request_interceptors_(request_interceptors.Pass()) { 102 std::swap(protocol_handlers_, *protocol_handlers); 103 } 104 105 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { 106 if (!request_context_) { 107 request_context_.reset(factory_->CreateMainRequestContext( 108 browser_context_, &protocol_handlers_, request_interceptors_.Pass())); 109 protocol_handlers_.clear(); 110 } 111 return request_context_.get(); 112 } 113 114 virtual scoped_refptr<base::SingleThreadTaskRunner> 115 GetNetworkTaskRunner() const OVERRIDE { 116 return content::BrowserThread::GetMessageLoopProxyForThread( 117 content::BrowserThread::IO); 118 } 119 120 private: 121 virtual ~MainURLRequestContextGetter() {} 122 123 content::BrowserContext* const browser_context_; 124 URLRequestContextFactory* const factory_; 125 content::ProtocolHandlerMap protocol_handlers_; 126 content::URLRequestInterceptorScopedVector request_interceptors_; 127 scoped_ptr<net::URLRequestContext> request_context_; 128 129 DISALLOW_COPY_AND_ASSIGN(MainURLRequestContextGetter); 130}; 131 132URLRequestContextFactory::URLRequestContextFactory() 133 : system_dependencies_initialized_(false), 134 main_dependencies_initialized_(false), 135 media_dependencies_initialized_(false) { 136} 137 138URLRequestContextFactory::~URLRequestContextFactory() { 139} 140 141void URLRequestContextFactory::InitializeOnUIThread() { 142 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 143 // Cast http user agent settings must be initialized in UI thread 144 // because it registers itself to pref notification observer which is not 145 // thread safe. 146 http_user_agent_settings_.reset(new CastHttpUserAgentSettings()); 147} 148 149net::URLRequestContextGetter* URLRequestContextFactory::CreateMainGetter( 150 content::BrowserContext* browser_context, 151 content::ProtocolHandlerMap* protocol_handlers, 152 content::URLRequestInterceptorScopedVector request_interceptors) { 153 DCHECK(!main_getter_) << "Main URLRequestContextGetter already initialized"; 154 main_getter_ = new MainURLRequestContextGetter(this, 155 browser_context, 156 protocol_handlers, 157 request_interceptors.Pass()); 158 return main_getter_.get(); 159} 160 161net::URLRequestContextGetter* URLRequestContextFactory::GetMainGetter() { 162 CHECK(main_getter_); 163 return main_getter_.get(); 164} 165 166net::URLRequestContextGetter* URLRequestContextFactory::GetSystemGetter() { 167 if (!system_getter_) { 168 system_getter_ = new URLRequestContextGetter(this, false); 169 } 170 return system_getter_.get(); 171} 172 173net::URLRequestContextGetter* URLRequestContextFactory::GetMediaGetter() { 174 if (!media_getter_) { 175 media_getter_ = new URLRequestContextGetter(this, true); 176 } 177 return media_getter_.get(); 178} 179 180void URLRequestContextFactory::InitializeSystemContextDependencies() { 181 if (system_dependencies_initialized_) 182 return; 183 184 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); 185 186 // TODO(lcwu): http://crbug.com/392352. For performance and security reasons, 187 // a persistent (on-disk) HttpServerProperties and ChannelIDService might be 188 // desirable in the future. 189 channel_id_service_.reset( 190 new net::ChannelIDService(new net::DefaultChannelIDStore(NULL), 191 base::WorkerPool::GetTaskRunner(true))); 192 193 cert_verifier_.reset(net::CertVerifier::CreateDefault()); 194 195 ssl_config_service_ = new net::SSLConfigServiceDefaults; 196 197 transport_security_state_.reset(new net::TransportSecurityState()); 198 http_auth_handler_factory_.reset( 199 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_.get())); 200 201 http_server_properties_.reset(new net::HttpServerPropertiesImpl); 202 203 proxy_service_.reset(net::ProxyService::CreateUsingSystemProxyResolver( 204 net::ProxyService::CreateSystemProxyConfigService( 205 content::BrowserThread::GetMessageLoopProxyForThread( 206 content::BrowserThread::IO).get(), 207 content::BrowserThread::UnsafeGetMessageLoopForThread( 208 content::BrowserThread::FILE)), 209 0, 210 NULL)); 211 system_dependencies_initialized_ = true; 212} 213 214void URLRequestContextFactory::InitializeMainContextDependencies( 215 net::HttpTransactionFactory* transaction_factory, 216 content::ProtocolHandlerMap* protocol_handlers, 217 content::URLRequestInterceptorScopedVector request_interceptors) { 218 if (main_dependencies_initialized_) 219 return; 220 221 main_transaction_factory_.reset(transaction_factory); 222 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 223 new net::URLRequestJobFactoryImpl()); 224 // Keep ProtocolHandlers added in sync with 225 // CastContentBrowserClient::IsHandledURL(). 226 bool set_protocol = false; 227 for (content::ProtocolHandlerMap::iterator it = protocol_handlers->begin(); 228 it != protocol_handlers->end(); 229 ++it) { 230 set_protocol = job_factory->SetProtocolHandler( 231 it->first, it->second.release()); 232 DCHECK(set_protocol); 233 } 234 set_protocol = job_factory->SetProtocolHandler( 235 url::kDataScheme, 236 new net::DataProtocolHandler); 237 DCHECK(set_protocol); 238 239 // Set up interceptors in the reverse order. 240 scoped_ptr<net::URLRequestJobFactory> top_job_factory = 241 job_factory.PassAs<net::URLRequestJobFactory>(); 242 for (content::URLRequestInterceptorScopedVector::reverse_iterator i = 243 request_interceptors.rbegin(); 244 i != request_interceptors.rend(); 245 ++i) { 246 top_job_factory.reset(new net::URLRequestInterceptingJobFactory( 247 top_job_factory.Pass(), make_scoped_ptr(*i))); 248 } 249 request_interceptors.weak_clear(); 250 251 main_job_factory_.reset(top_job_factory.release()); 252 253 main_dependencies_initialized_ = true; 254} 255 256void URLRequestContextFactory::InitializeMediaContextDependencies( 257 net::HttpTransactionFactory* transaction_factory) { 258 if (media_dependencies_initialized_) 259 return; 260 261 media_transaction_factory_.reset(transaction_factory); 262 media_dependencies_initialized_ = true; 263} 264 265void URLRequestContextFactory::PopulateNetworkSessionParams( 266 bool ignore_certificate_errors, 267 net::HttpNetworkSession::Params* params) { 268 params->host_resolver = host_resolver_.get(); 269 params->cert_verifier = cert_verifier_.get(); 270 params->channel_id_service = channel_id_service_.get(); 271 params->ssl_config_service = ssl_config_service_.get(); 272 params->transport_security_state = transport_security_state_.get(); 273 params->http_auth_handler_factory = http_auth_handler_factory_.get(); 274 params->http_server_properties = http_server_properties_->GetWeakPtr(); 275 params->ignore_certificate_errors = ignore_certificate_errors; 276 params->proxy_service = proxy_service_.get(); 277 278 // TODO(lcwu): http://crbug.com/329681. Remove this once spdy is enabled 279 // by default at the content level. 280 params->next_protos = net::NextProtosSpdy31(); 281 params->use_alternate_protocols = true; 282} 283 284net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() { 285 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 286 InitializeSystemContextDependencies(); 287 net::HttpNetworkSession::Params system_params; 288 PopulateNetworkSessionParams(false, &system_params); 289 system_transaction_factory_.reset(new net::HttpNetworkLayer( 290 new net::HttpNetworkSession(system_params))); 291 292 net::URLRequestContext* system_context = new net::URLRequestContext(); 293 system_context->set_host_resolver(host_resolver_.get()); 294 system_context->set_channel_id_service(channel_id_service_.get()); 295 system_context->set_cert_verifier(cert_verifier_.get()); 296 system_context->set_proxy_service(proxy_service_.get()); 297 system_context->set_ssl_config_service(ssl_config_service_.get()); 298 system_context->set_transport_security_state( 299 transport_security_state_.get()); 300 system_context->set_http_auth_handler_factory( 301 http_auth_handler_factory_.get()); 302 system_context->set_http_server_properties( 303 http_server_properties_->GetWeakPtr()); 304 system_context->set_http_transaction_factory( 305 system_transaction_factory_.get()); 306 system_context->set_http_user_agent_settings( 307 http_user_agent_settings_.get()); 308 system_context->set_cookie_store( 309 content::CreateCookieStore(content::CookieStoreConfig())); 310 return system_context; 311} 312 313net::URLRequestContext* URLRequestContextFactory::CreateMediaRequestContext() { 314 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 315 DCHECK(main_getter_) 316 << "Getting MediaRequestContext before MainRequestContext"; 317 net::URLRequestContext* main_context = main_getter_->GetURLRequestContext(); 318 319 // Set non caching backend. 320 net::HttpNetworkSession* main_session = 321 main_transaction_factory_->GetSession(); 322 InitializeMediaContextDependencies( 323 new net::HttpNetworkLayer(main_session)); 324 325 net::URLRequestContext* media_context = new net::URLRequestContext(); 326 media_context->CopyFrom(main_context); 327 media_context->set_http_transaction_factory( 328 media_transaction_factory_.get()); 329 return media_context; 330} 331 332net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext( 333 content::BrowserContext* browser_context, 334 content::ProtocolHandlerMap* protocol_handlers, 335 content::URLRequestInterceptorScopedVector request_interceptors) { 336 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 337 InitializeSystemContextDependencies(); 338 339 net::HttpCache::BackendFactory* main_backend = 340 net::HttpCache::DefaultBackend::InMemory(16 * 1024 * 1024); 341 342 bool ignore_certificate_errors = false; 343 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 344 if (cmd_line->HasSwitch(switches::kIgnoreCertificateErrors)) { 345 ignore_certificate_errors = true; 346 } 347 net::HttpNetworkSession::Params network_session_params; 348 PopulateNetworkSessionParams(ignore_certificate_errors, 349 &network_session_params); 350 InitializeMainContextDependencies( 351 new net::HttpCache(network_session_params, main_backend), 352 protocol_handlers, 353 request_interceptors.Pass()); 354 355 content::CookieStoreConfig cookie_config( 356 browser_context->GetPath().Append(kCookieStoreFile), 357 content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, 358 NULL, NULL); 359 cookie_config.background_task_runner = 360 scoped_refptr<base::SequencedTaskRunner>(); 361 scoped_refptr<net::CookieStore> cookie_store = 362 content::CreateCookieStore(cookie_config); 363 364 net::URLRequestContext* main_context = new net::URLRequestContext(); 365 main_context->set_host_resolver(host_resolver_.get()); 366 main_context->set_channel_id_service(channel_id_service_.get()); 367 main_context->set_cert_verifier(cert_verifier_.get()); 368 main_context->set_proxy_service(proxy_service_.get()); 369 main_context->set_ssl_config_service(ssl_config_service_.get()); 370 main_context->set_transport_security_state(transport_security_state_.get()); 371 main_context->set_http_auth_handler_factory( 372 http_auth_handler_factory_.get()); 373 main_context->set_http_server_properties( 374 http_server_properties_->GetWeakPtr()); 375 main_context->set_cookie_store(cookie_store.get()); 376 main_context->set_http_user_agent_settings( 377 http_user_agent_settings_.get()); 378 379 main_context->set_http_transaction_factory( 380 main_transaction_factory_.get()); 381 main_context->set_job_factory(main_job_factory_.get()); 382 return main_context; 383} 384 385} // namespace shell 386} // namespace chromecast 387