|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/url_request/url_request_context_builder.h" | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/string_util.h" | 
|  | #include "base/threading/thread.h" | 
|  | #include "base/thread_task_runner_handle.h" | 
|  | #include "net/base/cert_verifier.h" | 
|  | #include "net/base/host_resolver.h" | 
|  | #include "net/base/net_errors.h" | 
|  | #include "net/base/network_delegate.h" | 
|  | #include "net/base/ssl_config_service_defaults.h" | 
|  | #include "net/base/transport_security_state.h" | 
|  | #include "net/cookies/cookie_monster.h" | 
|  | #include "net/ftp/ftp_network_layer.h" | 
|  | #include "net/http/http_auth_handler_factory.h" | 
|  | #include "net/http/http_cache.h" | 
|  | #include "net/http/http_network_layer.h" | 
|  | #include "net/http/http_network_session.h" | 
|  | #include "net/http/http_server_properties_impl.h" | 
|  | #include "net/proxy/proxy_service.h" | 
|  | #include "net/url_request/static_http_user_agent_settings.h" | 
|  | #include "net/url_request/url_request_context.h" | 
|  | #include "net/url_request/url_request_context_storage.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class BasicNetworkDelegate : public NetworkDelegate { | 
|  | public: | 
|  | BasicNetworkDelegate() {} | 
|  | virtual ~BasicNetworkDelegate() {} | 
|  |  | 
|  | private: | 
|  | virtual int OnBeforeURLRequest(URLRequest* request, | 
|  | const CompletionCallback& callback, | 
|  | GURL* new_url) OVERRIDE { | 
|  | return OK; | 
|  | } | 
|  |  | 
|  | virtual int OnBeforeSendHeaders(URLRequest* request, | 
|  | const CompletionCallback& callback, | 
|  | HttpRequestHeaders* headers) OVERRIDE { | 
|  | return OK; | 
|  | } | 
|  |  | 
|  | virtual void OnSendHeaders(URLRequest* request, | 
|  | const HttpRequestHeaders& headers) OVERRIDE {} | 
|  |  | 
|  | virtual int OnHeadersReceived( | 
|  | URLRequest* request, | 
|  | const CompletionCallback& callback, | 
|  | const HttpResponseHeaders* original_response_headers, | 
|  | scoped_refptr<HttpResponseHeaders>* override_response_headers) | 
|  | OVERRIDE { | 
|  | return OK; | 
|  | } | 
|  |  | 
|  | virtual void OnBeforeRedirect(URLRequest* request, | 
|  | const GURL& new_location) OVERRIDE {} | 
|  |  | 
|  | virtual void OnResponseStarted(URLRequest* request) OVERRIDE {} | 
|  |  | 
|  | virtual void OnRawBytesRead(const URLRequest& request, | 
|  | int bytes_read) OVERRIDE {} | 
|  |  | 
|  | virtual void OnCompleted(URLRequest* request, bool started) OVERRIDE {} | 
|  |  | 
|  | virtual void OnURLRequestDestroyed(URLRequest* request) OVERRIDE {} | 
|  |  | 
|  | virtual void OnPACScriptError(int line_number, | 
|  | const string16& error) OVERRIDE {} | 
|  |  | 
|  | virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired( | 
|  | URLRequest* request, | 
|  | const AuthChallengeInfo& auth_info, | 
|  | const AuthCallback& callback, | 
|  | AuthCredentials* credentials) OVERRIDE { | 
|  | return NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; | 
|  | } | 
|  |  | 
|  | virtual bool OnCanGetCookies(const URLRequest& request, | 
|  | const CookieList& cookie_list) OVERRIDE { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | virtual bool OnCanSetCookie(const URLRequest& request, | 
|  | const std::string& cookie_line, | 
|  | CookieOptions* options) OVERRIDE { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | virtual bool OnCanAccessFile(const net::URLRequest& request, | 
|  | const FilePath& path) const OVERRIDE { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | virtual bool OnCanThrottleRequest(const URLRequest& request) const OVERRIDE { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | virtual int OnBeforeSocketStreamConnect( | 
|  | SocketStream* stream, | 
|  | const CompletionCallback& callback) OVERRIDE { | 
|  | return OK; | 
|  | } | 
|  |  | 
|  | virtual void OnRequestWaitStateChange(const URLRequest& request, | 
|  | RequestWaitState state) OVERRIDE { | 
|  | } | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate); | 
|  | }; | 
|  |  | 
|  | class BasicURLRequestContext : public URLRequestContext { | 
|  | public: | 
|  | BasicURLRequestContext() | 
|  | : cache_thread_("Cache Thread"), | 
|  | file_thread_("File Thread"), | 
|  | ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) {} | 
|  |  | 
|  | URLRequestContextStorage* storage() { | 
|  | return &storage_; | 
|  | } | 
|  |  | 
|  | void StartCacheThread() { | 
|  | cache_thread_.StartWithOptions( | 
|  | base::Thread::Options(MessageLoop::TYPE_IO, 0)); | 
|  | } | 
|  |  | 
|  | scoped_refptr<base::MessageLoopProxy> cache_message_loop_proxy() { | 
|  | DCHECK(cache_thread_.IsRunning()); | 
|  | return cache_thread_.message_loop_proxy(); | 
|  | } | 
|  |  | 
|  | void StartFileThread() { | 
|  | file_thread_.StartWithOptions( | 
|  | base::Thread::Options(MessageLoop::TYPE_DEFAULT, 0)); | 
|  | } | 
|  |  | 
|  | MessageLoop* file_message_loop() { | 
|  | DCHECK(file_thread_.IsRunning()); | 
|  | return file_thread_.message_loop(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | virtual ~BasicURLRequestContext() {} | 
|  |  | 
|  | private: | 
|  | base::Thread cache_thread_; | 
|  | base::Thread file_thread_; | 
|  | URLRequestContextStorage storage_; | 
|  | DISALLOW_COPY_AND_ASSIGN(BasicURLRequestContext); | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | URLRequestContextBuilder::HttpCacheParams::HttpCacheParams() | 
|  | : type(IN_MEMORY), | 
|  | max_size(0) {} | 
|  | URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {} | 
|  |  | 
|  | URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams() | 
|  | : ignore_certificate_errors(false), | 
|  | host_mapping_rules(NULL), | 
|  | http_pipelining_enabled(false), | 
|  | testing_fixed_http_port(0), | 
|  | testing_fixed_https_port(0), | 
|  | trusted_spdy_proxy() {} | 
|  |  | 
|  | URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams() | 
|  | {} | 
|  |  | 
|  | URLRequestContextBuilder::URLRequestContextBuilder() | 
|  | : ftp_enabled_(false), | 
|  | http_cache_enabled_(true) {} | 
|  | URLRequestContextBuilder::~URLRequestContextBuilder() {} | 
|  |  | 
|  | #if defined(OS_LINUX) || defined(OS_ANDROID) | 
|  | void URLRequestContextBuilder::set_proxy_config_service( | 
|  | ProxyConfigService* proxy_config_service) { | 
|  | proxy_config_service_.reset(proxy_config_service); | 
|  | } | 
|  | #endif  // defined(OS_LINUX) || defined(OS_ANDROID) | 
|  |  | 
|  | URLRequestContext* URLRequestContextBuilder::Build() { | 
|  | #if __LB_ENABLE_NATIVE_HTTP_STACK__ | 
|  | return NULL; | 
|  | #else | 
|  | BasicURLRequestContext* context = new BasicURLRequestContext; | 
|  | URLRequestContextStorage* storage = context->storage(); | 
|  |  | 
|  | storage->set_http_user_agent_settings(new StaticHttpUserAgentSettings( | 
|  | accept_language_, accept_charset_, user_agent_)); | 
|  |  | 
|  | if (!network_delegate_) | 
|  | network_delegate_.reset(new BasicNetworkDelegate); | 
|  | storage->set_network_delegate(network_delegate_.release()); | 
|  |  | 
|  | storage->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); | 
|  |  | 
|  | #if !DISABLE_FTP_SUPPORT | 
|  | if (ftp_enabled_) { | 
|  | storage->set_ftp_transaction_factory( | 
|  | new FtpNetworkLayer(context->host_resolver())); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | context->StartFileThread(); | 
|  |  | 
|  | // TODO(willchan): Switch to using this code when | 
|  | // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck. | 
|  | #if defined(OS_LINUX) || defined(OS_ANDROID) | 
|  | ProxyConfigService* proxy_config_service = proxy_config_service_.release(); | 
|  | #else | 
|  | ProxyConfigService* proxy_config_service = | 
|  | ProxyService::CreateSystemProxyConfigService( | 
|  | base::ThreadTaskRunnerHandle::Get(), | 
|  | context->file_message_loop()); | 
|  | #endif  // defined(OS_LINUX) || defined(OS_ANDROID) | 
|  | storage->set_proxy_service( | 
|  | ProxyService::CreateUsingSystemProxyResolver( | 
|  | proxy_config_service, | 
|  | 4,  // TODO(willchan): Find a better constant somewhere. | 
|  | context->net_log())); | 
|  | storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); | 
|  | storage->set_http_auth_handler_factory( | 
|  | net::HttpAuthHandlerRegistryFactory::CreateDefault( | 
|  | context->host_resolver())); | 
|  | storage->set_cookie_store(new CookieMonster(NULL, NULL)); | 
|  | storage->set_transport_security_state(new net::TransportSecurityState()); | 
|  | storage->set_http_server_properties(new net::HttpServerPropertiesImpl); | 
|  | storage->set_cert_verifier(CertVerifier::CreateDefault()); | 
|  |  | 
|  | net::HttpNetworkSession::Params network_session_params; | 
|  | network_session_params.host_resolver = context->host_resolver(); | 
|  | network_session_params.cert_verifier = context->cert_verifier(); | 
|  | network_session_params.transport_security_state = | 
|  | context->transport_security_state(); | 
|  | network_session_params.proxy_service = context->proxy_service(); | 
|  | network_session_params.ssl_config_service = | 
|  | context->ssl_config_service(); | 
|  | network_session_params.http_auth_handler_factory = | 
|  | context->http_auth_handler_factory(); | 
|  | network_session_params.network_delegate = | 
|  | context->network_delegate(); | 
|  | network_session_params.http_server_properties = | 
|  | context->http_server_properties(); | 
|  | network_session_params.net_log = context->net_log(); | 
|  | network_session_params.ignore_certificate_errors = | 
|  | http_network_session_params_.ignore_certificate_errors; | 
|  | network_session_params.host_mapping_rules = | 
|  | http_network_session_params_.host_mapping_rules; | 
|  | network_session_params.http_pipelining_enabled = | 
|  | http_network_session_params_.http_pipelining_enabled; | 
|  | network_session_params.testing_fixed_http_port = | 
|  | http_network_session_params_.testing_fixed_http_port; | 
|  | network_session_params.testing_fixed_https_port = | 
|  | http_network_session_params_.testing_fixed_https_port; | 
|  | network_session_params.trusted_spdy_proxy = | 
|  | http_network_session_params_.trusted_spdy_proxy; | 
|  |  | 
|  | HttpTransactionFactory* http_transaction_factory = NULL; | 
|  | if (http_cache_enabled_) { | 
|  | network_session_params.server_bound_cert_service = | 
|  | context->server_bound_cert_service(); | 
|  | HttpCache::BackendFactory* http_cache_backend = NULL; | 
|  | if (http_cache_params_.type == HttpCacheParams::DISK) { | 
|  | context->StartCacheThread(); | 
|  | http_cache_backend = | 
|  | new HttpCache::DefaultBackend(DISK_CACHE, | 
|  | http_cache_params_.path, | 
|  | http_cache_params_.max_size, | 
|  | context->cache_message_loop_proxy()); | 
|  | } else { | 
|  | http_cache_backend = | 
|  | HttpCache::DefaultBackend::InMemory(http_cache_params_.max_size); | 
|  | } | 
|  |  | 
|  | http_transaction_factory = new HttpCache( | 
|  | network_session_params, http_cache_backend); | 
|  | } else { | 
|  | scoped_refptr<net::HttpNetworkSession> network_session( | 
|  | new net::HttpNetworkSession(network_session_params)); | 
|  |  | 
|  | http_transaction_factory = new HttpNetworkLayer(network_session); | 
|  | } | 
|  | storage->set_http_transaction_factory(http_transaction_factory); | 
|  |  | 
|  | // TODO(willchan): Support sdch. | 
|  |  | 
|  | return context; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | }  // namespace net |