Index: net/proxy/dhcp_proxy_script_fetcher_win.cc |
=================================================================== |
--- net/proxy/dhcp_proxy_script_fetcher_win.cc (revision 85647) |
+++ net/proxy/dhcp_proxy_script_fetcher_win.cc (working copy) |
@@ -1,246 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "net/proxy/dhcp_proxy_script_fetcher_win.h" |
- |
-#include "net/base/net_errors.h" |
-#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h" |
- |
-#include <winsock2.h> |
-#include <iphlpapi.h> |
-#pragma comment(lib, "iphlpapi.lib") |
- |
-namespace { |
- |
-// How long to wait at maximum after we get results (a PAC file or |
-// knowledge that no PAC file is configured) from whichever network |
-// adapter finishes first. |
-const int kMaxWaitAfterFirstResultMs = 400; |
- |
-} // namespace |
- |
-namespace net { |
- |
-DhcpProxyScriptFetcherWin::DhcpProxyScriptFetcherWin( |
- URLRequestContext* url_request_context) |
- : state_(STATE_START), |
- ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_callback_( |
- this, &DhcpProxyScriptFetcherWin::OnFetcherDone)), |
- num_pending_fetchers_(0), |
- url_request_context_(url_request_context) { |
- DCHECK(url_request_context_); |
-} |
- |
-DhcpProxyScriptFetcherWin::~DhcpProxyScriptFetcherWin() { |
- Cancel(); |
-} |
- |
-int DhcpProxyScriptFetcherWin::Fetch(string16* utf16_text, |
- CompletionCallback* callback) { |
- DCHECK(CalledOnValidThread()); |
- if (state_ != STATE_START && state_ != STATE_DONE) { |
- NOTREACHED(); |
- return ERR_UNEXPECTED; |
- } |
- |
- std::set<std::string> adapter_names; |
- if (!ImplGetCandidateAdapterNames(&adapter_names)) { |
- return ERR_UNEXPECTED; |
- } |
- if (adapter_names.empty()) { |
- return ERR_PAC_NOT_IN_DHCP; |
- } |
- |
- state_ = STATE_NO_RESULTS; |
- |
- client_callback_ = callback; |
- destination_string_ = utf16_text; |
- |
- for (std::set<std::string>::iterator it = adapter_names.begin(); |
- it != adapter_names.end(); |
- ++it) { |
- DhcpProxyScriptAdapterFetcher* fetcher(ImplCreateAdapterFetcher()); |
- fetcher->Fetch(*it, &fetcher_callback_); |
- fetchers_.push_back(fetcher); |
- } |
- num_pending_fetchers_ = fetchers_.size(); |
- |
- return ERR_IO_PENDING; |
-} |
- |
-void DhcpProxyScriptFetcherWin::Cancel() { |
- DCHECK(CalledOnValidThread()); |
- |
- if (state_ != STATE_DONE) { |
- wait_timer_.Stop(); |
- state_ = STATE_DONE; |
- |
- for (FetcherVector::iterator it = fetchers_.begin(); |
- it != fetchers_.end(); |
- ++it) { |
- (*it)->Cancel(); |
- } |
- |
- fetchers_.reset(); |
- } |
-} |
- |
-std::string DhcpProxyScriptFetcherWin::GetFetcherName() const { |
- DCHECK(CalledOnValidThread()); |
- return "win"; |
-} |
- |
-const GURL& DhcpProxyScriptFetcherWin::GetPacURL() const { |
- DCHECK(CalledOnValidThread()); |
- DCHECK_EQ(state_, STATE_DONE); |
- |
- return pac_url_; |
-} |
- |
-void DhcpProxyScriptFetcherWin::OnFetcherDone(int result) { |
- DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS); |
- |
- if (--num_pending_fetchers_ == 0) { |
- TransitionToDone(); |
- return; |
- } |
- |
- // If the only pending adapters are those less preferred than one |
- // with a valid PAC script, we do not need to wait any longer. |
- for (FetcherVector::iterator it = fetchers_.begin(); |
- it != fetchers_.end(); |
- ++it) { |
- bool did_finish = (*it)->DidFinish(); |
- int result = (*it)->GetResult(); |
- if (did_finish && result == OK) { |
- TransitionToDone(); |
- return; |
- } |
- if (!did_finish || result != ERR_PAC_NOT_IN_DHCP) { |
- break; |
- } |
- } |
- |
- // Once we have a single result, we set a maximum on how long to wait |
- // for the rest of the results. |
- if (state_ == STATE_NO_RESULTS) { |
- state_ = STATE_SOME_RESULTS; |
- wait_timer_.Start( |
- base::TimeDelta::FromMilliseconds(ImplGetMaxWaitMs()), |
- this, &DhcpProxyScriptFetcherWin::OnWaitTimer); |
- } |
-} |
- |
-void DhcpProxyScriptFetcherWin::OnWaitTimer() { |
- DCHECK_EQ(state_, STATE_SOME_RESULTS); |
- TransitionToDone(); |
-} |
- |
-void DhcpProxyScriptFetcherWin::TransitionToDone() { |
- DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS); |
- |
- // Should have returned immediately at Fetch() if no adapters to check. |
- DCHECK(!fetchers_.empty()); |
- |
- // Scan twice for the result; once through the whole list for success, |
- // then if no success, return result for most preferred network adapter, |
- // preferring "real" network errors to the ERR_PAC_NOT_IN_DHCP error. |
- // Default to ERR_ABORTED if no fetcher completed. |
- int result = ERR_ABORTED; |
- for (FetcherVector::iterator it = fetchers_.begin(); |
- it != fetchers_.end(); |
- ++it) { |
- if ((*it)->DidFinish() && (*it)->GetResult() == OK) { |
- result = OK; |
- *destination_string_ = (*it)->GetPacScript(); |
- pac_url_ = (*it)->GetPacURL(); |
- break; |
- } |
- } |
- if (result != OK) { |
- destination_string_->clear(); |
- for (FetcherVector::iterator it = fetchers_.begin(); |
- it != fetchers_.end(); |
- ++it) { |
- if ((*it)->DidFinish()) { |
- result = (*it)->GetResult(); |
- if (result != ERR_PAC_NOT_IN_DHCP) { |
- break; |
- } |
- } |
- } |
- } |
- |
- Cancel(); |
- DCHECK_EQ(state_, STATE_DONE); |
- DCHECK(fetchers_.empty()); |
- |
- client_callback_->Run(result); |
-} |
- |
-DhcpProxyScriptAdapterFetcher* |
- DhcpProxyScriptFetcherWin::ImplCreateAdapterFetcher() { |
- return new DhcpProxyScriptAdapterFetcher(url_request_context_); |
-} |
- |
-bool DhcpProxyScriptFetcherWin::ImplGetCandidateAdapterNames( |
- std::set<std::string>* adapter_names) { |
- return GetCandidateAdapterNames(adapter_names); |
-} |
- |
-int DhcpProxyScriptFetcherWin::ImplGetMaxWaitMs() { |
- return kMaxWaitAfterFirstResultMs; |
-} |
- |
-bool DhcpProxyScriptFetcherWin::GetCandidateAdapterNames( |
- std::set<std::string>* adapter_names) { |
- DCHECK(adapter_names); |
- adapter_names->clear(); |
- |
- // The GetAdaptersAddresses MSDN page recommends using a size of 15000 to |
- // avoid reallocation. |
- ULONG adapters_size = 15000; |
- scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> adapters; |
- ULONG error = ERROR_SUCCESS; |
- int num_tries = 0; |
- do { |
- adapters.reset( |
- reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(adapters_size))); |
- // Return only unicast addresses, and skip information we do not need. |
- error = GetAdaptersAddresses(AF_UNSPEC, |
- GAA_FLAG_SKIP_ANYCAST | |
- GAA_FLAG_SKIP_MULTICAST | |
- GAA_FLAG_SKIP_DNS_SERVER | |
- GAA_FLAG_SKIP_FRIENDLY_NAME, |
- NULL, |
- adapters.get(), |
- &adapters_size); |
- ++num_tries; |
- } while (error == ERROR_BUFFER_OVERFLOW && num_tries <= 3); |
- |
- if (error == ERROR_NO_DATA) { |
- // There are no adapters that we care about. |
- return true; |
- } |
- |
- if (error != ERROR_SUCCESS) { |
- LOG(WARNING) << "Unexpected error retrieving WPAD configuration from DHCP."; |
- return false; |
- } |
- |
- IP_ADAPTER_ADDRESSES* adapter = NULL; |
- for (adapter = adapters.get(); adapter; adapter = adapter->Next) { |
- if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) |
- continue; |
- if ((adapter->Flags & IP_ADAPTER_DHCP_ENABLED) == 0) |
- continue; |
- |
- DCHECK(adapter->AdapterName); |
- adapter_names->insert(adapter->AdapterName); |
- } |
- |
- return true; |
-} |
- |
-} // namespace net |