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/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/browser/cast_http_user_agent_settings.h"
13 #include "chromecast/browser/cast_network_delegate.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/cookie_store_factory.h"
17 #include "content/public/common/content_switches.h"
18 #include "content/public/common/url_constants.h"
19 #include "net/cert/cert_verifier.h"
20 #include "net/cookies/cookie_store.h"
21 #include "net/dns/host_resolver.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_server_properties_impl.h"
26 #include "net/http/http_stream_factory.h"
27 #include "net/ocsp/nss_ocsp.h"
28 #include "net/proxy/proxy_service.h"
29 #include "net/socket/next_proto.h"
30 #include "net/ssl/channel_id_service.h"
31 #include "net/ssl/default_channel_id_store.h"
32 #include "net/ssl/ssl_config_service_defaults.h"
33 #include "net/url_request/data_protocol_handler.h"
34 #include "net/url_request/file_protocol_handler.h"
35 #include "net/url_request/url_request_context.h"
36 #include "net/url_request/url_request_context_getter.h"
37 #include "net/url_request/url_request_intercepting_job_factory.h"
38 #include "net/url_request/url_request_job_factory_impl.h"
40 namespace chromecast
{
45 const char kCookieStoreFile
[] = "Cookies";
49 // Private classes to expose URLRequestContextGetter that call back to the
50 // URLRequestContextFactory to create the URLRequestContext on demand.
52 // The URLRequestContextFactory::URLRequestContextGetter class is used for both
53 // the system and media URLRequestCotnexts.
54 class URLRequestContextFactory::URLRequestContextGetter
55 : public net::URLRequestContextGetter
{
57 URLRequestContextGetter(URLRequestContextFactory
* factory
, bool is_media
)
58 : is_media_(is_media
),
62 virtual net::URLRequestContext
* GetURLRequestContext() override
{
63 if (!request_context_
) {
65 request_context_
.reset(factory_
->CreateMediaRequestContext());
67 request_context_
.reset(factory_
->CreateSystemRequestContext());
69 // Set request context used by NSS for Crl requests.
70 net::SetURLRequestContextForNSSHttpIO(request_context_
.get());
71 #endif // defined(USE_NSS)
74 return request_context_
.get();
77 virtual scoped_refptr
<base::SingleThreadTaskRunner
>
78 GetNetworkTaskRunner() const override
{
79 return content::BrowserThread::GetMessageLoopProxyForThread(
80 content::BrowserThread::IO
);
84 virtual ~URLRequestContextGetter() {}
87 URLRequestContextFactory
* const factory_
;
88 scoped_ptr
<net::URLRequestContext
> request_context_
;
90 DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter
);
93 // The URLRequestContextFactory::MainURLRequestContextGetter class is used for
94 // the main URLRequestContext.
95 class URLRequestContextFactory::MainURLRequestContextGetter
96 : public net::URLRequestContextGetter
{
98 MainURLRequestContextGetter(
99 URLRequestContextFactory
* factory
,
100 content::BrowserContext
* browser_context
,
101 content::ProtocolHandlerMap
* protocol_handlers
,
102 content::URLRequestInterceptorScopedVector request_interceptors
)
103 : browser_context_(browser_context
),
105 request_interceptors_(request_interceptors
.Pass()) {
106 std::swap(protocol_handlers_
, *protocol_handlers
);
109 virtual net::URLRequestContext
* GetURLRequestContext() override
{
110 if (!request_context_
) {
111 request_context_
.reset(factory_
->CreateMainRequestContext(
112 browser_context_
, &protocol_handlers_
, request_interceptors_
.Pass()));
113 protocol_handlers_
.clear();
115 return request_context_
.get();
118 virtual scoped_refptr
<base::SingleThreadTaskRunner
>
119 GetNetworkTaskRunner() const override
{
120 return content::BrowserThread::GetMessageLoopProxyForThread(
121 content::BrowserThread::IO
);
125 virtual ~MainURLRequestContextGetter() {}
127 content::BrowserContext
* const browser_context_
;
128 URLRequestContextFactory
* const factory_
;
129 content::ProtocolHandlerMap protocol_handlers_
;
130 content::URLRequestInterceptorScopedVector request_interceptors_
;
131 scoped_ptr
<net::URLRequestContext
> request_context_
;
133 DISALLOW_COPY_AND_ASSIGN(MainURLRequestContextGetter
);
136 URLRequestContextFactory::URLRequestContextFactory()
137 : app_network_delegate_(CastNetworkDelegate::Create()),
138 system_network_delegate_(CastNetworkDelegate::Create()),
139 system_dependencies_initialized_(false),
140 main_dependencies_initialized_(false),
141 media_dependencies_initialized_(false) {
144 URLRequestContextFactory::~URLRequestContextFactory() {
147 void URLRequestContextFactory::InitializeOnUIThread() {
148 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
149 // Cast http user agent settings must be initialized in UI thread
150 // because it registers itself to pref notification observer which is not
152 http_user_agent_settings_
.reset(new CastHttpUserAgentSettings());
154 // Proxy config service should be initialized in UI thread, since
155 // ProxyConfigServiceDelegate on Android expects UI thread.
156 proxy_config_service_
.reset(net::ProxyService::CreateSystemProxyConfigService(
157 content::BrowserThread::GetMessageLoopProxyForThread(
158 content::BrowserThread::IO
),
159 content::BrowserThread::GetMessageLoopProxyForThread(
160 content::BrowserThread::FILE)));
163 net::URLRequestContextGetter
* URLRequestContextFactory::CreateMainGetter(
164 content::BrowserContext
* browser_context
,
165 content::ProtocolHandlerMap
* protocol_handlers
,
166 content::URLRequestInterceptorScopedVector request_interceptors
) {
167 DCHECK(!main_getter_
.get())
168 << "Main URLRequestContextGetter already initialized";
169 main_getter_
= new MainURLRequestContextGetter(this,
172 request_interceptors
.Pass());
173 return main_getter_
.get();
176 net::URLRequestContextGetter
* URLRequestContextFactory::GetMainGetter() {
177 CHECK(main_getter_
.get());
178 return main_getter_
.get();
181 net::URLRequestContextGetter
* URLRequestContextFactory::GetSystemGetter() {
182 if (!system_getter_
.get()) {
183 system_getter_
= new URLRequestContextGetter(this, false);
185 return system_getter_
.get();
188 net::URLRequestContextGetter
* URLRequestContextFactory::GetMediaGetter() {
189 if (!media_getter_
.get()) {
190 media_getter_
= new URLRequestContextGetter(this, true);
192 return media_getter_
.get();
195 void URLRequestContextFactory::InitializeSystemContextDependencies() {
196 if (system_dependencies_initialized_
)
199 host_resolver_
= net::HostResolver::CreateDefaultResolver(NULL
);
201 // TODO(lcwu): http://crbug.com/392352. For performance and security reasons,
202 // a persistent (on-disk) HttpServerProperties and ChannelIDService might be
203 // desirable in the future.
204 channel_id_service_
.reset(
205 new net::ChannelIDService(new net::DefaultChannelIDStore(NULL
),
206 base::WorkerPool::GetTaskRunner(true)));
208 cert_verifier_
.reset(net::CertVerifier::CreateDefault());
210 ssl_config_service_
= new net::SSLConfigServiceDefaults
;
212 transport_security_state_
.reset(new net::TransportSecurityState());
213 http_auth_handler_factory_
.reset(
214 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_
.get()));
216 http_server_properties_
.reset(new net::HttpServerPropertiesImpl
);
218 proxy_service_
.reset(net::ProxyService::CreateUsingSystemProxyResolver(
219 proxy_config_service_
.release(), 0, NULL
));
220 system_dependencies_initialized_
= true;
223 void URLRequestContextFactory::InitializeMainContextDependencies(
224 net::HttpTransactionFactory
* transaction_factory
,
225 content::ProtocolHandlerMap
* protocol_handlers
,
226 content::URLRequestInterceptorScopedVector request_interceptors
) {
227 if (main_dependencies_initialized_
)
230 main_transaction_factory_
.reset(transaction_factory
);
231 scoped_ptr
<net::URLRequestJobFactoryImpl
> job_factory(
232 new net::URLRequestJobFactoryImpl());
233 // Keep ProtocolHandlers added in sync with
234 // CastContentBrowserClient::IsHandledURL().
235 bool set_protocol
= false;
236 for (content::ProtocolHandlerMap::iterator it
= protocol_handlers
->begin();
237 it
!= protocol_handlers
->end();
239 set_protocol
= job_factory
->SetProtocolHandler(
240 it
->first
, it
->second
.release());
241 DCHECK(set_protocol
);
243 set_protocol
= job_factory
->SetProtocolHandler(
245 new net::DataProtocolHandler
);
246 DCHECK(set_protocol
);
247 #if defined(OS_ANDROID)
248 set_protocol
= job_factory
->SetProtocolHandler(
250 new net::FileProtocolHandler(
251 content::BrowserThread::GetBlockingPool()->
252 GetTaskRunnerWithShutdownBehavior(
253 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
)));
254 DCHECK(set_protocol
);
255 #endif // defined(OS_ANDROID)
257 // Set up interceptors in the reverse order.
258 scoped_ptr
<net::URLRequestJobFactory
> top_job_factory
=
259 job_factory
.PassAs
<net::URLRequestJobFactory
>();
260 for (content::URLRequestInterceptorScopedVector::reverse_iterator i
=
261 request_interceptors
.rbegin();
262 i
!= request_interceptors
.rend();
264 top_job_factory
.reset(new net::URLRequestInterceptingJobFactory(
265 top_job_factory
.Pass(), make_scoped_ptr(*i
)));
267 request_interceptors
.weak_clear();
269 main_job_factory_
.reset(top_job_factory
.release());
271 main_dependencies_initialized_
= true;
274 void URLRequestContextFactory::InitializeMediaContextDependencies(
275 net::HttpTransactionFactory
* transaction_factory
) {
276 if (media_dependencies_initialized_
)
279 media_transaction_factory_
.reset(transaction_factory
);
280 media_dependencies_initialized_
= true;
283 void URLRequestContextFactory::PopulateNetworkSessionParams(
284 bool ignore_certificate_errors
,
285 net::HttpNetworkSession::Params
* params
) {
286 params
->host_resolver
= host_resolver_
.get();
287 params
->cert_verifier
= cert_verifier_
.get();
288 params
->channel_id_service
= channel_id_service_
.get();
289 params
->ssl_config_service
= ssl_config_service_
.get();
290 params
->transport_security_state
= transport_security_state_
.get();
291 params
->http_auth_handler_factory
= http_auth_handler_factory_
.get();
292 params
->http_server_properties
= http_server_properties_
->GetWeakPtr();
293 params
->ignore_certificate_errors
= ignore_certificate_errors
;
294 params
->proxy_service
= proxy_service_
.get();
296 // TODO(lcwu): http://crbug.com/329681. Remove this once spdy is enabled
297 // by default at the content level.
298 params
->next_protos
= net::NextProtosSpdy31();
299 params
->use_alternate_protocols
= true;
302 net::URLRequestContext
* URLRequestContextFactory::CreateSystemRequestContext() {
303 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
304 InitializeSystemContextDependencies();
305 net::HttpNetworkSession::Params system_params
;
306 PopulateNetworkSessionParams(false, &system_params
);
307 system_transaction_factory_
.reset(new net::HttpNetworkLayer(
308 new net::HttpNetworkSession(system_params
)));
309 system_job_factory_
.reset(new net::URLRequestJobFactoryImpl());
311 net::URLRequestContext
* system_context
= new net::URLRequestContext();
312 system_context
->set_host_resolver(host_resolver_
.get());
313 system_context
->set_channel_id_service(channel_id_service_
.get());
314 system_context
->set_cert_verifier(cert_verifier_
.get());
315 system_context
->set_proxy_service(proxy_service_
.get());
316 system_context
->set_ssl_config_service(ssl_config_service_
.get());
317 system_context
->set_transport_security_state(
318 transport_security_state_
.get());
319 system_context
->set_http_auth_handler_factory(
320 http_auth_handler_factory_
.get());
321 system_context
->set_http_server_properties(
322 http_server_properties_
->GetWeakPtr());
323 system_context
->set_http_transaction_factory(
324 system_transaction_factory_
.get());
325 system_context
->set_http_user_agent_settings(
326 http_user_agent_settings_
.get());
327 system_context
->set_job_factory(system_job_factory_
.get());
328 system_context
->set_cookie_store(
329 content::CreateCookieStore(content::CookieStoreConfig()));
330 system_context
->set_network_delegate(system_network_delegate_
.get());
331 return system_context
;
334 net::URLRequestContext
* URLRequestContextFactory::CreateMediaRequestContext() {
335 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
336 DCHECK(main_getter_
.get())
337 << "Getting MediaRequestContext before MainRequestContext";
338 net::URLRequestContext
* main_context
= main_getter_
->GetURLRequestContext();
340 // Set non caching backend.
341 net::HttpNetworkSession
* main_session
=
342 main_transaction_factory_
->GetSession();
343 InitializeMediaContextDependencies(
344 new net::HttpNetworkLayer(main_session
));
346 net::URLRequestContext
* media_context
= new net::URLRequestContext();
347 media_context
->CopyFrom(main_context
);
348 media_context
->set_http_transaction_factory(
349 media_transaction_factory_
.get());
350 return media_context
;
353 net::URLRequestContext
* URLRequestContextFactory::CreateMainRequestContext(
354 content::BrowserContext
* browser_context
,
355 content::ProtocolHandlerMap
* protocol_handlers
,
356 content::URLRequestInterceptorScopedVector request_interceptors
) {
357 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
358 InitializeSystemContextDependencies();
360 net::HttpCache::BackendFactory
* main_backend
=
361 net::HttpCache::DefaultBackend::InMemory(16 * 1024 * 1024);
363 bool ignore_certificate_errors
= false;
364 CommandLine
* cmd_line
= CommandLine::ForCurrentProcess();
365 if (cmd_line
->HasSwitch(switches::kIgnoreCertificateErrors
)) {
366 ignore_certificate_errors
= true;
368 net::HttpNetworkSession::Params network_session_params
;
369 PopulateNetworkSessionParams(ignore_certificate_errors
,
370 &network_session_params
);
371 InitializeMainContextDependencies(
372 new net::HttpCache(network_session_params
, main_backend
),
374 request_interceptors
.Pass());
376 content::CookieStoreConfig
cookie_config(
377 browser_context
->GetPath().Append(kCookieStoreFile
),
378 content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES
,
380 cookie_config
.background_task_runner
=
381 scoped_refptr
<base::SequencedTaskRunner
>();
382 scoped_refptr
<net::CookieStore
> cookie_store
=
383 content::CreateCookieStore(cookie_config
);
385 net::URLRequestContext
* main_context
= new net::URLRequestContext();
386 main_context
->set_host_resolver(host_resolver_
.get());
387 main_context
->set_channel_id_service(channel_id_service_
.get());
388 main_context
->set_cert_verifier(cert_verifier_
.get());
389 main_context
->set_proxy_service(proxy_service_
.get());
390 main_context
->set_ssl_config_service(ssl_config_service_
.get());
391 main_context
->set_transport_security_state(transport_security_state_
.get());
392 main_context
->set_http_auth_handler_factory(
393 http_auth_handler_factory_
.get());
394 main_context
->set_http_server_properties(
395 http_server_properties_
->GetWeakPtr());
396 main_context
->set_cookie_store(cookie_store
.get());
397 main_context
->set_http_user_agent_settings(
398 http_user_agent_settings_
.get());
400 main_context
->set_http_transaction_factory(
401 main_transaction_factory_
.get());
402 main_context
->set_job_factory(main_job_factory_
.get());
403 main_context
->set_network_delegate(app_network_delegate_
.get());
407 void URLRequestContextFactory::InitializeNetworkDelegates() {
408 app_network_delegate_
->Initialize(false);
409 LOG(INFO
) << "Initialized app network delegate.";
410 system_network_delegate_
->Initialize(false);
411 LOG(INFO
) << "Initialized system network delegate.";
415 } // namespace chromecast