1 // Copyright 2013 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 "content/shell/browser/shell_url_request_context_getter.h" 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_split.h" 11 #include "base/strings/string_util.h" 12 #include "base/threading/sequenced_worker_pool.h" 13 #include "base/threading/worker_pool.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/shell/browser/shell_network_delegate.h" 18 #include "content/shell/common/shell_content_client.h" 19 #include "content/shell/common/shell_switches.h" 20 #include "net/base/cache_type.h" 21 #include "net/cert/cert_verifier.h" 22 #include "net/cookies/cookie_monster.h" 23 #include "net/dns/host_resolver.h" 24 #include "net/dns/mapped_host_resolver.h" 25 #include "net/http/http_auth_handler_factory.h" 26 #include "net/http/http_cache.h" 27 #include "net/http/http_network_session.h" 28 #include "net/http/http_server_properties_impl.h" 29 #include "net/http/transport_security_state.h" 30 #include "net/proxy/proxy_service.h" 31 #include "net/ssl/default_server_bound_cert_store.h" 32 #include "net/ssl/server_bound_cert_service.h" 33 #include "net/ssl/ssl_config_service_defaults.h" 34 #include "net/url_request/data_protocol_handler.h" 35 #include "net/url_request/file_protocol_handler.h" 36 #include "net/url_request/static_http_user_agent_settings.h" 37 #include "net/url_request/url_request_context.h" 38 #include "net/url_request/url_request_context_storage.h" 39 #include "net/url_request/url_request_intercepting_job_factory.h" 40 #include "net/url_request/url_request_job_factory_impl.h" 41 #include "url/url_constants.h" 42 43 namespace content { 44 45 namespace { 46 47 void InstallProtocolHandlers(net::URLRequestJobFactoryImpl* job_factory, 48 ProtocolHandlerMap* protocol_handlers) { 49 for (ProtocolHandlerMap::iterator it = 50 protocol_handlers->begin(); 51 it != protocol_handlers->end(); 52 ++it) { 53 bool set_protocol = job_factory->SetProtocolHandler( 54 it->first, it->second.release()); 55 DCHECK(set_protocol); 56 } 57 protocol_handlers->clear(); 58 } 59 60 } // namespace 61 62 ShellURLRequestContextGetter::ShellURLRequestContextGetter( 63 bool ignore_certificate_errors, 64 const base::FilePath& base_path, 65 base::MessageLoop* io_loop, 66 base::MessageLoop* file_loop, 67 ProtocolHandlerMap* protocol_handlers, 68 URLRequestInterceptorScopedVector request_interceptors, 69 net::NetLog* net_log) 70 : ignore_certificate_errors_(ignore_certificate_errors), 71 base_path_(base_path), 72 io_loop_(io_loop), 73 file_loop_(file_loop), 74 net_log_(net_log), 75 request_interceptors_(request_interceptors.Pass()) { 76 // Must first be created on the UI thread. 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 79 std::swap(protocol_handlers_, *protocol_handlers); 80 81 // We must create the proxy config service on the UI loop on Linux because it 82 // must synchronously run on the glib message loop. This will be passed to 83 // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). 84 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) { 85 proxy_config_service_.reset( 86 net::ProxyService::CreateSystemProxyConfigService( 87 io_loop_->message_loop_proxy().get(), file_loop_)); 88 } 89 } 90 91 ShellURLRequestContextGetter::~ShellURLRequestContextGetter() { 92 } 93 94 net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() { 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 96 97 if (!url_request_context_) { 98 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 99 100 url_request_context_.reset(new net::URLRequestContext()); 101 url_request_context_->set_net_log(net_log_); 102 network_delegate_.reset(new ShellNetworkDelegate); 103 if (command_line.HasSwitch(switches::kDumpRenderTree)) 104 ShellNetworkDelegate::SetAcceptAllCookies(false); 105 url_request_context_->set_network_delegate(network_delegate_.get()); 106 storage_.reset( 107 new net::URLRequestContextStorage(url_request_context_.get())); 108 storage_->set_cookie_store(CreateCookieStore(CookieStoreConfig())); 109 storage_->set_server_bound_cert_service(new net::ServerBoundCertService( 110 new net::DefaultServerBoundCertStore(NULL), 111 base::WorkerPool::GetTaskRunner(true))); 112 storage_->set_http_user_agent_settings( 113 new net::StaticHttpUserAgentSettings( 114 "en-us,en", GetShellUserAgent())); 115 116 scoped_ptr<net::HostResolver> host_resolver( 117 net::HostResolver::CreateDefaultResolver( 118 url_request_context_->net_log())); 119 120 storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); 121 storage_->set_transport_security_state(new net::TransportSecurityState); 122 if (command_line.HasSwitch(switches::kDumpRenderTree)) { 123 storage_->set_proxy_service(net::ProxyService::CreateDirect()); 124 } else { 125 // TODO(jam): use v8 if possible, look at chrome code. 126 storage_->set_proxy_service( 127 net::ProxyService::CreateUsingSystemProxyResolver( 128 proxy_config_service_.release(), 129 0, 130 url_request_context_->net_log())); 131 } 132 storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); 133 storage_->set_http_auth_handler_factory( 134 net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); 135 storage_->set_http_server_properties( 136 scoped_ptr<net::HttpServerProperties>( 137 new net::HttpServerPropertiesImpl())); 138 139 base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache")); 140 net::HttpCache::DefaultBackend* main_backend = 141 new net::HttpCache::DefaultBackend( 142 net::DISK_CACHE, 143 #if defined(OS_ANDROID) 144 // TODO(rdsmith): Remove when default backend for Android is 145 // changed to simple cache. 146 net::CACHE_BACKEND_SIMPLE, 147 #else 148 net::CACHE_BACKEND_DEFAULT, 149 #endif 150 cache_path, 151 0, 152 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) 153 .get()); 154 155 net::HttpNetworkSession::Params network_session_params; 156 network_session_params.cert_verifier = 157 url_request_context_->cert_verifier(); 158 network_session_params.transport_security_state = 159 url_request_context_->transport_security_state(); 160 network_session_params.server_bound_cert_service = 161 url_request_context_->server_bound_cert_service(); 162 network_session_params.proxy_service = 163 url_request_context_->proxy_service(); 164 network_session_params.ssl_config_service = 165 url_request_context_->ssl_config_service(); 166 network_session_params.http_auth_handler_factory = 167 url_request_context_->http_auth_handler_factory(); 168 network_session_params.network_delegate = 169 network_delegate_.get(); 170 network_session_params.http_server_properties = 171 url_request_context_->http_server_properties(); 172 network_session_params.net_log = 173 url_request_context_->net_log(); 174 network_session_params.ignore_certificate_errors = 175 ignore_certificate_errors_; 176 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) { 177 int value; 178 base::StringToInt(command_line.GetSwitchValueASCII( 179 switches::kTestingFixedHttpPort), &value); 180 network_session_params.testing_fixed_http_port = value; 181 } 182 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) { 183 int value; 184 base::StringToInt(command_line.GetSwitchValueASCII( 185 switches::kTestingFixedHttpsPort), &value); 186 network_session_params.testing_fixed_https_port = value; 187 } 188 if (command_line.HasSwitch(switches::kHostResolverRules)) { 189 scoped_ptr<net::MappedHostResolver> mapped_host_resolver( 190 new net::MappedHostResolver(host_resolver.Pass())); 191 mapped_host_resolver->SetRulesFromString( 192 command_line.GetSwitchValueASCII(switches::kHostResolverRules)); 193 host_resolver = mapped_host_resolver.Pass(); 194 } 195 196 // Give |storage_| ownership at the end in case it's |mapped_host_resolver|. 197 storage_->set_host_resolver(host_resolver.Pass()); 198 network_session_params.host_resolver = 199 url_request_context_->host_resolver(); 200 201 net::HttpCache* main_cache = new net::HttpCache( 202 network_session_params, main_backend); 203 storage_->set_http_transaction_factory(main_cache); 204 205 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 206 new net::URLRequestJobFactoryImpl()); 207 // Keep ProtocolHandlers added in sync with 208 // ShellContentBrowserClient::IsHandledURL(). 209 InstallProtocolHandlers(job_factory.get(), &protocol_handlers_); 210 bool set_protocol = job_factory->SetProtocolHandler( 211 url::kDataScheme, new net::DataProtocolHandler); 212 DCHECK(set_protocol); 213 set_protocol = job_factory->SetProtocolHandler( 214 url::kFileScheme, 215 new net::FileProtocolHandler( 216 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( 217 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); 218 DCHECK(set_protocol); 219 220 // Set up interceptors in the reverse order. 221 scoped_ptr<net::URLRequestJobFactory> top_job_factory = 222 job_factory.PassAs<net::URLRequestJobFactory>(); 223 for (URLRequestInterceptorScopedVector::reverse_iterator i = 224 request_interceptors_.rbegin(); 225 i != request_interceptors_.rend(); 226 ++i) { 227 top_job_factory.reset(new net::URLRequestInterceptingJobFactory( 228 top_job_factory.Pass(), make_scoped_ptr(*i))); 229 } 230 request_interceptors_.weak_clear(); 231 232 storage_->set_job_factory(top_job_factory.release()); 233 } 234 235 return url_request_context_.get(); 236 } 237 238 scoped_refptr<base::SingleThreadTaskRunner> 239 ShellURLRequestContextGetter::GetNetworkTaskRunner() const { 240 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 241 } 242 243 net::HostResolver* ShellURLRequestContextGetter::host_resolver() { 244 return url_request_context_->host_resolver(); 245 } 246 247 } // namespace content 248