1// Copyright (c) 2012 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 "android_webview/browser/net/aw_url_request_context_getter.h" 6 7#include <vector> 8 9#include "android_webview/browser/aw_browser_context.h" 10#include "android_webview/browser/aw_content_browser_client.h" 11#include "android_webview/browser/aw_request_interceptor.h" 12#include "android_webview/browser/net/aw_network_delegate.h" 13#include "android_webview/browser/net/aw_url_request_job_factory.h" 14#include "android_webview/browser/net/init_native_callback.h" 15#include "android_webview/common/aw_content_client.h" 16#include "base/command_line.h" 17#include "base/strings/string_number_conversions.h" 18#include "base/threading/sequenced_worker_pool.h" 19#include "base/threading/worker_pool.h" 20#include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h" 21#include "components/data_reduction_proxy/browser/data_reduction_proxy_config_service.h" 22#include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h" 23#include "content/public/browser/browser_thread.h" 24#include "content/public/browser/content_browser_client.h" 25#include "content/public/browser/cookie_store_factory.h" 26#include "content/public/common/content_client.h" 27#include "content/public/common/content_switches.h" 28#include "content/public/common/url_constants.h" 29#include "net/base/cache_type.h" 30#include "net/base/net_log.h" 31#include "net/cookies/cookie_store.h" 32#include "net/dns/mapped_host_resolver.h" 33#include "net/http/http_cache.h" 34#include "net/http/http_stream_factory.h" 35#include "net/proxy/proxy_service.h" 36#include "net/socket/next_proto.h" 37#include "net/ssl/default_channel_id_store.h" 38#include "net/url_request/data_protocol_handler.h" 39#include "net/url_request/file_protocol_handler.h" 40#include "net/url_request/url_request_context_builder.h" 41#include "net/url_request/url_request_context.h" 42#include "net/url_request/url_request_intercepting_job_factory.h" 43#include "net/url_request/url_request_interceptor.h" 44 45using content::BrowserThread; 46using data_reduction_proxy::DataReductionProxySettings; 47 48namespace android_webview { 49 50 51namespace { 52 53void ApplyCmdlineOverridesToURLRequestContextBuilder( 54 net::URLRequestContextBuilder* builder) { 55 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 56 if (command_line.HasSwitch(switches::kHostResolverRules)) { 57 // If hostname remappings were specified on the command-line, layer these 58 // rules on top of the real host resolver. This allows forwarding all 59 // requests through a designated test server. 60 scoped_ptr<net::MappedHostResolver> host_resolver( 61 new net::MappedHostResolver( 62 net::HostResolver::CreateDefaultResolver(NULL))); 63 host_resolver->SetRulesFromString( 64 command_line.GetSwitchValueASCII(switches::kHostResolverRules)); 65 builder->set_host_resolver(host_resolver.release()); 66 } 67} 68 69void ApplyCmdlineOverridesToNetworkSessionParams( 70 net::HttpNetworkSession::Params* params) { 71 int value; 72 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 73 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) { 74 base::StringToInt(command_line.GetSwitchValueASCII( 75 switches::kTestingFixedHttpPort), &value); 76 params->testing_fixed_http_port = value; 77 } 78 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) { 79 base::StringToInt(command_line.GetSwitchValueASCII( 80 switches::kTestingFixedHttpsPort), &value); 81 params->testing_fixed_https_port = value; 82 } 83 if (command_line.HasSwitch(switches::kIgnoreCertificateErrors)) { 84 params->ignore_certificate_errors = true; 85 } 86} 87 88void PopulateNetworkSessionParams( 89 net::URLRequestContext* context, 90 net::HttpNetworkSession::Params* params) { 91 params->host_resolver = context->host_resolver(); 92 params->cert_verifier = context->cert_verifier(); 93 params->channel_id_service = context->channel_id_service(); 94 params->transport_security_state = context->transport_security_state(); 95 params->proxy_service = context->proxy_service(); 96 params->ssl_config_service = context->ssl_config_service(); 97 params->http_auth_handler_factory = context->http_auth_handler_factory(); 98 params->network_delegate = context->network_delegate(); 99 params->http_server_properties = context->http_server_properties(); 100 params->net_log = context->net_log(); 101 // TODO(sgurun) remove once crbug.com/329681 is fixed. 102 params->next_protos = net::NextProtosSpdy31(); 103 params->use_alternate_protocols = true; 104 105 ApplyCmdlineOverridesToNetworkSessionParams(params); 106} 107 108scoped_ptr<net::URLRequestJobFactory> CreateJobFactory( 109 content::ProtocolHandlerMap* protocol_handlers, 110 content::URLRequestInterceptorScopedVector request_interceptors) { 111 scoped_ptr<AwURLRequestJobFactory> aw_job_factory(new AwURLRequestJobFactory); 112 bool set_protocol = aw_job_factory->SetProtocolHandler( 113 url::kFileScheme, 114 new net::FileProtocolHandler( 115 content::BrowserThread::GetBlockingPool()-> 116 GetTaskRunnerWithShutdownBehavior( 117 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); 118 DCHECK(set_protocol); 119 set_protocol = aw_job_factory->SetProtocolHandler( 120 url::kDataScheme, new net::DataProtocolHandler()); 121 DCHECK(set_protocol); 122 set_protocol = aw_job_factory->SetProtocolHandler( 123 url::kBlobScheme, 124 (*protocol_handlers)[url::kBlobScheme].release()); 125 DCHECK(set_protocol); 126 set_protocol = aw_job_factory->SetProtocolHandler( 127 url::kFileSystemScheme, 128 (*protocol_handlers)[url::kFileSystemScheme].release()); 129 DCHECK(set_protocol); 130 set_protocol = aw_job_factory->SetProtocolHandler( 131 content::kChromeUIScheme, 132 (*protocol_handlers)[content::kChromeUIScheme].release()); 133 DCHECK(set_protocol); 134 set_protocol = aw_job_factory->SetProtocolHandler( 135 content::kChromeDevToolsScheme, 136 (*protocol_handlers)[content::kChromeDevToolsScheme].release()); 137 DCHECK(set_protocol); 138 protocol_handlers->clear(); 139 140 // Note that even though the content:// scheme handler is created here, 141 // it cannot be used by child processes until access to it is granted via 142 // ChildProcessSecurityPolicy::GrantScheme(). This is done in 143 // AwContentBrowserClient. 144 request_interceptors.push_back( 145 CreateAndroidContentRequestInterceptor().release()); 146 request_interceptors.push_back( 147 CreateAndroidAssetFileRequestInterceptor().release()); 148 // The AwRequestInterceptor must come after the content and asset file job 149 // factories. This for WebViewClassic compatibility where it was not 150 // possible to intercept resource loads to resolvable content:// and 151 // file:// URIs. 152 // This logical dependency is also the reason why the Content 153 // URLRequestInterceptor has to be added as an interceptor rather than as a 154 // ProtocolHandler. 155 request_interceptors.push_back(new AwRequestInterceptor()); 156 157 // The chain of responsibility will execute the handlers in reverse to the 158 // order in which the elements of the chain are created. 159 scoped_ptr<net::URLRequestJobFactory> job_factory(aw_job_factory.Pass()); 160 for (content::URLRequestInterceptorScopedVector::reverse_iterator i = 161 request_interceptors.rbegin(); 162 i != request_interceptors.rend(); 163 ++i) { 164 job_factory.reset(new net::URLRequestInterceptingJobFactory( 165 job_factory.Pass(), make_scoped_ptr(*i))); 166 } 167 request_interceptors.weak_clear(); 168 169 return job_factory.Pass(); 170} 171 172} // namespace 173 174AwURLRequestContextGetter::AwURLRequestContextGetter( 175 const base::FilePath& partition_path, net::CookieStore* cookie_store, 176 scoped_ptr<data_reduction_proxy::DataReductionProxyConfigService> 177 config_service) 178 : partition_path_(partition_path), 179 cookie_store_(cookie_store), 180 net_log_(new net::NetLog()) { 181 data_reduction_proxy_config_service_ = config_service.Pass(); 182 // CreateSystemProxyConfigService for Android must be called on main thread. 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 184} 185 186AwURLRequestContextGetter::~AwURLRequestContextGetter() { 187} 188 189void AwURLRequestContextGetter::InitializeURLRequestContext() { 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 191 DCHECK(!url_request_context_); 192 193 net::URLRequestContextBuilder builder; 194 builder.set_user_agent(GetUserAgent()); 195 AwNetworkDelegate* aw_network_delegate = new AwNetworkDelegate(); 196 builder.set_network_delegate(aw_network_delegate); 197#if !defined(DISABLE_FTP_SUPPORT) 198 builder.set_ftp_enabled(false); // Android WebView does not support ftp yet. 199#endif 200 DCHECK(data_reduction_proxy_config_service_.get()); 201 // Android provides a local HTTP proxy that handles all the proxying. 202 // Create the proxy without a resolver since we rely on this local HTTP proxy. 203 // TODO(sgurun) is this behavior guaranteed through SDK? 204 builder.set_proxy_service( 205 net::ProxyService::CreateWithoutProxyResolver( 206 data_reduction_proxy_config_service_.release(), 207 net_log_.get())); 208 builder.set_accept_language(net::HttpUtil::GenerateAcceptLanguageHeader( 209 AwContentBrowserClient::GetAcceptLangsImpl())); 210 builder.set_net_log(net_log_.get()); 211 builder.set_channel_id_enabled(false); 212 ApplyCmdlineOverridesToURLRequestContextBuilder(&builder); 213 214 url_request_context_.reset(builder.Build()); 215 // TODO(mnaganov): Fix URLRequestContextBuilder to use proper threads. 216 net::HttpNetworkSession::Params network_session_params; 217 218 PopulateNetworkSessionParams(url_request_context_.get(), 219 &network_session_params); 220 221 net::HttpCache* main_cache = new net::HttpCache( 222 network_session_params, 223 new net::HttpCache::DefaultBackend( 224 net::DISK_CACHE, 225 net::CACHE_BACKEND_SIMPLE, 226 partition_path_.Append(FILE_PATH_LITERAL("Cache")), 227 20 * 1024 * 1024, // 20M 228 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE))); 229 230 AwBrowserContext* browser_context = AwBrowserContext::GetDefault(); 231 DCHECK(browser_context); 232 DataReductionProxySettings* data_reduction_proxy_settings = 233 browser_context->GetDataReductionProxySettings(); 234 DCHECK(data_reduction_proxy_settings); 235 data_reduction_proxy_auth_request_handler_.reset( 236 new data_reduction_proxy::DataReductionProxyAuthRequestHandler( 237 data_reduction_proxy::kClientAndroidWebview, 238 data_reduction_proxy_settings->params(), 239 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); 240 241 // Compression statistics are not gathered for WebView, so 242 // DataReductionProxyStatisticsPrefs is not instantiated and passed to the 243 // network delegate. 244 aw_network_delegate->set_data_reduction_proxy_params( 245 data_reduction_proxy_settings->params()); 246 aw_network_delegate->set_data_reduction_proxy_auth_request_handler( 247 data_reduction_proxy_auth_request_handler_.get()); 248 249 main_http_factory_.reset(main_cache); 250 url_request_context_->set_http_transaction_factory(main_cache); 251 url_request_context_->set_cookie_store(cookie_store_); 252 253 job_factory_ = CreateJobFactory(&protocol_handlers_, 254 request_interceptors_.Pass()); 255 url_request_context_->set_job_factory(job_factory_.get()); 256} 257 258net::URLRequestContext* AwURLRequestContextGetter::GetURLRequestContext() { 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 260 if (!url_request_context_) 261 InitializeURLRequestContext(); 262 263 return url_request_context_.get(); 264} 265 266scoped_refptr<base::SingleThreadTaskRunner> 267AwURLRequestContextGetter::GetNetworkTaskRunner() const { 268 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 269} 270 271void AwURLRequestContextGetter::SetHandlersAndInterceptors( 272 content::ProtocolHandlerMap* protocol_handlers, 273 content::URLRequestInterceptorScopedVector request_interceptors) { 274 std::swap(protocol_handlers_, *protocol_handlers); 275 request_interceptors_.swap(request_interceptors); 276} 277 278data_reduction_proxy::DataReductionProxyAuthRequestHandler* 279AwURLRequestContextGetter::GetDataReductionProxyAuthRequestHandler() const { 280 return data_reduction_proxy_auth_request_handler_.get(); 281} 282 283net::NetLog* AwURLRequestContextGetter::GetNetLog() { 284 return net_log_.get(); 285} 286 287void AwURLRequestContextGetter::SetKeyOnIO(const std::string& key) { 288 DCHECK(data_reduction_proxy_auth_request_handler_); 289 data_reduction_proxy_auth_request_handler_->InitAuthentication(key); 290} 291 292} // namespace android_webview 293