Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: net/proxy/dhcp_proxy_script_fetcher_win.cc

Issue 7189016: Do GetAdaptersAddresses on a worker thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/dhcp_proxy_script_fetcher_win.h" 5 #include "net/proxy/dhcp_proxy_script_fetcher_win.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "base/perftimer.h" 8 #include "base/perftimer.h"
9 #include "base/threading/worker_pool.h"
9 #include "net/base/net_errors.h" 10 #include "net/base/net_errors.h"
10 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h" 11 #include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
11 12
12 #include <winsock2.h> 13 #include <winsock2.h>
13 #include <iphlpapi.h> 14 #include <iphlpapi.h>
14 #pragma comment(lib, "iphlpapi.lib") 15 #pragma comment(lib, "iphlpapi.lib")
15 16
16 namespace { 17 namespace {
17 18
18 // How long to wait at maximum after we get results (a PAC file or 19 // How long to wait at maximum after we get results (a PAC file or
(...skipping 19 matching lines...) Expand all
38 ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_callback_( 39 ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_callback_(
39 this, &DhcpProxyScriptFetcherWin::OnFetcherDone)), 40 this, &DhcpProxyScriptFetcherWin::OnFetcherDone)),
40 num_pending_fetchers_(0), 41 num_pending_fetchers_(0),
41 url_request_context_(url_request_context) { 42 url_request_context_(url_request_context) {
42 DCHECK(url_request_context_); 43 DCHECK(url_request_context_);
43 } 44 }
44 45
45 DhcpProxyScriptFetcherWin::~DhcpProxyScriptFetcherWin() { 46 DhcpProxyScriptFetcherWin::~DhcpProxyScriptFetcherWin() {
46 // Count as user-initiated if we are not yet in STATE_DONE. 47 // Count as user-initiated if we are not yet in STATE_DONE.
47 Cancel(); 48 Cancel();
49
50 // The WeakPtr we passed to the worker thread may be destroyed on the
51 // worker thread. This detaches any outstanding WeakPtr state from
52 // the current thread.
53 base::SupportsWeakPtr<DhcpProxyScriptFetcherWin>::DetachFromThread();
48 } 54 }
49 55
50 int DhcpProxyScriptFetcherWin::Fetch(string16* utf16_text, 56 int DhcpProxyScriptFetcherWin::Fetch(string16* utf16_text,
51 CompletionCallback* callback) { 57 CompletionCallback* callback) {
52 DCHECK(CalledOnValidThread()); 58 DCHECK(CalledOnValidThread());
53 if (state_ != STATE_START && state_ != STATE_DONE) { 59 if (state_ != STATE_START && state_ != STATE_DONE) {
54 NOTREACHED(); 60 NOTREACHED();
55 return ERR_UNEXPECTED; 61 return ERR_UNEXPECTED;
56 } 62 }
57 63
58 fetch_start_time_ = base::TimeTicks::Now(); 64 fetch_start_time_ = base::TimeTicks::Now();
59 65
60 std::set<std::string> adapter_names;
61 if (!ImplGetCandidateAdapterNames(&adapter_names)) {
62 return ERR_UNEXPECTED;
63 }
64 if (adapter_names.empty()) {
65 return ERR_PAC_NOT_IN_DHCP;
66 }
67
68 state_ = STATE_NO_RESULTS; 66 state_ = STATE_NO_RESULTS;
69
70 client_callback_ = callback; 67 client_callback_ = callback;
71 destination_string_ = utf16_text; 68 destination_string_ = utf16_text;
72 69
73 for (std::set<std::string>::iterator it = adapter_names.begin(); 70 worker_thread_ = ImplCreateWorkerThread(AsWeakPtr());
74 it != adapter_names.end(); 71 worker_thread_->Start();
75 ++it) {
76 DhcpProxyScriptAdapterFetcher* fetcher(ImplCreateAdapterFetcher());
77 fetcher->Fetch(*it, &fetcher_callback_);
78 fetchers_.push_back(fetcher);
79 }
80 num_pending_fetchers_ = fetchers_.size();
81 72
82 return ERR_IO_PENDING; 73 return ERR_IO_PENDING;
83 } 74 }
84 75
85 void DhcpProxyScriptFetcherWin::Cancel() { 76 void DhcpProxyScriptFetcherWin::Cancel() {
86 DCHECK(CalledOnValidThread()); 77 DCHECK(CalledOnValidThread());
87 78
88 if (state_ != STATE_DONE) { 79 if (state_ != STATE_DONE) {
89 // We only count this stat if the cancel was explicitly initiated by 80 // We only count this stat if the cancel was explicitly initiated by
90 // our client, and if we weren't already in STATE_DONE. 81 // our client, and if we weren't already in STATE_DONE.
(...skipping 14 matching lines...) Expand all
105 for (FetcherVector::iterator it = fetchers_.begin(); 96 for (FetcherVector::iterator it = fetchers_.begin();
106 it != fetchers_.end(); 97 it != fetchers_.end();
107 ++it) { 98 ++it) {
108 (*it)->Cancel(); 99 (*it)->Cancel();
109 } 100 }
110 101
111 fetchers_.reset(); 102 fetchers_.reset();
112 } 103 }
113 } 104 }
114 105
106 void DhcpProxyScriptFetcherWin::OnGetCandidateAdapterNamesDone(
107 const std::set<std::string>& adapter_names) {
108 if (adapter_names.empty()) {
109 TransitionToDone();
110 return;
111 }
112
113 for (std::set<std::string>::const_iterator it = adapter_names.begin();
114 it != adapter_names.end();
115 ++it) {
116 DhcpProxyScriptAdapterFetcher* fetcher(ImplCreateAdapterFetcher());
117 fetcher->Fetch(*it, &fetcher_callback_);
118 fetchers_.push_back(fetcher);
119 }
120 num_pending_fetchers_ = fetchers_.size();
121 }
122
115 std::string DhcpProxyScriptFetcherWin::GetFetcherName() const { 123 std::string DhcpProxyScriptFetcherWin::GetFetcherName() const {
116 DCHECK(CalledOnValidThread()); 124 DCHECK(CalledOnValidThread());
117 return "win"; 125 return "win";
118 } 126 }
119 127
120 const GURL& DhcpProxyScriptFetcherWin::GetPacURL() const { 128 const GURL& DhcpProxyScriptFetcherWin::GetPacURL() const {
121 DCHECK(CalledOnValidThread()); 129 DCHECK(CalledOnValidThread());
122 DCHECK_EQ(state_, STATE_DONE); 130 DCHECK_EQ(state_, STATE_DONE);
123 131
124 return pac_url_; 132 return pac_url_;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 fetchers_.size()); 175 fetchers_.size());
168 UMA_HISTOGRAM_COUNTS_100("Net.DhcpWpadNumPendingAdaptersAtWaitTimer", 176 UMA_HISTOGRAM_COUNTS_100("Net.DhcpWpadNumPendingAdaptersAtWaitTimer",
169 num_pending_fetchers_); 177 num_pending_fetchers_);
170 178
171 TransitionToDone(); 179 TransitionToDone();
172 } 180 }
173 181
174 void DhcpProxyScriptFetcherWin::TransitionToDone() { 182 void DhcpProxyScriptFetcherWin::TransitionToDone() {
175 DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS); 183 DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS);
176 184
177 // Should have returned immediately at Fetch() if no adapters to check. 185 int result = ERR_PAC_NOT_IN_DHCP; // Default if no fetchers.
178 DCHECK(!fetchers_.empty()); 186 if (!fetchers_.empty()) {
179 187 // Scan twice for the result; once through the whole list for success,
180 // Scan twice for the result; once through the whole list for success, 188 // then if no success, return result for most preferred network adapter,
181 // then if no success, return result for most preferred network adapter, 189 // preferring "real" network errors to the ERR_PAC_NOT_IN_DHCP error.
182 // preferring "real" network errors to the ERR_PAC_NOT_IN_DHCP error. 190 // Default to ERR_ABORTED if no fetcher completed.
183 // Default to ERR_ABORTED if no fetcher completed. 191 result = ERR_ABORTED;
184 int result = ERR_ABORTED;
185 for (FetcherVector::iterator it = fetchers_.begin();
186 it != fetchers_.end();
187 ++it) {
188 if ((*it)->DidFinish() && (*it)->GetResult() == OK) {
189 result = OK;
190 *destination_string_ = (*it)->GetPacScript();
191 pac_url_ = (*it)->GetPacURL();
192 break;
193 }
194 }
195 if (result != OK) {
196 destination_string_->clear();
197 for (FetcherVector::iterator it = fetchers_.begin(); 192 for (FetcherVector::iterator it = fetchers_.begin();
198 it != fetchers_.end(); 193 it != fetchers_.end();
199 ++it) { 194 ++it) {
200 if ((*it)->DidFinish()) { 195 if ((*it)->DidFinish() && (*it)->GetResult() == OK) {
201 result = (*it)->GetResult(); 196 result = OK;
202 if (result != ERR_PAC_NOT_IN_DHCP) { 197 *destination_string_ = (*it)->GetPacScript();
203 break; 198 pac_url_ = (*it)->GetPacURL();
199 break;
200 }
201 }
202 if (result != OK) {
203 destination_string_->clear();
204 for (FetcherVector::iterator it = fetchers_.begin();
205 it != fetchers_.end();
206 ++it) {
207 if ((*it)->DidFinish()) {
208 result = (*it)->GetResult();
209 if (result != ERR_PAC_NOT_IN_DHCP) {
210 break;
211 }
204 } 212 }
205 } 213 }
206 } 214 }
207 } 215 }
208 216
209 CancelImpl(); 217 CancelImpl();
210 DCHECK_EQ(state_, STATE_DONE); 218 DCHECK_EQ(state_, STATE_DONE);
211 DCHECK(fetchers_.empty()); 219 DCHECK(fetchers_.empty());
212 220
213 UMA_HISTOGRAM_TIMES("Net.DhcpWpadCompletionTime", 221 UMA_HISTOGRAM_TIMES("Net.DhcpWpadCompletionTime",
(...skipping 13 matching lines...) Expand all
227 235
228 URLRequestContext* DhcpProxyScriptFetcherWin::url_request_context() const { 236 URLRequestContext* DhcpProxyScriptFetcherWin::url_request_context() const {
229 return url_request_context_; 237 return url_request_context_;
230 } 238 }
231 239
232 DhcpProxyScriptAdapterFetcher* 240 DhcpProxyScriptAdapterFetcher*
233 DhcpProxyScriptFetcherWin::ImplCreateAdapterFetcher() { 241 DhcpProxyScriptFetcherWin::ImplCreateAdapterFetcher() {
234 return new DhcpProxyScriptAdapterFetcher(url_request_context_); 242 return new DhcpProxyScriptAdapterFetcher(url_request_context_);
235 } 243 }
236 244
237 bool DhcpProxyScriptFetcherWin::ImplGetCandidateAdapterNames( 245 DhcpProxyScriptFetcherWin::WorkerThread*
238 std::set<std::string>* adapter_names) { 246 DhcpProxyScriptFetcherWin::ImplCreateWorkerThread(
239 return GetCandidateAdapterNames(adapter_names); 247 const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
248 return new WorkerThread(owner);
240 } 249 }
241 250
242 int DhcpProxyScriptFetcherWin::ImplGetMaxWaitMs() { 251 int DhcpProxyScriptFetcherWin::ImplGetMaxWaitMs() {
243 return kMaxWaitAfterFirstResultMs; 252 return kMaxWaitAfterFirstResultMs;
244 } 253 }
245 254
246 bool DhcpProxyScriptFetcherWin::GetCandidateAdapterNames( 255 bool DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(
247 std::set<std::string>* adapter_names) { 256 std::set<std::string>* adapter_names) {
248 DCHECK(adapter_names); 257 DCHECK(adapter_names);
249 adapter_names->clear(); 258 adapter_names->clear();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 if ((adapter->Flags & IP_ADAPTER_DHCP_ENABLED) == 0) 311 if ((adapter->Flags & IP_ADAPTER_DHCP_ENABLED) == 0)
303 continue; 312 continue;
304 313
305 DCHECK(adapter->AdapterName); 314 DCHECK(adapter->AdapterName);
306 adapter_names->insert(adapter->AdapterName); 315 adapter_names->insert(adapter->AdapterName);
307 } 316 }
308 317
309 return true; 318 return true;
310 } 319 }
311 320
321 DhcpProxyScriptFetcherWin::WorkerThread::WorkerThread(
322 const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
323 Init(owner);
324 }
325
326 DhcpProxyScriptFetcherWin::WorkerThread::~WorkerThread() {
327 }
328
329 void DhcpProxyScriptFetcherWin::WorkerThread::Start() {
330 bool succeeded = base::WorkerPool::PostTask(
331 FROM_HERE,
332 NewRunnableMethod(
333 this,
334 &DhcpProxyScriptFetcherWin::WorkerThread::ThreadFunc),
335 true);
336 DCHECK(succeeded);
337 }
338
339 void DhcpProxyScriptFetcherWin::WorkerThread::ThreadFunc() {
340 ImplGetCandidateAdapterNames(&adapter_names_);
341
342 bool succeeded = origin_loop_->PostTask(
343 FROM_HERE,
344 NewRunnableMethod(
345 this,
346 &DhcpProxyScriptFetcherWin::WorkerThread::OnThreadDone));
347 DCHECK(succeeded);
348 }
349
350 void DhcpProxyScriptFetcherWin::WorkerThread::OnThreadDone() {
351 DCHECK(thread_checker_.CalledOnValidThread());
352 if (owner_)
353 owner_->OnGetCandidateAdapterNamesDone(adapter_names_);
eroman 2011/06/21 03:02:54 How is cancellation handled? I understand that if
354 }
355
356 DhcpProxyScriptFetcherWin::WorkerThread::WorkerThread() {
357 }
358
359 void DhcpProxyScriptFetcherWin::WorkerThread::Init(
360 const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) {
361 owner_ = owner;
362 origin_loop_ = base::MessageLoopProxy::CreateForCurrentThread();
363 }
364
365 bool DhcpProxyScriptFetcherWin::WorkerThread::ImplGetCandidateAdapterNames(
366 std::set<std::string>* adapter_names) {
367 return DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(adapter_names);
368 }
369
312 } // namespace net 370 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/dhcp_proxy_script_fetcher_win.h ('k') | net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698