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.
5 #include "chromecast/shell/browser/url_request_context_factory.h"
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"
38 namespace chromecast
{
43 const char kCookieStoreFile
[] = "Cookies";
47 // Private classes to expose URLRequestContextGetter that call back to the
48 // URLRequestContextFactory to create the URLRequestContext on demand.
50 // The URLRequestContextFactory::URLRequestContextGetter class is used for both
51 // the system and media URLRequestCotnexts.
52 class URLRequestContextFactory::URLRequestContextGetter
53 : public net::URLRequestContextGetter
{
55 URLRequestContextGetter(URLRequestContextFactory
* factory
, bool is_media
)
56 : is_media_(is_media
),
60 virtual net::URLRequestContext
* GetURLRequestContext() OVERRIDE
{
61 if (!request_context_
) {
63 request_context_
.reset(factory_
->CreateMediaRequestContext());
65 request_context_
.reset(factory_
->CreateSystemRequestContext());
66 // Set request context used by NSS for Crl requests.
67 net::SetURLRequestContextForNSSHttpIO(request_context_
.get());
70 return request_context_
.get();
73 virtual scoped_refptr
<base::SingleThreadTaskRunner
>
74 GetNetworkTaskRunner() const OVERRIDE
{
75 return content::BrowserThread::GetMessageLoopProxyForThread(
76 content::BrowserThread::IO
);
80 virtual ~URLRequestContextGetter() {}
83 URLRequestContextFactory
* const factory_
;
84 scoped_ptr
<net::URLRequestContext
> request_context_
;
86 DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter
);
89 // The URLRequestContextFactory::MainURLRequestContextGetter class is used for
90 // the main URLRequestContext.
91 class URLRequestContextFactory::MainURLRequestContextGetter
92 : public net::URLRequestContextGetter
{
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
),
101 request_interceptors_(request_interceptors
.Pass()) {
102 std::swap(protocol_handlers_
, *protocol_handlers
);
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();
111 return request_context_
.get();
114 virtual scoped_refptr
<base::SingleThreadTaskRunner
>
115 GetNetworkTaskRunner() const OVERRIDE
{
116 return content::BrowserThread::GetMessageLoopProxyForThread(
117 content::BrowserThread::IO
);
121 virtual ~MainURLRequestContextGetter() {}
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_
;
129 DISALLOW_COPY_AND_ASSIGN(MainURLRequestContextGetter
);
132 URLRequestContextFactory::URLRequestContextFactory()
133 : system_dependencies_initialized_(false),
134 main_dependencies_initialized_(false),
135 media_dependencies_initialized_(false) {
138 URLRequestContextFactory::~URLRequestContextFactory() {
141 void 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
146 http_user_agent_settings_
.reset(new CastHttpUserAgentSettings());
149 net::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,
157 request_interceptors
.Pass());
158 return main_getter_
.get();
161 net::URLRequestContextGetter
* URLRequestContextFactory::GetMainGetter() {
163 return main_getter_
.get();
166 net::URLRequestContextGetter
* URLRequestContextFactory::GetSystemGetter() {
167 if (!system_getter_
) {
168 system_getter_
= new URLRequestContextGetter(this, false);
170 return system_getter_
.get();
173 net::URLRequestContextGetter
* URLRequestContextFactory::GetMediaGetter() {
174 if (!media_getter_
) {
175 media_getter_
= new URLRequestContextGetter(this, true);
177 return media_getter_
.get();
180 void URLRequestContextFactory::InitializeSystemContextDependencies() {
181 if (system_dependencies_initialized_
)
184 host_resolver_
= net::HostResolver::CreateDefaultResolver(NULL
);
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)));
193 cert_verifier_
.reset(net::CertVerifier::CreateDefault());
195 ssl_config_service_
= new net::SSLConfigServiceDefaults
;
197 transport_security_state_
.reset(new net::TransportSecurityState());
198 http_auth_handler_factory_
.reset(
199 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_
.get()));
201 http_server_properties_
.reset(new net::HttpServerPropertiesImpl
);
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)),
211 system_dependencies_initialized_
= true;
214 void URLRequestContextFactory::InitializeMainContextDependencies(
215 net::HttpTransactionFactory
* transaction_factory
,
216 content::ProtocolHandlerMap
* protocol_handlers
,
217 content::URLRequestInterceptorScopedVector request_interceptors
) {
218 if (main_dependencies_initialized_
)
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();
230 set_protocol
= job_factory
->SetProtocolHandler(
231 it
->first
, it
->second
.release());
232 DCHECK(set_protocol
);
234 set_protocol
= job_factory
->SetProtocolHandler(
236 new net::DataProtocolHandler
);
237 DCHECK(set_protocol
);
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();
246 top_job_factory
.reset(new net::URLRequestInterceptingJobFactory(
247 top_job_factory
.Pass(), make_scoped_ptr(*i
)));
249 request_interceptors
.weak_clear();
251 main_job_factory_
.reset(top_job_factory
.release());
253 main_dependencies_initialized_
= true;
256 void URLRequestContextFactory::InitializeMediaContextDependencies(
257 net::HttpTransactionFactory
* transaction_factory
) {
258 if (media_dependencies_initialized_
)
261 media_transaction_factory_
.reset(transaction_factory
);
262 media_dependencies_initialized_
= true;
265 void 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();
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;
284 net::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
)));
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
;
313 net::URLRequestContext
* URLRequestContextFactory::CreateMediaRequestContext() {
314 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
316 << "Getting MediaRequestContext before MainRequestContext";
317 net::URLRequestContext
* main_context
= main_getter_
->GetURLRequestContext();
319 // Set non caching backend.
320 net::HttpNetworkSession
* main_session
=
321 main_transaction_factory_
->GetSession();
322 InitializeMediaContextDependencies(
323 new net::HttpNetworkLayer(main_session
));
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
;
332 net::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();
339 net::HttpCache::BackendFactory
* main_backend
=
340 net::HttpCache::DefaultBackend::InMemory(16 * 1024 * 1024);
342 bool ignore_certificate_errors
= false;
343 CommandLine
* cmd_line
= CommandLine::ForCurrentProcess();
344 if (cmd_line
->HasSwitch(switches::kIgnoreCertificateErrors
)) {
345 ignore_certificate_errors
= true;
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
),
353 request_interceptors
.Pass());
355 content::CookieStoreConfig
cookie_config(
356 browser_context
->GetPath().Append(kCookieStoreFile
),
357 content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES
,
359 cookie_config
.background_task_runner
=
360 scoped_refptr
<base::SequencedTaskRunner
>();
361 scoped_refptr
<net::CookieStore
> cookie_store
=
362 content::CreateCookieStore(cookie_config
);
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());
379 main_context
->set_http_transaction_factory(
380 main_transaction_factory_
.get());
381 main_context
->set_job_factory(main_job_factory_
.get());
386 } // namespace chromecast