OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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/proxy/init_proxy_resolver.h" |
| 6 |
| 7 #include "base/compiler_specific.h" |
| 8 #include "base/logging.h" |
| 9 #include "net/base/net_errors.h" |
| 10 #include "net/proxy/proxy_config.h" |
| 11 #include "net/proxy/proxy_resolver.h" |
| 12 #include "net/proxy/proxy_script_fetcher.h" |
| 13 |
| 14 namespace net { |
| 15 |
| 16 InitProxyResolver::InitProxyResolver(ProxyResolver* resolver, |
| 17 ProxyScriptFetcher* proxy_script_fetcher) |
| 18 : resolver_(resolver), |
| 19 proxy_script_fetcher_(proxy_script_fetcher), |
| 20 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( |
| 21 this, &InitProxyResolver::OnIOCompletion)), |
| 22 user_callback_(NULL), |
| 23 current_pac_url_index_(0u), |
| 24 next_state_(STATE_NONE) { |
| 25 } |
| 26 |
| 27 InitProxyResolver::~InitProxyResolver() { |
| 28 switch (next_state_) { |
| 29 case STATE_FETCH_PAC_SCRIPT_COMPLETE: |
| 30 proxy_script_fetcher_->Cancel(); |
| 31 break; |
| 32 case STATE_SET_PAC_SCRIPT_COMPLETE: |
| 33 resolver_->CancelSetPacScript(); |
| 34 break; |
| 35 default: |
| 36 break; |
| 37 } |
| 38 } |
| 39 |
| 40 int InitProxyResolver::Init(const ProxyConfig& config, |
| 41 CompletionCallback* callback) { |
| 42 DCHECK_EQ(STATE_NONE, next_state_); |
| 43 DCHECK(callback); |
| 44 DCHECK(config.MayRequirePACResolver()); |
| 45 |
| 46 pac_urls_ = BuildPacUrlsFallbackList(config); |
| 47 DCHECK(!pac_urls_.empty()); |
| 48 |
| 49 next_state_ = GetStartState(); |
| 50 |
| 51 int rv = DoLoop(OK); |
| 52 if (rv == ERR_IO_PENDING) |
| 53 user_callback_ = callback; |
| 54 return rv; |
| 55 } |
| 56 |
| 57 // Initialize the fallback rules. |
| 58 // (1) WPAD |
| 59 // (2) Custom PAC URL. |
| 60 InitProxyResolver::UrlList InitProxyResolver::BuildPacUrlsFallbackList( |
| 61 const ProxyConfig& config) const { |
| 62 UrlList pac_urls; |
| 63 if (config.auto_detect) { |
| 64 GURL pac_url = resolver_->expects_pac_bytes() ? |
| 65 GURL("http://wpad/wpad.dat") : GURL(); |
| 66 pac_urls.push_back(pac_url); |
| 67 } |
| 68 if (config.pac_url.is_valid()) |
| 69 pac_urls.push_back(config.pac_url); |
| 70 return pac_urls; |
| 71 } |
| 72 |
| 73 void InitProxyResolver::OnIOCompletion(int result) { |
| 74 DCHECK_NE(STATE_NONE, next_state_); |
| 75 int rv = DoLoop(result); |
| 76 if (rv != ERR_IO_PENDING) |
| 77 DoCallback(rv); |
| 78 } |
| 79 |
| 80 int InitProxyResolver::DoLoop(int result) { |
| 81 DCHECK_NE(next_state_, STATE_NONE); |
| 82 int rv = result; |
| 83 do { |
| 84 State state = next_state_; |
| 85 next_state_ = STATE_NONE; |
| 86 switch (state) { |
| 87 case STATE_FETCH_PAC_SCRIPT: |
| 88 DCHECK_EQ(OK, rv); |
| 89 rv = DoFetchPacScript(); |
| 90 break; |
| 91 case STATE_FETCH_PAC_SCRIPT_COMPLETE: |
| 92 rv = DoFetchPacScriptComplete(rv); |
| 93 break; |
| 94 case STATE_SET_PAC_SCRIPT: |
| 95 DCHECK_EQ(OK, rv); |
| 96 rv = DoSetPacScript(); |
| 97 break; |
| 98 case STATE_SET_PAC_SCRIPT_COMPLETE: |
| 99 rv = DoSetPacScriptComplete(rv); |
| 100 break; |
| 101 default: |
| 102 NOTREACHED() << "bad state"; |
| 103 rv = ERR_UNEXPECTED; |
| 104 break; |
| 105 } |
| 106 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 107 return rv; |
| 108 } |
| 109 |
| 110 void InitProxyResolver::DoCallback(int result) { |
| 111 DCHECK_NE(ERR_IO_PENDING, result); |
| 112 DCHECK(user_callback_); |
| 113 user_callback_->Run(result); |
| 114 } |
| 115 |
| 116 int InitProxyResolver::DoFetchPacScript() { |
| 117 DCHECK(resolver_->expects_pac_bytes()); |
| 118 |
| 119 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; |
| 120 |
| 121 const GURL& pac_url = current_pac_url(); |
| 122 |
| 123 LOG(INFO) << "Starting fetch of PAC script " << pac_url; |
| 124 |
| 125 return proxy_script_fetcher_->Fetch(pac_url, &pac_bytes_, &io_callback_); |
| 126 } |
| 127 |
| 128 int InitProxyResolver::DoFetchPacScriptComplete(int result) { |
| 129 DCHECK(resolver_->expects_pac_bytes()); |
| 130 |
| 131 LOG(INFO) << "Completed PAC script fetch of " << current_pac_url() |
| 132 << " with result " << ErrorToString(result) |
| 133 << ". Fetched a total of " << pac_bytes_.size() << " bytes"; |
| 134 |
| 135 if (result != OK) |
| 136 return TryToFallbackPacUrl(result); |
| 137 |
| 138 next_state_ = STATE_SET_PAC_SCRIPT; |
| 139 return result; |
| 140 } |
| 141 |
| 142 int InitProxyResolver::DoSetPacScript() { |
| 143 const GURL& pac_url = current_pac_url(); |
| 144 |
| 145 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; |
| 146 |
| 147 return resolver_->expects_pac_bytes() ? |
| 148 resolver_->SetPacScriptByData(pac_bytes_, &io_callback_) : |
| 149 resolver_->SetPacScriptByUrl(pac_url, &io_callback_); |
| 150 } |
| 151 |
| 152 int InitProxyResolver::DoSetPacScriptComplete(int result) { |
| 153 if (result != OK) { |
| 154 LOG(INFO) << "Failed configuring PAC using " << current_pac_url() |
| 155 << " with error " << ErrorToString(result); |
| 156 return TryToFallbackPacUrl(result); |
| 157 } |
| 158 return result; |
| 159 } |
| 160 |
| 161 int InitProxyResolver::TryToFallbackPacUrl(int error) { |
| 162 DCHECK_LT(error, 0); |
| 163 |
| 164 if (current_pac_url_index_ + 1 >= pac_urls_.size()) { |
| 165 // Nothing left to fall back to. |
| 166 return error; |
| 167 } |
| 168 |
| 169 // Advance to next URL in our list. |
| 170 ++current_pac_url_index_; |
| 171 |
| 172 LOG(INFO) << "Falling back to next PAC URL..."; |
| 173 |
| 174 next_state_ = GetStartState(); |
| 175 |
| 176 return OK; |
| 177 } |
| 178 |
| 179 InitProxyResolver::State InitProxyResolver::GetStartState() const { |
| 180 return resolver_->expects_pac_bytes() ? |
| 181 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; |
| 182 } |
| 183 |
| 184 const GURL& InitProxyResolver::current_pac_url() const { |
| 185 DCHECK_LT(current_pac_url_index_, pac_urls_.size()); |
| 186 return pac_urls_[current_pac_url_index_]; |
| 187 } |
| 188 |
| 189 } // namespace net |
OLD | NEW |