| Index: net/proxy/dhcp_proxy_script_fetcher_win.cc
|
| diff --git a/net/proxy/dhcp_proxy_script_fetcher_win.cc b/net/proxy/dhcp_proxy_script_fetcher_win.cc
|
| deleted file mode 100644
|
| index 8870e94166aa81095a551b6ea8d60449fb3993a7..0000000000000000000000000000000000000000
|
| --- a/net/proxy/dhcp_proxy_script_fetcher_win.cc
|
| +++ /dev/null
|
| @@ -1,359 +0,0 @@
|
| -// Copyright (c) 2012 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 "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/threading/sequenced_worker_pool.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 many threads to use at maximum to do DHCP lookups. This is
|
| -// chosen based on the following UMA data:
|
| -// - When OnWaitTimer fires, ~99.8% of users have 6 or fewer network
|
| -// adapters enabled for DHCP in total.
|
| -// - At the same measurement point, ~99.7% of users have 3 or fewer pending
|
| -// DHCP adapter lookups.
|
| -// - There is however a very long and thin tail of users who have
|
| -// systems reporting up to 100+ adapters (this must be some very weird
|
| -// OS bug (?), probably the cause of http://crbug.com/240034).
|
| -//
|
| -// The maximum number of threads is chosen such that even systems that
|
| -// report a huge number of network adapters should not run out of
|
| -// memory from this number of threads, while giving a good chance of
|
| -// getting back results for any responsive adapters.
|
| -//
|
| -// The ~99.8% of systems that have 6 or fewer network adapters will
|
| -// not grow the thread pool to its maximum size (rather, they will
|
| -// grow it to 6 or fewer threads) so setting the limit lower would not
|
| -// improve performance or memory usage on those systems.
|
| -const int kMaxDhcpLookupThreads = 12;
|
| -
|
| -// 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;
|
| -
|
| -const int kGetAdaptersAddressesErrors[] = {
|
| - ERROR_ADDRESS_NOT_ASSOCIATED,
|
| - ERROR_BUFFER_OVERFLOW,
|
| - ERROR_INVALID_PARAMETER,
|
| - ERROR_NOT_ENOUGH_MEMORY,
|
| - ERROR_NO_DATA,
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -namespace net {
|
| -
|
| -DhcpProxyScriptFetcherWin::DhcpProxyScriptFetcherWin(
|
| - URLRequestContext* url_request_context)
|
| - : state_(STATE_START),
|
| - num_pending_fetchers_(0),
|
| - destination_string_(NULL),
|
| - url_request_context_(url_request_context) {
|
| - DCHECK(url_request_context_);
|
| -
|
| - worker_pool_ = new base::SequencedWorkerPool(kMaxDhcpLookupThreads,
|
| - "PacDhcpLookup");
|
| -}
|
| -
|
| -DhcpProxyScriptFetcherWin::~DhcpProxyScriptFetcherWin() {
|
| - // Count as user-initiated if we are not yet in STATE_DONE.
|
| - Cancel();
|
| -
|
| - worker_pool_->Shutdown();
|
| -}
|
| -
|
| -int DhcpProxyScriptFetcherWin::Fetch(base::string16* utf16_text,
|
| - const CompletionCallback& callback) {
|
| - DCHECK(CalledOnValidThread());
|
| - if (state_ != STATE_START && state_ != STATE_DONE) {
|
| - NOTREACHED();
|
| - return ERR_UNEXPECTED;
|
| - }
|
| -
|
| - state_ = STATE_WAIT_ADAPTERS;
|
| - callback_ = callback;
|
| - destination_string_ = utf16_text;
|
| -
|
| - last_query_ = ImplCreateAdapterQuery();
|
| - GetTaskRunner()->PostTaskAndReply(
|
| - FROM_HERE,
|
| - base::Bind(
|
| - &DhcpProxyScriptFetcherWin::AdapterQuery::GetCandidateAdapterNames,
|
| - last_query_.get()),
|
| - base::Bind(
|
| - &DhcpProxyScriptFetcherWin::OnGetCandidateAdapterNamesDone,
|
| - AsWeakPtr(),
|
| - last_query_));
|
| -
|
| - return ERR_IO_PENDING;
|
| -}
|
| -
|
| -void DhcpProxyScriptFetcherWin::Cancel() {
|
| - DCHECK(CalledOnValidThread());
|
| -
|
| - CancelImpl();
|
| -}
|
| -
|
| -void DhcpProxyScriptFetcherWin::CancelImpl() {
|
| - DCHECK(CalledOnValidThread());
|
| -
|
| - if (state_ != STATE_DONE) {
|
| - callback_.Reset();
|
| - wait_timer_.Stop();
|
| - state_ = STATE_DONE;
|
| -
|
| - for (FetcherVector::iterator it = fetchers_.begin();
|
| - it != fetchers_.end();
|
| - ++it) {
|
| - (*it)->Cancel();
|
| - }
|
| -
|
| - fetchers_.clear();
|
| - }
|
| -}
|
| -
|
| -void DhcpProxyScriptFetcherWin::OnGetCandidateAdapterNamesDone(
|
| - scoped_refptr<AdapterQuery> query) {
|
| - DCHECK(CalledOnValidThread());
|
| -
|
| - // This can happen if this object is reused for multiple queries,
|
| - // and a previous query was cancelled before it completed.
|
| - if (query.get() != last_query_.get())
|
| - return;
|
| - last_query_ = NULL;
|
| -
|
| - // Enable unit tests to wait for this to happen; in production this function
|
| - // call is a no-op.
|
| - ImplOnGetCandidateAdapterNamesDone();
|
| -
|
| - // We may have been cancelled.
|
| - if (state_ != STATE_WAIT_ADAPTERS)
|
| - return;
|
| -
|
| - state_ = STATE_NO_RESULTS;
|
| -
|
| - const std::set<std::string>& adapter_names = query->adapter_names();
|
| -
|
| - if (adapter_names.empty()) {
|
| - TransitionToDone();
|
| - return;
|
| - }
|
| -
|
| - for (std::set<std::string>::const_iterator it = adapter_names.begin();
|
| - it != adapter_names.end();
|
| - ++it) {
|
| - DhcpProxyScriptAdapterFetcher* fetcher(ImplCreateAdapterFetcher());
|
| - fetcher->Fetch(
|
| - *it, base::Bind(&DhcpProxyScriptFetcherWin::OnFetcherDone,
|
| - base::Unretained(this)));
|
| - fetchers_.push_back(fetcher);
|
| - }
|
| - num_pending_fetchers_ = fetchers_.size();
|
| -}
|
| -
|
| -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(FROM_HERE,
|
| - ImplGetMaxWait(), 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);
|
| -
|
| - int result = ERR_PAC_NOT_IN_DHCP; // Default if no fetchers.
|
| - if (!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.
|
| - 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;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - CompletionCallback callback = callback_;
|
| - CancelImpl();
|
| - DCHECK_EQ(state_, STATE_DONE);
|
| - DCHECK(fetchers_.empty());
|
| - DCHECK(callback_.is_null()); // Invariant of data.
|
| -
|
| - // We may be deleted re-entrantly within this outcall.
|
| - callback.Run(result);
|
| -}
|
| -
|
| -int DhcpProxyScriptFetcherWin::num_pending_fetchers() const {
|
| - return num_pending_fetchers_;
|
| -}
|
| -
|
| -URLRequestContext* DhcpProxyScriptFetcherWin::url_request_context() const {
|
| - return url_request_context_;
|
| -}
|
| -
|
| -scoped_refptr<base::TaskRunner> DhcpProxyScriptFetcherWin::GetTaskRunner() {
|
| - return worker_pool_->GetTaskRunnerWithShutdownBehavior(
|
| - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
|
| -}
|
| -
|
| -DhcpProxyScriptAdapterFetcher*
|
| - DhcpProxyScriptFetcherWin::ImplCreateAdapterFetcher() {
|
| - return new DhcpProxyScriptAdapterFetcher(url_request_context_,
|
| - GetTaskRunner());
|
| -}
|
| -
|
| -DhcpProxyScriptFetcherWin::AdapterQuery*
|
| - DhcpProxyScriptFetcherWin::ImplCreateAdapterQuery() {
|
| - return new AdapterQuery();
|
| -}
|
| -
|
| -base::TimeDelta DhcpProxyScriptFetcherWin::ImplGetMaxWait() {
|
| - return base::TimeDelta::FromMilliseconds(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<IP_ADAPTER_ADDRESSES, base::FreeDeleter> adapters;
|
| - ULONG error = ERROR_SUCCESS;
|
| - int num_tries = 0;
|
| -
|
| - do {
|
| - adapters.reset(static_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;
|
| -}
|
| -
|
| -DhcpProxyScriptFetcherWin::AdapterQuery::AdapterQuery() {
|
| -}
|
| -
|
| -DhcpProxyScriptFetcherWin::AdapterQuery::~AdapterQuery() {
|
| -}
|
| -
|
| -void DhcpProxyScriptFetcherWin::AdapterQuery::GetCandidateAdapterNames() {
|
| - ImplGetCandidateAdapterNames(&adapter_names_);
|
| -}
|
| -
|
| -const std::set<std::string>&
|
| - DhcpProxyScriptFetcherWin::AdapterQuery::adapter_names() const {
|
| - return adapter_names_;
|
| -}
|
| -
|
| -bool DhcpProxyScriptFetcherWin::AdapterQuery::ImplGetCandidateAdapterNames(
|
| - std::set<std::string>* adapter_names) {
|
| - return DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(adapter_names);
|
| -}
|
| -
|
| -} // namespace net
|
|
|