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 "net/url_request/url_request_context_builder.h"
6
7#include <string>
8
9#include "base/basictypes.h"
10#include "base/compiler_specific.h"
11#include "base/logging.h"
12#include "base/strings/string_util.h"
13#include "base/thread_task_runner_handle.h"
14#include "base/threading/thread.h"
15#include "net/base/cache_type.h"
16#include "net/base/net_errors.h"
17#include "net/base/network_delegate.h"
18#include "net/cert/cert_verifier.h"
19#include "net/cookies/cookie_monster.h"
20#include "net/dns/host_resolver.h"
21#include "net/ftp/ftp_network_layer.h"
22#include "net/http/http_auth_handler_factory.h"
23#include "net/http/http_cache.h"
24#include "net/http/http_network_layer.h"
25#include "net/http/http_network_session.h"
26#include "net/http/http_server_properties_impl.h"
27#include "net/http/transport_security_persister.h"
28#include "net/http/transport_security_state.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/static_http_user_agent_settings.h"
34#include "net/url_request/url_request_context.h"
35#include "net/url_request/url_request_context_storage.h"
36#include "net/url_request/url_request_job_factory_impl.h"
37#include "net/url_request/url_request_throttler_manager.h"
38
39#if !defined(DISABLE_FILE_SUPPORT)
40#include "net/url_request/file_protocol_handler.h"
41#endif
42
43#if !defined(DISABLE_FTP_SUPPORT)
44#include "net/url_request/ftp_protocol_handler.h"
45#endif
46
47namespace net {
48
49namespace {
50
51class BasicNetworkDelegate : public NetworkDelegate {
52 public:
53  BasicNetworkDelegate() {}
54  virtual ~BasicNetworkDelegate() {}
55
56 private:
57  virtual int OnBeforeURLRequest(URLRequest* request,
58                                 const CompletionCallback& callback,
59                                 GURL* new_url) OVERRIDE {
60    return OK;
61  }
62
63  virtual int OnBeforeSendHeaders(URLRequest* request,
64                                  const CompletionCallback& callback,
65                                  HttpRequestHeaders* headers) OVERRIDE {
66    return OK;
67  }
68
69  virtual void OnSendHeaders(URLRequest* request,
70                             const HttpRequestHeaders& headers) OVERRIDE {}
71
72  virtual int OnHeadersReceived(
73      URLRequest* request,
74      const CompletionCallback& callback,
75      const HttpResponseHeaders* original_response_headers,
76      scoped_refptr<HttpResponseHeaders>* override_response_headers,
77      GURL* allowed_unsafe_redirect_url) OVERRIDE {
78    return OK;
79  }
80
81  virtual void OnBeforeRedirect(URLRequest* request,
82                                const GURL& new_location) OVERRIDE {}
83
84  virtual void OnResponseStarted(URLRequest* request) OVERRIDE {}
85
86  virtual void OnRawBytesRead(const URLRequest& request,
87                              int bytes_read) OVERRIDE {}
88
89  virtual void OnCompleted(URLRequest* request, bool started) OVERRIDE {}
90
91  virtual void OnURLRequestDestroyed(URLRequest* request) OVERRIDE {}
92
93  virtual void OnPACScriptError(int line_number,
94                                const base::string16& error) OVERRIDE {}
95
96  virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired(
97      URLRequest* request,
98      const AuthChallengeInfo& auth_info,
99      const AuthCallback& callback,
100      AuthCredentials* credentials) OVERRIDE {
101    return NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
102  }
103
104  virtual bool OnCanGetCookies(const URLRequest& request,
105                               const CookieList& cookie_list) OVERRIDE {
106    return true;
107  }
108
109  virtual bool OnCanSetCookie(const URLRequest& request,
110                              const std::string& cookie_line,
111                              CookieOptions* options) OVERRIDE {
112    return true;
113  }
114
115  virtual bool OnCanAccessFile(const net::URLRequest& request,
116                               const base::FilePath& path) const OVERRIDE {
117    return true;
118  }
119
120  virtual bool OnCanThrottleRequest(const URLRequest& request) const OVERRIDE {
121    // Returning true will only enable throttling if there's also a
122    // URLRequestThrottlerManager, which there isn't, by default.
123    return true;
124  }
125
126  virtual int OnBeforeSocketStreamConnect(
127      SocketStream* stream,
128      const CompletionCallback& callback) OVERRIDE {
129    return OK;
130  }
131
132  DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
133};
134
135class BasicURLRequestContext : public URLRequestContext {
136 public:
137  BasicURLRequestContext()
138      : storage_(this) {}
139
140  URLRequestContextStorage* storage() {
141    return &storage_;
142  }
143
144  base::Thread* GetCacheThread() {
145    if (!cache_thread_) {
146      cache_thread_.reset(new base::Thread("Network Cache Thread"));
147      cache_thread_->StartWithOptions(
148          base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
149    }
150    return cache_thread_.get();
151  }
152
153  base::Thread* GetFileThread() {
154    if (!file_thread_) {
155      file_thread_.reset(new base::Thread("Network File Thread"));
156      file_thread_->StartWithOptions(
157          base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
158    }
159    return file_thread_.get();
160  }
161
162  void set_transport_security_persister(
163      scoped_ptr<TransportSecurityPersister> transport_security_persister) {
164    transport_security_persister = transport_security_persister.Pass();
165  }
166
167 protected:
168  virtual ~BasicURLRequestContext() {
169    AssertNoURLRequests();
170  }
171
172 private:
173  // Threads should be torn down last.
174  scoped_ptr<base::Thread> cache_thread_;
175  scoped_ptr<base::Thread> file_thread_;
176
177  URLRequestContextStorage storage_;
178  scoped_ptr<TransportSecurityPersister> transport_security_persister_;
179
180  DISALLOW_COPY_AND_ASSIGN(BasicURLRequestContext);
181};
182
183}  // namespace
184
185URLRequestContextBuilder::HttpCacheParams::HttpCacheParams()
186    : type(IN_MEMORY),
187      max_size(0) {}
188URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {}
189
190URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
191    : ignore_certificate_errors(false),
192      host_mapping_rules(NULL),
193      testing_fixed_http_port(0),
194      testing_fixed_https_port(0),
195      next_protos(NextProtosDefaults()),
196      use_alternate_protocols(true),
197      enable_quic(false) {
198}
199
200URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
201{}
202
203URLRequestContextBuilder::SchemeFactory::SchemeFactory(
204    const std::string& auth_scheme,
205    net::HttpAuthHandlerFactory* auth_handler_factory)
206    : scheme(auth_scheme), factory(auth_handler_factory) {
207}
208
209URLRequestContextBuilder::SchemeFactory::~SchemeFactory() {
210}
211
212URLRequestContextBuilder::URLRequestContextBuilder()
213    : data_enabled_(false),
214#if !defined(DISABLE_FILE_SUPPORT)
215      file_enabled_(false),
216#endif
217#if !defined(DISABLE_FTP_SUPPORT)
218      ftp_enabled_(false),
219#endif
220      http_cache_enabled_(true),
221      throttling_enabled_(false),
222      channel_id_enabled_(true) {
223}
224
225URLRequestContextBuilder::~URLRequestContextBuilder() {}
226
227void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams& params) {
228  http_cache_enabled_ = true;
229  http_cache_params_ = params;
230}
231
232void URLRequestContextBuilder::DisableHttpCache() {
233  http_cache_enabled_ = false;
234  http_cache_params_ = HttpCacheParams();
235}
236
237void URLRequestContextBuilder::SetSpdyAndQuicEnabled(bool spdy_enabled,
238                                                     bool quic_enabled) {
239  http_network_session_params_.next_protos =
240      NextProtosWithSpdyAndQuic(spdy_enabled, quic_enabled);
241  http_network_session_params_.enable_quic = quic_enabled;
242}
243
244URLRequestContext* URLRequestContextBuilder::Build() {
245  BasicURLRequestContext* context = new BasicURLRequestContext;
246  URLRequestContextStorage* storage = context->storage();
247
248  storage->set_http_user_agent_settings(new StaticHttpUserAgentSettings(
249      accept_language_, user_agent_));
250
251  if (!network_delegate_)
252    network_delegate_.reset(new BasicNetworkDelegate);
253  NetworkDelegate* network_delegate = network_delegate_.release();
254  storage->set_network_delegate(network_delegate);
255
256  if (net_log_) {
257    storage->set_net_log(net_log_.release());
258  } else {
259    storage->set_net_log(new net::NetLog);
260  }
261
262  if (!host_resolver_) {
263    host_resolver_ = net::HostResolver::CreateDefaultResolver(
264        context->net_log());
265  }
266  storage->set_host_resolver(host_resolver_.Pass());
267
268  if (!proxy_service_) {
269    // TODO(willchan): Switch to using this code when
270    // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
271  #if defined(OS_LINUX) || defined(OS_ANDROID)
272    ProxyConfigService* proxy_config_service = proxy_config_service_.release();
273  #else
274    ProxyConfigService* proxy_config_service = NULL;
275    if (proxy_config_service_) {
276      proxy_config_service = proxy_config_service_.release();
277    } else {
278      proxy_config_service =
279          ProxyService::CreateSystemProxyConfigService(
280              base::ThreadTaskRunnerHandle::Get().get(),
281              context->GetFileThread()->task_runner());
282    }
283  #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
284    proxy_service_.reset(
285        ProxyService::CreateUsingSystemProxyResolver(
286            proxy_config_service,
287            0,  // This results in using the default value.
288            context->net_log()));
289  }
290  storage->set_proxy_service(proxy_service_.release());
291
292  storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
293  HttpAuthHandlerRegistryFactory* http_auth_handler_registry_factory =
294      net::HttpAuthHandlerRegistryFactory::CreateDefault(
295           context->host_resolver());
296  for (size_t i = 0; i < extra_http_auth_handlers_.size(); ++i) {
297    http_auth_handler_registry_factory->RegisterSchemeFactory(
298        extra_http_auth_handlers_[i].scheme,
299        extra_http_auth_handlers_[i].factory);
300  }
301  storage->set_http_auth_handler_factory(http_auth_handler_registry_factory);
302  storage->set_cookie_store(new CookieMonster(NULL, NULL));
303
304  if (channel_id_enabled_) {
305    // TODO(mmenke):  This always creates a file thread, even when it ends up
306    // not being used.  Consider lazily creating the thread.
307    storage->set_channel_id_service(
308        new ChannelIDService(
309            new DefaultChannelIDStore(NULL),
310            context->GetFileThread()->message_loop_proxy()));
311  }
312
313  storage->set_transport_security_state(new net::TransportSecurityState());
314  if (!transport_security_persister_path_.empty()) {
315    context->set_transport_security_persister(
316        make_scoped_ptr<TransportSecurityPersister>(
317            new TransportSecurityPersister(
318                context->transport_security_state(),
319                transport_security_persister_path_,
320                context->GetFileThread()->message_loop_proxy(),
321                false)));
322  }
323
324  storage->set_http_server_properties(
325      scoped_ptr<net::HttpServerProperties>(
326          new net::HttpServerPropertiesImpl()));
327  storage->set_cert_verifier(CertVerifier::CreateDefault());
328
329  if (throttling_enabled_)
330    storage->set_throttler_manager(new URLRequestThrottlerManager());
331
332  net::HttpNetworkSession::Params network_session_params;
333  network_session_params.host_resolver = context->host_resolver();
334  network_session_params.cert_verifier = context->cert_verifier();
335  network_session_params.transport_security_state =
336      context->transport_security_state();
337  network_session_params.proxy_service = context->proxy_service();
338  network_session_params.ssl_config_service =
339      context->ssl_config_service();
340  network_session_params.http_auth_handler_factory =
341      context->http_auth_handler_factory();
342  network_session_params.network_delegate = network_delegate;
343  network_session_params.http_server_properties =
344      context->http_server_properties();
345  network_session_params.net_log = context->net_log();
346
347  network_session_params.ignore_certificate_errors =
348      http_network_session_params_.ignore_certificate_errors;
349  network_session_params.host_mapping_rules =
350      http_network_session_params_.host_mapping_rules;
351  network_session_params.testing_fixed_http_port =
352      http_network_session_params_.testing_fixed_http_port;
353  network_session_params.testing_fixed_https_port =
354      http_network_session_params_.testing_fixed_https_port;
355  network_session_params.use_alternate_protocols =
356    http_network_session_params_.use_alternate_protocols;
357  network_session_params.trusted_spdy_proxy =
358      http_network_session_params_.trusted_spdy_proxy;
359  network_session_params.next_protos = http_network_session_params_.next_protos;
360  network_session_params.enable_quic = http_network_session_params_.enable_quic;
361
362  HttpTransactionFactory* http_transaction_factory = NULL;
363  if (http_cache_enabled_) {
364    network_session_params.channel_id_service =
365        context->channel_id_service();
366    HttpCache::BackendFactory* http_cache_backend = NULL;
367    if (http_cache_params_.type == HttpCacheParams::DISK) {
368      http_cache_backend = new HttpCache::DefaultBackend(
369          DISK_CACHE,
370          net::CACHE_BACKEND_DEFAULT,
371          http_cache_params_.path,
372          http_cache_params_.max_size,
373          context->GetCacheThread()->task_runner());
374    } else {
375      http_cache_backend =
376          HttpCache::DefaultBackend::InMemory(http_cache_params_.max_size);
377    }
378
379    http_transaction_factory = new HttpCache(
380        network_session_params, http_cache_backend);
381  } else {
382    scoped_refptr<net::HttpNetworkSession> network_session(
383        new net::HttpNetworkSession(network_session_params));
384
385    http_transaction_factory = new HttpNetworkLayer(network_session.get());
386  }
387  storage->set_http_transaction_factory(http_transaction_factory);
388
389  URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl;
390  if (data_enabled_)
391    job_factory->SetProtocolHandler("data", new DataProtocolHandler);
392
393#if !defined(DISABLE_FILE_SUPPORT)
394  if (file_enabled_) {
395    job_factory->SetProtocolHandler(
396    "file",
397    new FileProtocolHandler(context->GetFileThread()->message_loop_proxy()));
398  }
399#endif  // !defined(DISABLE_FILE_SUPPORT)
400
401#if !defined(DISABLE_FTP_SUPPORT)
402  if (ftp_enabled_) {
403    ftp_transaction_factory_.reset(
404        new FtpNetworkLayer(context->host_resolver()));
405    job_factory->SetProtocolHandler("ftp",
406        new FtpProtocolHandler(ftp_transaction_factory_.get()));
407  }
408#endif  // !defined(DISABLE_FTP_SUPPORT)
409
410  storage->set_job_factory(job_factory);
411
412  // TODO(willchan): Support sdch.
413
414  return context;
415}
416
417}  // namespace net
418