| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/proxy/proxy_list.h" | 5 #include "net/proxy/proxy_list.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/string_tokenizer.h" | 8 #include "base/string_tokenizer.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 | 10 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); | 54 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); |
| 55 it != proxies_.end(); ) { | 55 it != proxies_.end(); ) { |
| 56 if (!(scheme_bit_field & it->scheme())) { | 56 if (!(scheme_bit_field & it->scheme())) { |
| 57 it = proxies_.erase(it); | 57 it = proxies_.erase(it); |
| 58 continue; | 58 continue; |
| 59 } | 59 } |
| 60 ++it; | 60 ++it; |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 | 63 |
| 64 ProxyServer ProxyList::Get() const { | 64 bool ProxyList::IsEmpty() const { |
| 65 if (!proxies_.empty()) | 65 return proxies_.empty(); |
| 66 return proxies_[0]; | 66 } |
| 67 return ProxyServer(ProxyServer::SCHEME_DIRECT, std::string(), -1); | 67 |
| 68 const ProxyServer& ProxyList::Get() const { |
| 69 DCHECK(!proxies_.empty()); |
| 70 return proxies_[0]; |
| 68 } | 71 } |
| 69 | 72 |
| 70 std::string ProxyList::ToPacString() const { | 73 std::string ProxyList::ToPacString() const { |
| 71 std::string proxy_list; | 74 std::string proxy_list; |
| 72 std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); | 75 std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); |
| 73 for (; iter != proxies_.end(); ++iter) { | 76 for (; iter != proxies_.end(); ++iter) { |
| 74 if (!proxy_list.empty()) | 77 if (!proxy_list.empty()) |
| 75 proxy_list += ";"; | 78 proxy_list += ";"; |
| 76 proxy_list += iter->ToPacString(); | 79 proxy_list += iter->ToPacString(); |
| 77 } | 80 } |
| 78 return proxy_list.empty() ? "DIRECT" : proxy_list; | 81 return proxy_list.empty() ? std::string() : proxy_list; |
| 79 } | 82 } |
| 80 | 83 |
| 81 void ProxyList::SetFromPacString(const std::string& pac_string) { | 84 void ProxyList::SetFromPacString(const std::string& pac_string) { |
| 82 StringTokenizer entry_tok(pac_string, ";"); | 85 StringTokenizer entry_tok(pac_string, ";"); |
| 83 proxies_.clear(); | 86 proxies_.clear(); |
| 84 while (entry_tok.GetNext()) { | 87 while (entry_tok.GetNext()) { |
| 85 ProxyServer uri = ProxyServer::FromPacString( | 88 ProxyServer uri = ProxyServer::FromPacString( |
| 86 entry_tok.token_begin(), entry_tok.token_end()); | 89 entry_tok.token_begin(), entry_tok.token_end()); |
| 87 // Silently discard malformed inputs. | 90 // Silently discard malformed inputs. |
| 88 if (uri.is_valid()) | 91 if (uri.is_valid()) |
| 89 proxies_.push_back(uri); | 92 proxies_.push_back(uri); |
| 90 } | 93 } |
| 94 |
| 95 // If we failed to parse anything from the PAC results list, fallback to |
| 96 // DIRECT (this basically means an error in the PAC script). |
| 97 if (proxies_.empty()) { |
| 98 proxies_.push_back(ProxyServer::Direct()); |
| 99 } |
| 91 } | 100 } |
| 92 | 101 |
| 93 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { | 102 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info) { |
| 94 // Number of minutes to wait before retrying a bad proxy server. | 103 // Number of minutes to wait before retrying a bad proxy server. |
| 95 const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); | 104 const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); |
| 96 | 105 |
| 106 // TODO(eroman): It would be good if instead of removing failed proxies |
| 107 // from the list, we simply annotated them with the error code they failed |
| 108 // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to |
| 109 // be given this information by the network transaction. |
| 110 // |
| 111 // The advantage of this approach is when the network transaction |
| 112 // fails, we could output the full list of proxies that were attempted, and |
| 113 // why each one of those failed (as opposed to just the last failure). |
| 114 // |
| 115 // And also, before failing the transaction wholesale, we could go back and |
| 116 // retry the "bad proxies" which we never tried to begin with. |
| 117 // (RemoveBadProxies would annotate them as 'expected bad' rather then delete |
| 118 // them from the list, so we would know what they were). |
| 119 |
| 97 if (proxies_.empty()) { | 120 if (proxies_.empty()) { |
| 98 NOTREACHED(); | 121 NOTREACHED(); |
| 99 return false; | 122 return false; |
| 100 } | 123 } |
| 101 | 124 |
| 102 std::string key = proxies_[0].ToURI(); | 125 if (!proxies_[0].is_direct()) { |
| 103 | 126 std::string key = proxies_[0].ToURI(); |
| 104 // Mark this proxy as bad. | 127 // Mark this proxy as bad. |
| 105 ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); | 128 ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); |
| 106 if (iter != proxy_retry_info->end()) { | 129 if (iter != proxy_retry_info->end()) { |
| 107 // TODO(nsylvain): This is not the first time we get this. We should | 130 // TODO(nsylvain): This is not the first time we get this. We should |
| 108 // double the retry time. Bug 997660. | 131 // double the retry time. Bug 997660. |
| 109 iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; | 132 iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; |
| 110 } else { | 133 } else { |
| 111 ProxyRetryInfo retry_info; | 134 ProxyRetryInfo retry_info; |
| 112 retry_info.current_delay = kProxyRetryDelay; | 135 retry_info.current_delay = kProxyRetryDelay; |
| 113 retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; | 136 retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; |
| 114 (*proxy_retry_info)[key] = retry_info; | 137 (*proxy_retry_info)[key] = retry_info; |
| 138 } |
| 115 } | 139 } |
| 116 | 140 |
| 117 // Remove this proxy from our list. | 141 // Remove this proxy from our list. |
| 118 proxies_.erase(proxies_.begin()); | 142 proxies_.erase(proxies_.begin()); |
| 119 | 143 |
| 120 return !proxies_.empty(); | 144 return !proxies_.empty(); |
| 121 } | 145 } |
| 122 | 146 |
| 123 } // namespace net | 147 } // namespace net |
| OLD | NEW |