| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 10 #include "base/strings/string_tokenizer.h" | 10 #include "base/strings/string_tokenizer.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 if (bad_proxy->second.try_while_bad) | 64 if (bad_proxy->second.try_while_bad) |
| 65 bad_proxies_to_try.push_back(*iter); | 65 bad_proxies_to_try.push_back(*iter); |
| 66 continue; | 66 continue; |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 good_proxies.push_back(*iter); | 69 good_proxies.push_back(*iter); |
| 70 } | 70 } |
| 71 | 71 |
| 72 // "proxies_ = good_proxies + bad_proxies" | 72 // "proxies_ = good_proxies + bad_proxies" |
| 73 proxies_.swap(good_proxies); | 73 proxies_.swap(good_proxies); |
| 74 proxies_.insert(proxies_.end(), bad_proxies_to_try.begin(), | 74 proxies_.insert( |
| 75 bad_proxies_to_try.end()); | 75 proxies_.end(), bad_proxies_to_try.begin(), bad_proxies_to_try.end()); |
| 76 } | 76 } |
| 77 | 77 |
| 78 void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { | 78 void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { |
| 79 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); | 79 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); |
| 80 it != proxies_.end(); ) { | 80 it != proxies_.end();) { |
| 81 if (!(scheme_bit_field & it->scheme())) { | 81 if (!(scheme_bit_field & it->scheme())) { |
| 82 it = proxies_.erase(it); | 82 it = proxies_.erase(it); |
| 83 continue; | 83 continue; |
| 84 } | 84 } |
| 85 ++it; | 85 ++it; |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 void ProxyList::Clear() { | 89 void ProxyList::Clear() { |
| 90 proxies_.clear(); | 90 proxies_.clear(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 107 | 107 |
| 108 const ProxyServer& ProxyList::Get() const { | 108 const ProxyServer& ProxyList::Get() const { |
| 109 DCHECK(!proxies_.empty()); | 109 DCHECK(!proxies_.empty()); |
| 110 return proxies_[0]; | 110 return proxies_[0]; |
| 111 } | 111 } |
| 112 | 112 |
| 113 void ProxyList::SetFromPacString(const std::string& pac_string) { | 113 void ProxyList::SetFromPacString(const std::string& pac_string) { |
| 114 base::StringTokenizer entry_tok(pac_string, ";"); | 114 base::StringTokenizer entry_tok(pac_string, ";"); |
| 115 proxies_.clear(); | 115 proxies_.clear(); |
| 116 while (entry_tok.GetNext()) { | 116 while (entry_tok.GetNext()) { |
| 117 ProxyServer uri = ProxyServer::FromPacString( | 117 ProxyServer uri = ProxyServer::FromPacString(entry_tok.token_begin(), |
| 118 entry_tok.token_begin(), entry_tok.token_end()); | 118 entry_tok.token_end()); |
| 119 // Silently discard malformed inputs. | 119 // Silently discard malformed inputs. |
| 120 if (uri.is_valid()) | 120 if (uri.is_valid()) |
| 121 proxies_.push_back(uri); | 121 proxies_.push_back(uri); |
| 122 } | 122 } |
| 123 | 123 |
| 124 // If we failed to parse anything from the PAC results list, fallback to | 124 // If we failed to parse anything from the PAC results list, fallback to |
| 125 // DIRECT (this basically means an error in the PAC script). | 125 // DIRECT (this basically means an error in the PAC script). |
| 126 if (proxies_.empty()) { | 126 if (proxies_.empty()) { |
| 127 proxies_.push_back(ProxyServer::Direct()); | 127 proxies_.push_back(ProxyServer::Direct()); |
| 128 } | 128 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 141 | 141 |
| 142 base::ListValue* ProxyList::ToValue() const { | 142 base::ListValue* ProxyList::ToValue() const { |
| 143 base::ListValue* list = new base::ListValue(); | 143 base::ListValue* list = new base::ListValue(); |
| 144 for (size_t i = 0; i < proxies_.size(); ++i) | 144 for (size_t i = 0; i < proxies_.size(); ++i) |
| 145 list->AppendString(proxies_[i].ToURI()); | 145 list->AppendString(proxies_[i].ToURI()); |
| 146 return list; | 146 return list; |
| 147 } | 147 } |
| 148 | 148 |
| 149 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info, | 149 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info, |
| 150 const BoundNetLog& net_log) { | 150 const BoundNetLog& net_log) { |
| 151 | |
| 152 // TODO(eroman): It would be good if instead of removing failed proxies | 151 // TODO(eroman): It would be good if instead of removing failed proxies |
| 153 // from the list, we simply annotated them with the error code they failed | 152 // from the list, we simply annotated them with the error code they failed |
| 154 // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to | 153 // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to |
| 155 // be given this information by the network transaction. | 154 // be given this information by the network transaction. |
| 156 // | 155 // |
| 157 // The advantage of this approach is when the network transaction | 156 // The advantage of this approach is when the network transaction |
| 158 // fails, we could output the full list of proxies that were attempted, and | 157 // fails, we could output the full list of proxies that were attempted, and |
| 159 // why each one of those failed (as opposed to just the last failure). | 158 // why each one of those failed (as opposed to just the last failure). |
| 160 // | 159 // |
| 161 // And also, before failing the transaction wholesale, we could go back and | 160 // And also, before failing the transaction wholesale, we could go back and |
| 162 // retry the "bad proxies" which we never tried to begin with. | 161 // retry the "bad proxies" which we never tried to begin with. |
| 163 // (RemoveBadProxies would annotate them as 'expected bad' rather then delete | 162 // (RemoveBadProxies would annotate them as 'expected bad' rather then delete |
| 164 // them from the list, so we would know what they were). | 163 // them from the list, so we would know what they were). |
| 165 | 164 |
| 166 if (proxies_.empty()) { | 165 if (proxies_.empty()) { |
| 167 NOTREACHED(); | 166 NOTREACHED(); |
| 168 return false; | 167 return false; |
| 169 } | 168 } |
| 170 UpdateRetryInfoOnFallback(proxy_retry_info, base::TimeDelta(), true, | 169 UpdateRetryInfoOnFallback( |
| 171 ProxyServer(), net_log); | 170 proxy_retry_info, base::TimeDelta(), true, ProxyServer(), net_log); |
| 172 | 171 |
| 173 // Remove this proxy from our list. | 172 // Remove this proxy from our list. |
| 174 proxies_.erase(proxies_.begin()); | 173 proxies_.erase(proxies_.begin()); |
| 175 return !proxies_.empty(); | 174 return !proxies_.empty(); |
| 176 } | 175 } |
| 177 | 176 |
| 178 void ProxyList::AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info, | 177 void ProxyList::AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info, |
| 179 base::TimeDelta retry_delay, | 178 base::TimeDelta retry_delay, |
| 180 bool try_while_bad, | 179 bool try_while_bad, |
| 181 const ProxyServer& proxy_to_retry, | 180 const ProxyServer& proxy_to_retry, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 201 void ProxyList::UpdateRetryInfoOnFallback( | 200 void ProxyList::UpdateRetryInfoOnFallback( |
| 202 ProxyRetryInfoMap* proxy_retry_info, | 201 ProxyRetryInfoMap* proxy_retry_info, |
| 203 base::TimeDelta retry_delay, | 202 base::TimeDelta retry_delay, |
| 204 bool reconsider, | 203 bool reconsider, |
| 205 const ProxyServer& another_proxy_to_bypass, | 204 const ProxyServer& another_proxy_to_bypass, |
| 206 const BoundNetLog& net_log) const { | 205 const BoundNetLog& net_log) const { |
| 207 // Time to wait before retrying a bad proxy server. | 206 // Time to wait before retrying a bad proxy server. |
| 208 if (retry_delay == base::TimeDelta()) { | 207 if (retry_delay == base::TimeDelta()) { |
| 209 #if defined(SPDY_PROXY_AUTH_ORIGIN) | 208 #if defined(SPDY_PROXY_AUTH_ORIGIN) |
| 210 // Randomize the timeout over a range from one to five minutes. | 209 // Randomize the timeout over a range from one to five minutes. |
| 211 retry_delay = | 210 retry_delay = TimeDelta::FromMilliseconds( |
| 212 TimeDelta::FromMilliseconds( | 211 base::RandInt(1 * 60 * 1000, 5 * 60 * 1000)); |
| 213 base::RandInt(1 * 60 * 1000, 5 * 60 * 1000)); | |
| 214 #else | 212 #else |
| 215 retry_delay = TimeDelta::FromMinutes(5); | 213 retry_delay = TimeDelta::FromMinutes(5); |
| 216 #endif | 214 #endif |
| 217 } | 215 } |
| 218 | 216 |
| 219 if (proxies_.empty()) { | 217 if (proxies_.empty()) { |
| 220 NOTREACHED(); | 218 NOTREACHED(); |
| 221 return; | 219 return; |
| 222 } | 220 } |
| 223 | 221 |
| 224 if (!proxies_[0].is_direct()) { | 222 if (!proxies_[0].is_direct()) { |
| 225 AddProxyToRetryList(proxy_retry_info, retry_delay, reconsider, proxies_[0], | 223 AddProxyToRetryList( |
| 226 net_log); | 224 proxy_retry_info, retry_delay, reconsider, proxies_[0], net_log); |
| 227 | 225 |
| 228 // If an additional proxy to bypass is specified, add it to the retry map | 226 // If an additional proxy to bypass is specified, add it to the retry map |
| 229 // as well. | 227 // as well. |
| 230 if (another_proxy_to_bypass.is_valid()) { | 228 if (another_proxy_to_bypass.is_valid()) { |
| 231 AddProxyToRetryList(proxy_retry_info, retry_delay, reconsider, | 229 AddProxyToRetryList(proxy_retry_info, |
| 232 another_proxy_to_bypass, net_log); | 230 retry_delay, |
| 231 reconsider, |
| 232 another_proxy_to_bypass, |
| 233 net_log); |
| 233 } | 234 } |
| 234 } | 235 } |
| 235 } | 236 } |
| 236 | 237 |
| 237 } // namespace net | 238 } // namespace net |
| OLD | NEW |