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/channel_id_service.h" 32 #include "net/ssl/default_channel_id_store.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(), file_loop_->message_loop_proxy())); 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_channel_id_service(new net::ChannelIDService( 110 new net::DefaultChannelIDStore(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 154 net::HttpNetworkSession::Params network_session_params; 155 network_session_params.cert_verifier = 156 url_request_context_->cert_verifier(); 157 network_session_params.transport_security_state = 158 url_request_context_->transport_security_state(); 159 network_session_params.channel_id_service = 160 url_request_context_->channel_id_service(); 161 network_session_params.proxy_service = 162 url_request_context_->proxy_service(); 163 network_session_params.ssl_config_service = 164 url_request_context_->ssl_config_service(); 165 network_session_params.http_auth_handler_factory = 166 url_request_context_->http_auth_handler_factory(); 167 network_session_params.network_delegate = 168 network_delegate_.get(); 169 network_session_params.http_server_properties = 170 url_request_context_->http_server_properties(); 171 network_session_params.net_log = 172 url_request_context_->net_log(); 173 network_session_params.ignore_certificate_errors = 174 ignore_certificate_errors_; 175 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) { 176 int value; 177 base::StringToInt(command_line.GetSwitchValueASCII( 178 switches::kTestingFixedHttpPort), &value); 179 network_session_params.testing_fixed_http_port = value; 180 } 181 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) { 182 int value; 183 base::StringToInt(command_line.GetSwitchValueASCII( 184 switches::kTestingFixedHttpsPort), &value); 185 network_session_params.testing_fixed_https_port = value; 186 } 187 if (command_line.HasSwitch(switches::kHostResolverRules)) { 188 scoped_ptr<net::MappedHostResolver> mapped_host_resolver( 189 new net::MappedHostResolver(host_resolver.Pass())); 190 mapped_host_resolver->SetRulesFromString( 191 command_line.GetSwitchValueASCII(switches::kHostResolverRules)); 192 host_resolver = mapped_host_resolver.Pass(); 193 } 194 195 // Give |storage_| ownership at the end in case it's |mapped_host_resolver|. 196 storage_->set_host_resolver(host_resolver.Pass()); 197 network_session_params.host_resolver = 198 url_request_context_->host_resolver(); 199 200 net::HttpCache* main_cache = new net::HttpCache( 201 network_session_params, main_backend); 202 storage_->set_http_transaction_factory(main_cache); 203 204 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 205 new net::URLRequestJobFactoryImpl()); 206 // Keep ProtocolHandlers added in sync with 207 // ShellContentBrowserClient::IsHandledURL(). 208 InstallProtocolHandlers(job_factory.get(), &protocol_handlers_); 209 bool set_protocol = job_factory->SetProtocolHandler( 210 url::kDataScheme, new net::DataProtocolHandler); 211 DCHECK(set_protocol); 212 #if !defined(DISABLE_FILE_SUPPORT) 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 #endif 220 221 // Set up interceptors in the reverse order. 222 scoped_ptr<net::URLRequestJobFactory> top_job_factory = 223 job_factory.PassAs<net::URLRequestJobFactory>(); 224 for (URLRequestInterceptorScopedVector::reverse_iterator i = 225 request_interceptors_.rbegin(); 226 i != request_interceptors_.rend(); 227 ++i) { 228 top_job_factory.reset(new net::URLRequestInterceptingJobFactory( 229 top_job_factory.Pass(), make_scoped_ptr(*i))); 230 } 231 request_interceptors_.weak_clear(); 232 233 storage_->set_job_factory(top_job_factory.release()); 234 } 235 236 return url_request_context_.get(); 237 } 238 239 scoped_refptr<base::SingleThreadTaskRunner> 240 ShellURLRequestContextGetter::GetNetworkTaskRunner() const { 241 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 242 } 243 244 net::HostResolver* ShellURLRequestContextGetter::host_resolver() { 245 return url_request_context_->host_resolver(); 246 } 247 248 } // namespace content 249