| 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
|
| index dbe4df2b300f3e1a4a77500e7e0f0043e3d0877f..2c7fd23b920b5ec04bf8926d9c831aaa723859a4 100644
|
| --- a/net/proxy/dhcp_proxy_script_fetcher_win.cc
|
| +++ b/net/proxy/dhcp_proxy_script_fetcher_win.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "base/metrics/histogram.h"
|
| #include "base/perftimer.h"
|
| +#include "base/threading/worker_pool.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
|
|
|
| @@ -45,6 +46,11 @@ DhcpProxyScriptFetcherWin::DhcpProxyScriptFetcherWin(
|
| DhcpProxyScriptFetcherWin::~DhcpProxyScriptFetcherWin() {
|
| // Count as user-initiated if we are not yet in STATE_DONE.
|
| Cancel();
|
| +
|
| + // The WeakPtr we passed to the worker thread may be destroyed on the
|
| + // worker thread. This detaches any outstanding WeakPtr state from
|
| + // the current thread.
|
| + base::SupportsWeakPtr<DhcpProxyScriptFetcherWin>::DetachFromThread();
|
| }
|
|
|
| int DhcpProxyScriptFetcherWin::Fetch(string16* utf16_text,
|
| @@ -57,27 +63,12 @@ int DhcpProxyScriptFetcherWin::Fetch(string16* utf16_text,
|
|
|
| fetch_start_time_ = base::TimeTicks::Now();
|
|
|
| - 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;
|
| -
|
| + state_ = STATE_WAIT_ADAPTERS;
|
| 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();
|
| + worker_thread_ = ImplCreateWorkerThread(AsWeakPtr());
|
| + worker_thread_->Start();
|
|
|
| return ERR_IO_PENDING;
|
| }
|
| @@ -113,6 +104,31 @@ void DhcpProxyScriptFetcherWin::CancelImpl() {
|
| }
|
| }
|
|
|
| +void DhcpProxyScriptFetcherWin::OnGetCandidateAdapterNamesDone(
|
| + const std::set<std::string>& adapter_names) {
|
| + DCHECK(CalledOnValidThread());
|
| +
|
| + // We may have been cancelled.
|
| + if (state_ != STATE_WAIT_ADAPTERS)
|
| + return;
|
| +
|
| + state_ = STATE_NO_RESULTS;
|
| +
|
| + 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, &fetcher_callback_);
|
| + fetchers_.push_back(fetcher);
|
| + }
|
| + num_pending_fetchers_ = fetchers_.size();
|
| +}
|
| +
|
| std::string DhcpProxyScriptFetcherWin::GetFetcherName() const {
|
| DCHECK(CalledOnValidThread());
|
| return "win";
|
| @@ -175,33 +191,33 @@ void DhcpProxyScriptFetcherWin::OnWaitTimer() {
|
| 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();
|
| + 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()) {
|
| - result = (*it)->GetResult();
|
| - if (result != ERR_PAC_NOT_IN_DHCP) {
|
| - break;
|
| + 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;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -238,9 +254,10 @@ DhcpProxyScriptAdapterFetcher*
|
| return new DhcpProxyScriptAdapterFetcher(url_request_context_);
|
| }
|
|
|
| -bool DhcpProxyScriptFetcherWin::ImplGetCandidateAdapterNames(
|
| - std::set<std::string>* adapter_names) {
|
| - return GetCandidateAdapterNames(adapter_names);
|
| +DhcpProxyScriptFetcherWin::WorkerThread*
|
| + DhcpProxyScriptFetcherWin::ImplCreateWorkerThread(
|
| + const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
|
| + return new WorkerThread(owner);
|
| }
|
|
|
| int DhcpProxyScriptFetcherWin::ImplGetMaxWaitMs() {
|
| @@ -313,4 +330,53 @@ bool DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(
|
| return true;
|
| }
|
|
|
| +DhcpProxyScriptFetcherWin::WorkerThread::WorkerThread(
|
| + const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
|
| + Init(owner);
|
| +}
|
| +
|
| +DhcpProxyScriptFetcherWin::WorkerThread::~WorkerThread() {
|
| +}
|
| +
|
| +void DhcpProxyScriptFetcherWin::WorkerThread::Start() {
|
| + bool succeeded = base::WorkerPool::PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &DhcpProxyScriptFetcherWin::WorkerThread::ThreadFunc),
|
| + true);
|
| + DCHECK(succeeded);
|
| +}
|
| +
|
| +void DhcpProxyScriptFetcherWin::WorkerThread::ThreadFunc() {
|
| + ImplGetCandidateAdapterNames(&adapter_names_);
|
| +
|
| + bool succeeded = origin_loop_->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &DhcpProxyScriptFetcherWin::WorkerThread::OnThreadDone));
|
| + DCHECK(succeeded);
|
| +}
|
| +
|
| +void DhcpProxyScriptFetcherWin::WorkerThread::OnThreadDone() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (owner_)
|
| + owner_->OnGetCandidateAdapterNamesDone(adapter_names_);
|
| +}
|
| +
|
| +DhcpProxyScriptFetcherWin::WorkerThread::WorkerThread() {
|
| +}
|
| +
|
| +void DhcpProxyScriptFetcherWin::WorkerThread::Init(
|
| + const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
|
| + owner_ = owner;
|
| + origin_loop_ = base::MessageLoopProxy::CreateForCurrentThread();
|
| +}
|
| +
|
| +bool DhcpProxyScriptFetcherWin::WorkerThread::ImplGetCandidateAdapterNames(
|
| + std::set<std::string>* adapter_names) {
|
| + return DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(adapter_names);
|
| +}
|
| +
|
| } // namespace net
|
|
|