15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_list.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_server.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyList::ProxyList() {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyList::~ProxyList() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::Set(const std::string& proxy_uri_list) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.clear();
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer str_tok(proxy_uri_list, ";");
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (str_tok.GetNext()) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyServer uri = ProxyServer::FromURI(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        str_tok.token_begin(), str_tok.token_end(), ProxyServer::SCHEME_HTTP);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Silently discard malformed inputs.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uri.is_valid())
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxies_.push_back(uri);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::SetSingleProxyServer(const ProxyServer& proxy_server) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.clear();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddProxyServer(proxy_server);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyList::AddProxyServer(const ProxyServer& proxy_server) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxy_server.is_valid())
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxies_.push_back(proxy_server);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::DeprioritizeBadProxies(
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyRetryInfoMap& proxy_retry_info) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Partition the proxy list in two:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   (1) the known bad proxies
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   (2) everything else
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ProxyServer> good_proxies;
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<ProxyServer> bad_proxies_to_try;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ProxyServer>::const_iterator iter = proxies_.begin();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; iter != proxies_.end(); ++iter) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyRetryInfoMap::const_iterator bad_proxy =
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_retry_info.find(iter->ToURI());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bad_proxy != proxy_retry_info.end()) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This proxy is bad. Check if it's time to retry.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (bad_proxy->second.bad_until >= TimeTicks::Now()) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // still invalid.
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (bad_proxy->second.try_while_bad)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          bad_proxies_to_try.push_back(*iter);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    good_proxies.push_back(*iter);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "proxies_ = good_proxies + bad_proxies"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.swap(good_proxies);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  proxies_.insert(proxies_.end(), bad_proxies_to_try.begin(),
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  bad_proxies_to_try.end());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<ProxyServer>::iterator it = proxies_.begin();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != proxies_.end(); ) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(scheme_bit_field & it->scheme())) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it = proxies_.erase(it);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::Clear() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.clear();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyList::IsEmpty() const {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxies_.empty();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ProxyList::size() const {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxies_.size();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if |*this| lists the same proxies as |other|.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyList::Equals(const ProxyList& other) const {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size() != other.size())
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return proxies_ == other.proxies_;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyServer& ProxyList::Get() const {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!proxies_.empty());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxies_[0];
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyList::SetFromPacString(const std::string& pac_string) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer entry_tok(pac_string, ";");
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.clear();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (entry_tok.GetNext()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyServer uri = ProxyServer::FromPacString(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry_tok.token_begin(), entry_tok.token_end());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Silently discard malformed inputs.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (uri.is_valid())
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxies_.push_back(uri);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we failed to parse anything from the PAC results list, fallback to
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DIRECT (this basically means an error in the PAC script).
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxies_.empty()) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxies_.push_back(ProxyServer::Direct());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProxyList::ToPacString() const {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string proxy_list;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ProxyServer>::const_iterator iter = proxies_.begin();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; iter != proxies_.end(); ++iter) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!proxy_list.empty())
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_list += ";";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_list += iter->ToPacString();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_list.empty() ? std::string() : proxy_list;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::ListValue* ProxyList::ToValue() const {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue* list = new base::ListValue();
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < proxies_.size(); ++i)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    list->AppendString(proxies_[i].ToURI());
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return list;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info,
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         int net_error,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const BoundNetLog& net_log) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): It would be good if instead of removing failed proxies
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the list, we simply annotated them with the error code they failed
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be given this information by the network transaction.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The advantage of this approach is when the network transaction
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fails, we could output the full list of proxies that were attempted, and
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // why each one of those failed (as opposed to just the last failure).
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And also, before failing the transaction wholesale, we could go back and
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // retry the "bad proxies" which we never tried to begin with.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (RemoveBadProxies would annotate them as 'expected bad' rather then delete
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them from the list, so we would know what they were).
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxies_.empty()) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // By default, proxies are not retried for 5 minutes.
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateRetryInfoOnFallback(proxy_retry_info,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            TimeDelta::FromMinutes(5),
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            true,
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            ProxyServer(),
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                            net_error,
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            net_log);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove this proxy from our list.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxies_.erase(proxies_.begin());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !proxies_.empty();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProxyList::AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info,
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    base::TimeDelta retry_delay,
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    bool try_while_bad,
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const ProxyServer& proxy_to_retry,
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    int net_error,
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const BoundNetLog& net_log) const {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Mark this proxy as bad.
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string proxy_key = proxy_to_retry.ToURI();
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(proxy_key);
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter != proxy_retry_info->end()) {
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(nsylvain): This is not the first time we get this. We should
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // double the retry time. Bug 997660.
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ProxyRetryInfo retry_info;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    retry_info.current_delay = retry_delay;
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay;
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    retry_info.try_while_bad = try_while_bad;
20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    retry_info.net_error = net_error;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*proxy_retry_info)[proxy_key] = retry_info;
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net_log.AddEvent(NetLog::TYPE_PROXY_LIST_FALLBACK,
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   NetLog::StringCallback("bad_proxy", &proxy_key));
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProxyList::UpdateRetryInfoOnFallback(
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ProxyRetryInfoMap* proxy_retry_info,
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::TimeDelta retry_delay,
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool reconsider,
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ProxyServer& another_proxy_to_bypass,
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int net_error,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const BoundNetLog& net_log) const {
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(retry_delay != base::TimeDelta());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proxies_.empty()) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proxies_[0].is_direct()) {
22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    AddProxyToRetryList(proxy_retry_info,
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        retry_delay,
22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        reconsider,
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        proxies_[0],
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        net_error,
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        net_log);
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If an additional proxy to bypass is specified, add it to the retry map
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // as well.
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (another_proxy_to_bypass.is_valid()) {
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      AddProxyToRetryList(proxy_retry_info,
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          retry_delay,
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          reconsider,
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          another_proxy_to_bypass,
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          net_error,
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          net_log);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
244