Home | History | Annotate | Download | only in browser
      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/file_protocol_handler.h"
     34 #include "net/url_request/url_request_context.h"
     35 #include "net/url_request/url_request_context_getter.h"
     36 #include "net/url_request/url_request_intercepting_job_factory.h"
     37 #include "net/url_request/url_request_job_factory_impl.h"
     38 
     39 namespace chromecast {
     40 namespace shell {
     41 
     42 namespace {
     43 
     44 const char kCookieStoreFile[] = "Cookies";
     45 
     46 }  // namespace
     47 
     48 // Private classes to expose URLRequestContextGetter that call back to the
     49 // URLRequestContextFactory to create the URLRequestContext on demand.
     50 //
     51 // The URLRequestContextFactory::URLRequestContextGetter class is used for both
     52 // the system and media URLRequestCotnexts.
     53 class URLRequestContextFactory::URLRequestContextGetter
     54     : public net::URLRequestContextGetter {
     55  public:
     56   URLRequestContextGetter(URLRequestContextFactory* factory, bool is_media)
     57       : is_media_(is_media),
     58         factory_(factory) {
     59   }
     60 
     61   virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
     62     if (!request_context_) {
     63       if (is_media_) {
     64         request_context_.reset(factory_->CreateMediaRequestContext());
     65       } else {
     66         request_context_.reset(factory_->CreateSystemRequestContext());
     67 #if defined(USE_NSS)
     68         // Set request context used by NSS for Crl requests.
     69         net::SetURLRequestContextForNSSHttpIO(request_context_.get());
     70 #endif  // defined(USE_NSS)
     71       }
     72     }
     73     return request_context_.get();
     74   }
     75 
     76   virtual scoped_refptr<base::SingleThreadTaskRunner>
     77       GetNetworkTaskRunner() const OVERRIDE {
     78     return content::BrowserThread::GetMessageLoopProxyForThread(
     79         content::BrowserThread::IO);
     80   }
     81 
     82  private:
     83   virtual ~URLRequestContextGetter() {}
     84 
     85   const bool is_media_;
     86   URLRequestContextFactory* const factory_;
     87   scoped_ptr<net::URLRequestContext> request_context_;
     88 
     89   DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter);
     90 };
     91 
     92 // The URLRequestContextFactory::MainURLRequestContextGetter class is used for
     93 // the main URLRequestContext.
     94 class URLRequestContextFactory::MainURLRequestContextGetter
     95     : public net::URLRequestContextGetter {
     96  public:
     97   MainURLRequestContextGetter(
     98       URLRequestContextFactory* factory,
     99       content::BrowserContext* browser_context,
    100       content::ProtocolHandlerMap* protocol_handlers,
    101       content::URLRequestInterceptorScopedVector request_interceptors)
    102       : browser_context_(browser_context),
    103         factory_(factory),
    104         request_interceptors_(request_interceptors.Pass()) {
    105     std::swap(protocol_handlers_, *protocol_handlers);
    106   }
    107 
    108   virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
    109     if (!request_context_) {
    110       request_context_.reset(factory_->CreateMainRequestContext(
    111           browser_context_, &protocol_handlers_, request_interceptors_.Pass()));
    112       protocol_handlers_.clear();
    113     }
    114     return request_context_.get();
    115   }
    116 
    117   virtual scoped_refptr<base::SingleThreadTaskRunner>
    118       GetNetworkTaskRunner() const OVERRIDE {
    119     return content::BrowserThread::GetMessageLoopProxyForThread(
    120         content::BrowserThread::IO);
    121   }
    122 
    123  private:
    124   virtual ~MainURLRequestContextGetter() {}
    125 
    126   content::BrowserContext* const browser_context_;
    127   URLRequestContextFactory* const factory_;
    128   content::ProtocolHandlerMap protocol_handlers_;
    129   content::URLRequestInterceptorScopedVector request_interceptors_;
    130   scoped_ptr<net::URLRequestContext> request_context_;
    131 
    132   DISALLOW_COPY_AND_ASSIGN(MainURLRequestContextGetter);
    133 };
    134 
    135 URLRequestContextFactory::URLRequestContextFactory()
    136     : system_dependencies_initialized_(false),
    137       main_dependencies_initialized_(false),
    138       media_dependencies_initialized_(false) {
    139 }
    140 
    141 URLRequestContextFactory::~URLRequestContextFactory() {
    142 }
    143 
    144 void URLRequestContextFactory::InitializeOnUIThread() {
    145   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    146   // Cast http user agent settings must be initialized in UI thread
    147   // because it registers itself to pref notification observer which is not
    148   // thread safe.
    149   http_user_agent_settings_.reset(new CastHttpUserAgentSettings());
    150 
    151   // Proxy config service should be initialized in UI thread, since
    152   // ProxyConfigServiceDelegate on Android expects UI thread.
    153   proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
    154       content::BrowserThread::GetMessageLoopProxyForThread(
    155           content::BrowserThread::IO),
    156       content::BrowserThread::GetMessageLoopProxyForThread(
    157           content::BrowserThread::FILE)));
    158 }
    159 
    160 net::URLRequestContextGetter* URLRequestContextFactory::CreateMainGetter(
    161     content::BrowserContext* browser_context,
    162     content::ProtocolHandlerMap* protocol_handlers,
    163     content::URLRequestInterceptorScopedVector request_interceptors) {
    164   DCHECK(!main_getter_.get())
    165       << "Main URLRequestContextGetter already initialized";
    166   main_getter_ = new MainURLRequestContextGetter(this,
    167                                                  browser_context,
    168                                                  protocol_handlers,
    169                                                  request_interceptors.Pass());
    170   return main_getter_.get();
    171 }
    172 
    173 net::URLRequestContextGetter* URLRequestContextFactory::GetMainGetter() {
    174   CHECK(main_getter_.get());
    175   return main_getter_.get();
    176 }
    177 
    178 net::URLRequestContextGetter* URLRequestContextFactory::GetSystemGetter() {
    179   if (!system_getter_.get()) {
    180     system_getter_ = new URLRequestContextGetter(this, false);
    181   }
    182   return system_getter_.get();
    183 }
    184 
    185 net::URLRequestContextGetter* URLRequestContextFactory::GetMediaGetter() {
    186   if (!media_getter_.get()) {
    187     media_getter_ = new URLRequestContextGetter(this, true);
    188   }
    189   return media_getter_.get();
    190 }
    191 
    192 void URLRequestContextFactory::InitializeSystemContextDependencies() {
    193   if (system_dependencies_initialized_)
    194     return;
    195 
    196   host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL);
    197 
    198   // TODO(lcwu): http://crbug.com/392352. For performance and security reasons,
    199   // a persistent (on-disk) HttpServerProperties and ChannelIDService might be
    200   // desirable in the future.
    201   channel_id_service_.reset(
    202       new net::ChannelIDService(new net::DefaultChannelIDStore(NULL),
    203                                 base::WorkerPool::GetTaskRunner(true)));
    204 
    205   cert_verifier_.reset(net::CertVerifier::CreateDefault());
    206 
    207   ssl_config_service_ = new net::SSLConfigServiceDefaults;
    208 
    209   transport_security_state_.reset(new net::TransportSecurityState());
    210   http_auth_handler_factory_.reset(
    211       net::HttpAuthHandlerFactory::CreateDefault(host_resolver_.get()));
    212 
    213   http_server_properties_.reset(new net::HttpServerPropertiesImpl);
    214 
    215   proxy_service_.reset(net::ProxyService::CreateUsingSystemProxyResolver(
    216       proxy_config_service_.release(), 0, NULL));
    217   system_dependencies_initialized_ = true;
    218 }
    219 
    220 void URLRequestContextFactory::InitializeMainContextDependencies(
    221     net::HttpTransactionFactory* transaction_factory,
    222     content::ProtocolHandlerMap* protocol_handlers,
    223     content::URLRequestInterceptorScopedVector request_interceptors) {
    224   if (main_dependencies_initialized_)
    225     return;
    226 
    227   main_transaction_factory_.reset(transaction_factory);
    228   scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
    229       new net::URLRequestJobFactoryImpl());
    230   // Keep ProtocolHandlers added in sync with
    231   // CastContentBrowserClient::IsHandledURL().
    232   bool set_protocol = false;
    233   for (content::ProtocolHandlerMap::iterator it = protocol_handlers->begin();
    234        it != protocol_handlers->end();
    235        ++it) {
    236     set_protocol = job_factory->SetProtocolHandler(
    237         it->first, it->second.release());
    238     DCHECK(set_protocol);
    239   }
    240   set_protocol = job_factory->SetProtocolHandler(
    241       url::kDataScheme,
    242       new net::DataProtocolHandler);
    243   DCHECK(set_protocol);
    244 #if defined(OS_ANDROID)
    245   set_protocol = job_factory->SetProtocolHandler(
    246       url::kFileScheme,
    247       new net::FileProtocolHandler(
    248           content::BrowserThread::GetBlockingPool()->
    249               GetTaskRunnerWithShutdownBehavior(
    250                   base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
    251   DCHECK(set_protocol);
    252 #endif  // defined(OS_ANDROID)
    253 
    254   // Set up interceptors in the reverse order.
    255   scoped_ptr<net::URLRequestJobFactory> top_job_factory =
    256       job_factory.PassAs<net::URLRequestJobFactory>();
    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)));
    263   }
    264   request_interceptors.weak_clear();
    265 
    266   main_job_factory_.reset(top_job_factory.release());
    267 
    268   main_dependencies_initialized_ = true;
    269 }
    270 
    271 void URLRequestContextFactory::InitializeMediaContextDependencies(
    272     net::HttpTransactionFactory* transaction_factory) {
    273   if (media_dependencies_initialized_)
    274     return;
    275 
    276   media_transaction_factory_.reset(transaction_factory);
    277   media_dependencies_initialized_ = true;
    278 }
    279 
    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();
    292 
    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;
    297 }
    298 
    299 net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() {
    300   DCHECK(content::BrowserThread::CurrentlyOn(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());
    307 
    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   return system_context;
    328 }
    329 
    330 net::URLRequestContext* URLRequestContextFactory::CreateMediaRequestContext() {
    331   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
    332   DCHECK(main_getter_.get())
    333       << "Getting MediaRequestContext before MainRequestContext";
    334   net::URLRequestContext* main_context = main_getter_->GetURLRequestContext();
    335 
    336   // Set non caching backend.
    337   net::HttpNetworkSession* main_session =
    338       main_transaction_factory_->GetSession();
    339   InitializeMediaContextDependencies(
    340       new net::HttpNetworkLayer(main_session));
    341 
    342   net::URLRequestContext* media_context = new net::URLRequestContext();
    343   media_context->CopyFrom(main_context);
    344   media_context->set_http_transaction_factory(
    345       media_transaction_factory_.get());
    346   return media_context;
    347 }
    348 
    349 net::URLRequestContext* URLRequestContextFactory::CreateMainRequestContext(
    350     content::BrowserContext* browser_context,
    351     content::ProtocolHandlerMap* protocol_handlers,
    352     content::URLRequestInterceptorScopedVector request_interceptors) {
    353   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
    354   InitializeSystemContextDependencies();
    355 
    356   net::HttpCache::BackendFactory* main_backend =
    357       net::HttpCache::DefaultBackend::InMemory(16 * 1024 * 1024);
    358 
    359   bool ignore_certificate_errors = false;
    360   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
    361   if (cmd_line->HasSwitch(switches::kIgnoreCertificateErrors)) {
    362     ignore_certificate_errors = true;
    363   }
    364   net::HttpNetworkSession::Params network_session_params;
    365   PopulateNetworkSessionParams(ignore_certificate_errors,
    366                                &network_session_params);
    367   InitializeMainContextDependencies(
    368       new net::HttpCache(network_session_params, main_backend),
    369       protocol_handlers,
    370       request_interceptors.Pass());
    371 
    372   content::CookieStoreConfig cookie_config(
    373       browser_context->GetPath().Append(kCookieStoreFile),
    374       content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES,
    375       NULL, NULL);
    376   cookie_config.background_task_runner =
    377       scoped_refptr<base::SequencedTaskRunner>();
    378   scoped_refptr<net::CookieStore> cookie_store =
    379       content::CreateCookieStore(cookie_config);
    380 
    381   net::URLRequestContext* main_context = new net::URLRequestContext();
    382   main_context->set_host_resolver(host_resolver_.get());
    383   main_context->set_channel_id_service(channel_id_service_.get());
    384   main_context->set_cert_verifier(cert_verifier_.get());
    385   main_context->set_proxy_service(proxy_service_.get());
    386   main_context->set_ssl_config_service(ssl_config_service_.get());
    387   main_context->set_transport_security_state(transport_security_state_.get());
    388   main_context->set_http_auth_handler_factory(
    389       http_auth_handler_factory_.get());
    390   main_context->set_http_server_properties(
    391       http_server_properties_->GetWeakPtr());
    392   main_context->set_cookie_store(cookie_store.get());
    393   main_context->set_http_user_agent_settings(
    394       http_user_agent_settings_.get());
    395 
    396   main_context->set_http_transaction_factory(
    397       main_transaction_factory_.get());
    398   main_context->set_job_factory(main_job_factory_.get());
    399   return main_context;
    400 }
    401 
    402 }  // namespace shell
    403 }  // namespace chromecast
    404