Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / chromecast / browser / url_request_context_factory.cc
blob57091c7513498312fad4be964d3ed3fe41e480bf
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/threading/worker_pool.h"
11 #include "chromecast/browser/cast_http_user_agent_settings.h"
12 #include "chromecast/browser/cast_network_delegate.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_network_layer.h"
23 #include "net/http/http_server_properties_impl.h"
24 #include "net/http/http_stream_factory.h"
25 #include "net/ocsp/nss_ocsp.h"
26 #include "net/proxy/proxy_service.h"
27 #include "net/socket/next_proto.h"
28 #include "net/ssl/channel_id_service.h"
29 #include "net/ssl/default_channel_id_store.h"
30 #include "net/ssl/ssl_config_service_defaults.h"
31 #include "net/url_request/data_protocol_handler.h"
32 #include "net/url_request/file_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 {
39 namespace shell {
41 namespace {
43 const char kCookieStoreFile[] = "Cookies";
45 } // namespace
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 {
54 public:
55 URLRequestContextGetter(URLRequestContextFactory* factory, bool is_media)
56 : is_media_(is_media),
57 factory_(factory) {
60 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 #if defined(USE_NSS)
67 // Set request context used by NSS for Crl requests.
68 net::SetURLRequestContextForNSSHttpIO(request_context_.get());
69 #endif // defined(USE_NSS)
72 return request_context_.get();
75 scoped_refptr<base::SingleThreadTaskRunner>
76 GetNetworkTaskRunner() const override {
77 return content::BrowserThread::GetMessageLoopProxyForThread(
78 content::BrowserThread::IO);
81 private:
82 ~URLRequestContextGetter() override {}
84 const bool is_media_;
85 URLRequestContextFactory* const factory_;
86 scoped_ptr<net::URLRequestContext> request_context_;
88 DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter);
91 // The URLRequestContextFactory::MainURLRequestContextGetter class is used for
92 // the main URLRequestContext.
93 class URLRequestContextFactory::MainURLRequestContextGetter
94 : public net::URLRequestContextGetter {
95 public:
96 MainURLRequestContextGetter(
97 URLRequestContextFactory* factory,
98 content::BrowserContext* browser_context,
99 content::ProtocolHandlerMap* protocol_handlers,
100 content::URLRequestInterceptorScopedVector request_interceptors)
101 : browser_context_(browser_context),
102 factory_(factory),
103 request_interceptors_(request_interceptors.Pass()) {
104 std::swap(protocol_handlers_, *protocol_handlers);
107 net::URLRequestContext* GetURLRequestContext() override {
108 if (!request_context_) {
109 request_context_.reset(factory_->CreateMainRequestContext(
110 browser_context_, &protocol_handlers_, request_interceptors_.Pass()));
111 protocol_handlers_.clear();
113 return request_context_.get();
116 scoped_refptr<base::SingleThreadTaskRunner>
117 GetNetworkTaskRunner() const override {
118 return content::BrowserThread::GetMessageLoopProxyForThread(
119 content::BrowserThread::IO);
122 private:
123 ~MainURLRequestContextGetter() override {}
125 content::BrowserContext* const browser_context_;
126 URLRequestContextFactory* const factory_;
127 content::ProtocolHandlerMap protocol_handlers_;
128 content::URLRequestInterceptorScopedVector request_interceptors_;
129 scoped_ptr<net::URLRequestContext> request_context_;
131 DISALLOW_COPY_AND_ASSIGN(MainURLRequestContextGetter);
134 URLRequestContextFactory::URLRequestContextFactory()
135 : app_network_delegate_(CastNetworkDelegate::Create()),
136 system_network_delegate_(CastNetworkDelegate::Create()),
137 system_dependencies_initialized_(false),
138 main_dependencies_initialized_(false),
139 media_dependencies_initialized_(false) {
142 URLRequestContextFactory::~URLRequestContextFactory() {
145 void URLRequestContextFactory::InitializeOnUIThread() {
146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
147 // Cast http user agent settings must be initialized in UI thread
148 // because it registers itself to pref notification observer which is not
149 // thread safe.
150 http_user_agent_settings_.reset(new CastHttpUserAgentSettings());
152 // Proxy config service should be initialized in UI thread, since
153 // ProxyConfigServiceDelegate on Android expects UI thread.
154 proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
155 content::BrowserThread::GetMessageLoopProxyForThread(
156 content::BrowserThread::IO),
157 content::BrowserThread::GetMessageLoopProxyForThread(
158 content::BrowserThread::FILE)));
161 net::URLRequestContextGetter* URLRequestContextFactory::CreateMainGetter(
162 content::BrowserContext* browser_context,
163 content::ProtocolHandlerMap* protocol_handlers,
164 content::URLRequestInterceptorScopedVector request_interceptors) {
165 DCHECK(!main_getter_.get())
166 << "Main URLRequestContextGetter already initialized";
167 main_getter_ = new MainURLRequestContextGetter(this,
168 browser_context,
169 protocol_handlers,
170 request_interceptors.Pass());
171 return main_getter_.get();
174 net::URLRequestContextGetter* URLRequestContextFactory::GetMainGetter() {
175 CHECK(main_getter_.get());
176 return main_getter_.get();
179 net::URLRequestContextGetter* URLRequestContextFactory::GetSystemGetter() {
180 if (!system_getter_.get()) {
181 system_getter_ = new URLRequestContextGetter(this, false);
183 return system_getter_.get();
186 net::URLRequestContextGetter* URLRequestContextFactory::GetMediaGetter() {
187 if (!media_getter_.get()) {
188 media_getter_ = new URLRequestContextGetter(this, true);
190 return media_getter_.get();
193 void URLRequestContextFactory::InitializeSystemContextDependencies() {
194 if (system_dependencies_initialized_)
195 return;
197 host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL);
199 // TODO(lcwu): http://crbug.com/392352. For performance and security reasons,
200 // a persistent (on-disk) HttpServerProperties and ChannelIDService might be
201 // desirable in the future.
202 channel_id_service_.reset(
203 new net::ChannelIDService(new net::DefaultChannelIDStore(NULL),
204 base::WorkerPool::GetTaskRunner(true)));
206 cert_verifier_.reset(net::CertVerifier::CreateDefault());
208 ssl_config_service_ = new net::SSLConfigServiceDefaults;
210 transport_security_state_.reset(new net::TransportSecurityState());
211 http_auth_handler_factory_.reset(
212 net::HttpAuthHandlerFactory::CreateDefault(host_resolver_.get()));
214 http_server_properties_.reset(new net::HttpServerPropertiesImpl);
216 proxy_service_.reset(net::ProxyService::CreateUsingSystemProxyResolver(
217 proxy_config_service_.release(), 0, NULL));
218 system_dependencies_initialized_ = true;
221 void URLRequestContextFactory::InitializeMainContextDependencies(
222 net::HttpTransactionFactory* transaction_factory,
223 content::ProtocolHandlerMap* protocol_handlers,
224 content::URLRequestInterceptorScopedVector request_interceptors) {
225 if (main_dependencies_initialized_)
226 return;
228 main_transaction_factory_.reset(transaction_factory);
229 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
230 new net::URLRequestJobFactoryImpl());
231 // Keep ProtocolHandlers added in sync with
232 // CastContentBrowserClient::IsHandledURL().
233 bool set_protocol = false;
234 for (content::ProtocolHandlerMap::iterator it = protocol_handlers->begin();
235 it != protocol_handlers->end();
236 ++it) {
237 set_protocol = job_factory->SetProtocolHandler(
238 it->first, it->second.release());
239 DCHECK(set_protocol);
241 set_protocol = job_factory->SetProtocolHandler(
242 url::kDataScheme,
243 new net::DataProtocolHandler);
244 DCHECK(set_protocol);
245 #if defined(OS_ANDROID)
246 set_protocol = job_factory->SetProtocolHandler(
247 url::kFileScheme,
248 new net::FileProtocolHandler(
249 content::BrowserThread::GetBlockingPool()->
250 GetTaskRunnerWithShutdownBehavior(
251 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
252 DCHECK(set_protocol);
253 #endif // defined(OS_ANDROID)
255 // Set up interceptors in the reverse order.
256 scoped_ptr<net::URLRequestJobFactory> top_job_factory = job_factory.Pass();
257 for (content::URLRequestInterceptorScopedVector::reverse_iterator i =
258 request_interceptors.rbegin();
259 i != request_interceptors.rend();
260 ++i) {
261 top_job_factory.reset(new net::URLRequestInterceptingJobFactory(
262 top_job_factory.Pass(), make_scoped_ptr(*i)));
264 request_interceptors.weak_clear();
266 main_job_factory_.reset(top_job_factory.release());
268 main_dependencies_initialized_ = true;
271 void URLRequestContextFactory::InitializeMediaContextDependencies(
272 net::HttpTransactionFactory* transaction_factory) {
273 if (media_dependencies_initialized_)
274 return;
276 media_transaction_factory_.reset(transaction_factory);
277 media_dependencies_initialized_ = true;
280 void URLRequestContextFactory::PopulateNetworkSessionParams(
281 bool ignore_certificate_errors,
282 net::HttpNetworkSession::Params* params) {
283 params->host_resolver = host_resolver_.get();
284 params->cert_verifier = cert_verifier_.get();
285 params->channel_id_service = channel_id_service_.get();
286 params->ssl_config_service = ssl_config_service_.get();
287 params->transport_security_state = transport_security_state_.get();
288 params->http_auth_handler_factory = http_auth_handler_factory_.get();
289 params->http_server_properties = http_server_properties_->GetWeakPtr();
290 params->ignore_certificate_errors = ignore_certificate_errors;
291 params->proxy_service = proxy_service_.get();
293 // TODO(lcwu): http://crbug.com/329681. Remove this once spdy is enabled
294 // by default at the content level.
295 params->next_protos = net::NextProtosSpdy31();
296 params->use_alternate_protocols = true;
299 net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() {
300 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
301 InitializeSystemContextDependencies();
302 net::HttpNetworkSession::Params system_params;
303 PopulateNetworkSessionParams(false, &system_params);
304 system_transaction_factory_.reset(new net::HttpNetworkLayer(
305 new net::HttpNetworkSession(system_params)));
306 system_job_factory_.reset(new net::URLRequestJobFactoryImpl());
308 net::URLRequestContext* system_context = new net::URLRequestContext();
309 system_context->set_host_resolver(host_resolver_.get());
310 system_context->set_channel_id_service(channel_id_service_.get());
311 system_context->set_cert_verifier(cert_verifier_.get());
312 system_context->set_proxy_service(proxy_service_.get());
313 system_context->set_ssl_config_service(ssl_config_service_.get());
314 system_context->set_transport_security_state(
315 transport_security_state_.get());
316 system_context->set_http_auth_handler_factory(
317 http_auth_handler_factory_.get());
318 system_context->set_http_server_properties(
319 http_server_properties_->GetWeakPtr());
320 system_context->set_http_transaction_factory(
321 system_transaction_factory_.get());
322 system_context->set_http_user_agent_settings(
323 http_user_agent_settings_.get());
324 system_context->set_job_factory(system_job_factory_.get());
325 system_context->set_cookie_store(
326 content::CreateCookieStore(content::CookieStoreConfig()));
327 system_context->set_network_delegate(system_network_delegate_.get());
328 return system_context;
331 net::URLRequestContext* URLRequestContextFactory::CreateMediaRequestContext() {
332 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
333 DCHECK(main_getter_.get())
334 << "Getting MediaRequestContext before MainRequestContext";
335 net::URLRequestContext* main_context = main_getter_->GetURLRequestContext();
337 // Set non caching backend.
338 net::HttpNetworkSession* main_session =
339 main_transaction_factory_->GetSession();
340 InitializeMediaContextDependencies(
341 new net::HttpNetworkLayer(main_session));
343 net::URLRequestContext* media_context = new net::URLRequestContext();
344 media_context->CopyFrom(main_context);
345 media_context->set_http_transaction_factory(
346 media_transaction_factory_.get());
347 return media_context;
350 net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext(
351 content::BrowserContext* browser_context,
352 content::ProtocolHandlerMap* protocol_handlers,
353 content::URLRequestInterceptorScopedVector request_interceptors) {
354 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
355 InitializeSystemContextDependencies();
357 bool ignore_certificate_errors = false;
358 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
359 if (cmd_line->HasSwitch(switches::kIgnoreCertificateErrors)) {
360 ignore_certificate_errors = true;
362 net::HttpNetworkSession::Params network_session_params;
363 PopulateNetworkSessionParams(ignore_certificate_errors,
364 &network_session_params);
365 InitializeMainContextDependencies(
366 new net::HttpNetworkLayer(
367 new net::HttpNetworkSession(network_session_params)),
368 protocol_handlers,
369 request_interceptors.Pass());
371 content::CookieStoreConfig cookie_config(
372 browser_context->GetPath().Append(kCookieStoreFile),
373 content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES,
374 NULL, NULL);
375 cookie_config.background_task_runner =
376 scoped_refptr<base::SequencedTaskRunner>();
377 scoped_refptr<net::CookieStore> cookie_store =
378 content::CreateCookieStore(cookie_config);
380 net::URLRequestContext* main_context = new net::URLRequestContext();
381 main_context->set_host_resolver(host_resolver_.get());
382 main_context->set_channel_id_service(channel_id_service_.get());
383 main_context->set_cert_verifier(cert_verifier_.get());
384 main_context->set_proxy_service(proxy_service_.get());
385 main_context->set_ssl_config_service(ssl_config_service_.get());
386 main_context->set_transport_security_state(transport_security_state_.get());
387 main_context->set_http_auth_handler_factory(
388 http_auth_handler_factory_.get());
389 main_context->set_http_server_properties(
390 http_server_properties_->GetWeakPtr());
391 main_context->set_cookie_store(cookie_store.get());
392 main_context->set_http_user_agent_settings(
393 http_user_agent_settings_.get());
395 main_context->set_http_transaction_factory(
396 main_transaction_factory_.get());
397 main_context->set_job_factory(main_job_factory_.get());
398 main_context->set_network_delegate(app_network_delegate_.get());
399 return main_context;
402 void URLRequestContextFactory::InitializeNetworkDelegates() {
403 app_network_delegate_->Initialize(false);
404 LOG(INFO) << "Initialized app network delegate.";
405 system_network_delegate_->Initialize(false);
406 LOG(INFO) << "Initialized system network delegate.";
409 } // namespace shell
410 } // namespace chromecast