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

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

Issue 149525: Remove the concept of threading from ProxyService, and move it into the Proxy... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Add missing header for mac Created 11 years, 5 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
« no previous file with comments | « net/proxy/proxy_service.h ('k') | net/proxy/proxy_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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/proxy_service.h" 5 #include "net/proxy/proxy_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "googleurl/src/gurl.h" 13 #include "googleurl/src/gurl.h"
13 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
14 #include "net/proxy/proxy_config_service_fixed.h" 15 #include "net/proxy/proxy_config_service_fixed.h"
15 #include "net/proxy/proxy_script_fetcher.h" 16 #include "net/proxy/proxy_script_fetcher.h"
16 #if defined(OS_WIN) 17 #if defined(OS_WIN)
17 #include "net/proxy/proxy_config_service_win.h" 18 #include "net/proxy/proxy_config_service_win.h"
18 #include "net/proxy/proxy_resolver_winhttp.h" 19 #include "net/proxy/proxy_resolver_winhttp.h"
19 #elif defined(OS_MACOSX) 20 #elif defined(OS_MACOSX)
20 #include "net/proxy/proxy_resolver_mac.h" 21 #include "net/proxy/proxy_resolver_mac.h"
21 #elif defined(OS_LINUX) 22 #elif defined(OS_LINUX)
22 #include "net/proxy/proxy_config_service_linux.h" 23 #include "net/proxy/proxy_config_service_linux.h"
23 #endif 24 #endif
24 #include "net/proxy/proxy_resolver.h" 25 #include "net/proxy/proxy_resolver.h"
25 #include "net/proxy/proxy_resolver_v8.h" 26 #include "net/proxy/proxy_resolver_v8.h"
27 #include "net/proxy/single_threaded_proxy_resolver.h"
26 #include "net/url_request/url_request_context.h" 28 #include "net/url_request/url_request_context.h"
27 29
28 using base::TimeDelta; 30 using base::TimeDelta;
29 using base::TimeTicks; 31 using base::TimeTicks;
30 32
31 namespace net { 33 namespace net {
32 34
33 // Config getter that fails every time. 35 // Config getter that fails every time.
34 class ProxyConfigServiceNull : public ProxyConfigService { 36 class ProxyConfigServiceNull : public ProxyConfigService {
35 public: 37 public:
36 // ProxyConfigService implementation: 38 // ProxyConfigService implementation:
37 virtual int GetProxyConfig(ProxyConfig* config) { 39 virtual int GetProxyConfig(ProxyConfig* config) {
38 return ERR_NOT_IMPLEMENTED; 40 return ERR_NOT_IMPLEMENTED;
39 } 41 }
40 }; 42 };
41 43
42 // Proxy resolver that fails every time. 44 // Proxy resolver that fails every time.
43 class ProxyResolverNull : public ProxyResolver { 45 class ProxyResolverNull : public ProxyResolver {
44 public: 46 public:
45 ProxyResolverNull() : ProxyResolver(true /*does_fetch*/) {} 47 ProxyResolverNull() : ProxyResolver(false /*expects_pac_bytes*/) {}
46 48
47 // ProxyResolver implementation: 49 // ProxyResolver implementation:
48 virtual int GetProxyForURL(const GURL& /*query_url*/, 50 virtual int GetProxyForURL(const GURL& url,
49 const GURL& /*pac_url*/, 51 ProxyInfo* results,
50 ProxyInfo* /*results*/) { 52 CompletionCallback* callback,
53 RequestHandle* request) {
51 return ERR_NOT_IMPLEMENTED; 54 return ERR_NOT_IMPLEMENTED;
52 } 55 }
56
57 virtual void CancelRequest(RequestHandle request) {
58 NOTREACHED();
59 }
60
61 private:
62 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {}
53 }; 63 };
54 64
55 // Strip away any reference fragments and the username/password, as they 65 // Strip away any reference fragments and the username/password, as they
56 // are not relevant to proxy resolution. 66 // are not relevant to proxy resolution.
57 static GURL SanitizeURLForProxyResolver(const GURL& url) { 67 static GURL SanitizeURLForProxyResolver(const GURL& url) {
58 // TODO(eroman): The following duplicates logic from 68 // TODO(eroman): The following duplicates logic from
59 // HttpUtil::SpecForRequest. Should probably live in net_util.h 69 // HttpUtil::SpecForRequest. Should probably live in net_util.h
60 GURL::Replacements replacements; 70 GURL::Replacements replacements;
61 replacements.ClearUsername(); 71 replacements.ClearUsername();
62 replacements.ClearPassword(); 72 replacements.ClearPassword();
63 replacements.ClearRef(); 73 replacements.ClearRef();
64 return url.ReplaceComponents(replacements); 74 return url.ReplaceComponents(replacements);
65 } 75 }
66 76
67 // Runs on the PAC thread to notify the proxy resolver of the fetched PAC
68 // script contents. This task shouldn't outlive ProxyService, since
69 // |resolver| is owned by ProxyService.
70 class NotifyFetchCompletionTask : public Task {
71 public:
72 NotifyFetchCompletionTask(ProxyResolver* resolver, const std::string& bytes)
73 : resolver_(resolver), bytes_(bytes) {}
74
75 virtual void Run() {
76 resolver_->SetPacScript(bytes_);
77 }
78
79 private:
80 ProxyResolver* resolver_;
81 std::string bytes_;
82 };
83
84 // ProxyService::PacRequest --------------------------------------------------- 77 // ProxyService::PacRequest ---------------------------------------------------
85 78
86 // We rely on the fact that the origin thread (and its message loop) will not
87 // be destroyed until after the PAC thread is destroyed.
88
89 class ProxyService::PacRequest 79 class ProxyService::PacRequest
90 : public base::RefCountedThreadSafe<ProxyService::PacRequest> { 80 : public base::RefCounted<ProxyService::PacRequest> {
91 public: 81 public:
92 // |service| -- the ProxyService that owns this request.
93 // |url| -- the url of the query.
94 // |results| -- the structure to fill with proxy resolve results.
95 PacRequest(ProxyService* service, 82 PacRequest(ProxyService* service,
96 const GURL& url, 83 const GURL& url,
97 ProxyInfo* results, 84 ProxyInfo* results,
98 CompletionCallback* callback) 85 CompletionCallback* user_callback)
99 : service_(service), 86 : service_(service),
100 callback_(callback), 87 user_callback_(user_callback),
88 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
89 this, &PacRequest::QueryComplete)),
101 results_(results), 90 results_(results),
102 url_(url), 91 url_(url),
103 is_started_(false), 92 resolve_job_(NULL),
104 origin_loop_(MessageLoop::current()) { 93 config_id_(ProxyConfig::INVALID_ID) {
105 DCHECK(callback); 94 DCHECK(user_callback);
106 } 95 }
107 96
108 // Start the resolve proxy request on the PAC thread. 97 // Starts the resolve proxy request.
109 void Query() { 98 int Start() {
110 is_started_ = true; 99 DCHECK(!was_cancelled());
111 AddRef(); // balanced in QueryComplete 100 DCHECK(!is_started());
112 101
113 GURL query_url = SanitizeURLForProxyResolver(url_); 102 config_id_ = service_->config_.id();
114 const GURL& pac_url = service_->config_.pac_url;
115 results_->config_id_ = service_->config_.id();
116 103
117 service_->pac_thread()->message_loop()->PostTask(FROM_HERE, 104 return resolver()->GetProxyForURL(
118 NewRunnableMethod(this, &ProxyService::PacRequest::DoQuery, 105 url_, results_, &io_callback_, &resolve_job_);
119 service_->resolver(), query_url, pac_url));
120 } 106 }
121 107
122 // Run the request's callback on the current message loop. 108 bool is_started() const {
123 void PostCallback(int result_code) { 109 // Note that !! casts to bool. (VS gives a warning otherwise).
124 AddRef(); // balanced in DoCallback 110 return !!resolve_job_;
125 MessageLoop::current()->PostTask(FROM_HERE, 111 }
126 NewRunnableMethod(this, &ProxyService::PacRequest::DoCallback, 112
127 result_code)); 113 void StartAndComplete() {
114 int rv = Start();
115 if (rv != ERR_IO_PENDING)
116 QueryComplete(rv);
128 } 117 }
129 118
130 void Cancel() { 119 void Cancel() {
131 // Clear these to inform QueryComplete that it should not try to 120 // The request may already be running in the resolver.
132 // access them. 121 if (is_started()) {
122 resolver()->CancelRequest(resolve_job_);
123 resolve_job_ = NULL;
124 }
125
126 // Mark as cancelled, to prevent accessing this again later.
133 service_ = NULL; 127 service_ = NULL;
134 callback_ = NULL; 128 user_callback_ = NULL;
135 results_ = NULL; 129 results_ = NULL;
136 } 130 }
137 131
138 // Returns true if Cancel() has been called. 132 // Returns true if Cancel() has been called.
139 bool was_cancelled() const { return callback_ == NULL; } 133 bool was_cancelled() const { return user_callback_ == NULL; }
134
135 // Helper to call after ProxyResolver completion (both synchronous and
136 // asynchronous). Fixes up the result that is to be returned to user.
137 int QueryDidComplete(int result_code) {
138 DCHECK(!was_cancelled());
139
140 // Make a note in the results which configuration was in use at the
141 // time of the resolve.
142 results_->config_id_ = config_id_;
143
144 // Reset the state associated with in-progress-resolve.
145 resolve_job_ = NULL;
146 config_id_ = ProxyConfig::INVALID_ID;
147
148 // Notify the service of the completion.
149 service_->DidCompletePacRequest(results_->config_id_, result_code);
150
151 // Clean up the results list.
152 if (result_code == OK)
153 results_->RemoveBadProxies(service_->proxy_retry_info_);
154
155 return result_code;
156 }
140 157
141 private: 158 private:
142 friend class ProxyService; 159 // Callback for when the ProxyResolver request has completed.
160 void QueryComplete(int result_code) {
161 result_code = QueryDidComplete(result_code);
143 162
144 // Runs on the PAC thread. 163 // Remove this completed PacRequest from the service's pending list.
145 void DoQuery(ProxyResolver* resolver, 164 /// (which will probably cause deletion of |this|).
146 const GURL& query_url, 165 CompletionCallback* callback = user_callback_;
147 const GURL& pac_url) { 166 service_->RemovePendingRequest(this);
148 int rv = resolver->GetProxyForURL(query_url, pac_url, &results_buf_); 167
149 origin_loop_->PostTask(FROM_HERE, 168 callback->Run(result_code);
150 NewRunnableMethod(this, &PacRequest::QueryComplete, rv));
151 } 169 }
152 170
153 // Runs the completion callback on the origin thread. 171 ProxyResolver* resolver() const { return service_->resolver_.get(); }
154 void QueryComplete(int result_code) {
155 // The PacRequest may have been cancelled after it was started.
156 if (!was_cancelled()) {
157 service_->DidCompletePacRequest(results_->config_id_, result_code);
158 172
159 if (result_code == OK) {
160 results_->Use(results_buf_);
161 results_->RemoveBadProxies(service_->proxy_retry_info_);
162 }
163 callback_->Run(result_code);
164
165 // We check for cancellation once again, in case the callback deleted
166 // the owning ProxyService (whose destructor will in turn cancel us).
167 if (!was_cancelled())
168 service_->RemoveFrontOfRequestQueue(this);
169 }
170
171 Release(); // balances the AddRef in Query. we may get deleted after
172 // we return.
173 }
174
175 // Runs the completion callback on the origin thread.
176 void DoCallback(int result_code) {
177 if (!was_cancelled()) {
178 callback_->Run(result_code);
179 }
180 Release(); // balances the AddRef in PostCallback.
181 }
182
183 // Must only be used on the "origin" thread.
184 ProxyService* service_; 173 ProxyService* service_;
185 CompletionCallback* callback_; 174 CompletionCallback* user_callback_;
175 CompletionCallbackImpl<PacRequest> io_callback_;
186 ProxyInfo* results_; 176 ProxyInfo* results_;
187 GURL url_; 177 GURL url_;
188 bool is_started_; 178 ProxyResolver::RequestHandle resolve_job_;
189 179 ProxyConfig::ID config_id_; // The config id when the resolve was started.
190 // Usable from within DoQuery on the PAC thread.
191 ProxyInfo results_buf_;
192 MessageLoop* origin_loop_;
193 }; 180 };
194 181
195 // ProxyService --------------------------------------------------------------- 182 // ProxyService ---------------------------------------------------------------
196 183
197 ProxyService::ProxyService(ProxyConfigService* config_service, 184 ProxyService::ProxyService(ProxyConfigService* config_service,
198 ProxyResolver* resolver) 185 ProxyResolver* resolver)
199 : config_service_(config_service), 186 : config_service_(config_service),
200 resolver_(resolver), 187 resolver_(resolver),
201 next_config_id_(1), 188 next_config_id_(1),
202 config_is_bad_(false), 189 config_is_bad_(false),
(...skipping 21 matching lines...) Expand all
224 // Send javascript errors and alerts to LOG(INFO). 211 // Send javascript errors and alerts to LOG(INFO).
225 HostResolver* host_resolver = url_request_context->host_resolver(); 212 HostResolver* host_resolver = url_request_context->host_resolver();
226 ProxyResolverV8::JSBindings* js_bindings = 213 ProxyResolverV8::JSBindings* js_bindings =
227 ProxyResolverV8::CreateDefaultBindings(host_resolver, io_loop); 214 ProxyResolverV8::CreateDefaultBindings(host_resolver, io_loop);
228 215
229 proxy_resolver = new ProxyResolverV8(js_bindings); 216 proxy_resolver = new ProxyResolverV8(js_bindings);
230 } else { 217 } else {
231 proxy_resolver = CreateNonV8ProxyResolver(); 218 proxy_resolver = CreateNonV8ProxyResolver();
232 } 219 }
233 220
221 // Wrap the (synchronous) ProxyResolver implementation in a single-threaded
222 // runner. This will dispatch requests to a threadpool of size 1.
223 proxy_resolver = new SingleThreadedProxyResolver(proxy_resolver);
224
234 ProxyService* proxy_service = new ProxyService( 225 ProxyService* proxy_service = new ProxyService(
235 proxy_config_service, proxy_resolver); 226 proxy_config_service, proxy_resolver);
236 227
237 if (!proxy_resolver->does_fetch()) { 228 if (proxy_resolver->expects_pac_bytes()) {
238 // Configure PAC script downloads to be issued using |url_request_context|. 229 // Configure PAC script downloads to be issued using |url_request_context|.
239 DCHECK(url_request_context); 230 DCHECK(url_request_context);
240 proxy_service->SetProxyScriptFetcher( 231 proxy_service->SetProxyScriptFetcher(
241 ProxyScriptFetcher::Create(url_request_context)); 232 ProxyScriptFetcher::Create(url_request_context));
242 } 233 }
243 234
244 return proxy_service; 235 return proxy_service;
245 } 236 }
246 237
247 // static 238 // static
248 ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) { 239 ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
249 return Create(&pc, false, NULL, NULL); 240 return Create(&pc, false, NULL, NULL);
250 } 241 }
251 242
252 // static 243 // static
253 ProxyService* ProxyService::CreateNull() { 244 ProxyService* ProxyService::CreateNull() {
254 // Use a configuration fetcher and proxy resolver which always fail. 245 // Use a configuration fetcher and proxy resolver which always fail.
255 return new ProxyService(new ProxyConfigServiceNull, new ProxyResolverNull); 246 return new ProxyService(new ProxyConfigServiceNull, new ProxyResolverNull);
256 } 247 }
257 248
258 int ProxyService::ResolveProxy(const GURL& url, ProxyInfo* result, 249 int ProxyService::ResolveProxy(const GURL& raw_url, ProxyInfo* result,
259 CompletionCallback* callback, 250 CompletionCallback* callback,
260 PacRequest** pac_request) { 251 PacRequest** pac_request) {
261 DCHECK(callback); 252 DCHECK(callback);
262 253
254 GURL url = SanitizeURLForProxyResolver(raw_url);
255
263 // Check if the request can be completed right away. This is the case when 256 // Check if the request can be completed right away. This is the case when
264 // using a direct connection, or when the config is bad. 257 // using a direct connection, or when the config is bad.
265 UpdateConfigIfOld(); 258 UpdateConfigIfOld();
266 int rv = TryToCompleteSynchronously(url, result); 259 int rv = TryToCompleteSynchronously(url, result);
267 if (rv != ERR_IO_PENDING) 260 if (rv != ERR_IO_PENDING)
268 return rv; 261 return rv;
269 262
270 // Otherwise, push the request into the work queue.
271 scoped_refptr<PacRequest> req = new PacRequest(this, url, result, callback); 263 scoped_refptr<PacRequest> req = new PacRequest(this, url, result, callback);
264
265 bool resolver_is_ready = PrepareResolverForRequests();
266
267 if (resolver_is_ready) {
268 // Start the resolve request.
269 rv = req->Start();
270 if (rv != ERR_IO_PENDING)
271 return req->QueryDidComplete(rv);
272 }
273
274 DCHECK_EQ(ERR_IO_PENDING, rv);
275 DCHECK(!ContainsPendingRequest(req));
272 pending_requests_.push_back(req); 276 pending_requests_.push_back(req);
273 ProcessPendingRequests(req.get());
274 277
275 // Completion will be notifed through |callback|, unless the caller cancels 278 // Completion will be notifed through |callback|, unless the caller cancels
276 // the request using |pac_request|. 279 // the request using |pac_request|.
277 if (pac_request) 280 if (pac_request)
278 *pac_request = req.get(); 281 *pac_request = req.get();
279 return rv; // ERR_IO_PENDING 282 return rv; // ERR_IO_PENDING
280 } 283 }
281 284
282 int ProxyService::TryToCompleteSynchronously(const GURL& url, 285 int ProxyService::TryToCompleteSynchronously(const GURL& url,
283 ProxyInfo* result) { 286 ProxyInfo* result) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 } 346 }
344 break; 347 break;
345 } 348 }
346 default: 349 default:
347 result->UseDirect(); 350 result->UseDirect();
348 NOTREACHED(); 351 NOTREACHED();
349 break; 352 break;
350 } 353 }
351 } 354 }
352 355
353 void ProxyService::InitPacThread() {
354 if (!pac_thread_.get()) {
355 pac_thread_.reset(new base::Thread("pac-thread"));
356 pac_thread_->Start();
357 }
358 }
359
360 ProxyService::~ProxyService() { 356 ProxyService::~ProxyService() {
361 // Cancel the inprogress request (if any), and free the rest. 357 // Cancel any inprogress requests.
362 for (PendingRequestsQueue::iterator it = pending_requests_.begin(); 358 for (PendingRequests::iterator it = pending_requests_.begin();
363 it != pending_requests_.end(); 359 it != pending_requests_.end();
364 ++it) { 360 ++it) {
365 (*it)->Cancel(); 361 (*it)->Cancel();
366 } 362 }
367 } 363 }
368 364
369 void ProxyService::ProcessPendingRequests(PacRequest* recent_req) { 365 void ProxyService::ResumeAllPendingRequests() {
370 if (pending_requests_.empty()) 366 // Make a copy in case |this| is deleted during the synchronous completion
371 return; 367 // of one of the requests. If |this| is deleted then all of the PacRequest
368 // instances will be Cancel()-ed.
369 PendingRequests pending_copy = pending_requests_;
372 370
373 // While the PAC script is being downloaded, requests are blocked. 371 for (PendingRequests::iterator it = pending_copy.begin();
372 it != pending_copy.end();
373 ++it) {
374 PacRequest* req = it->get();
375 if (!req->is_started() && !req->was_cancelled())
376 req->StartAndComplete();
377 }
378 }
379
380 bool ProxyService::PrepareResolverForRequests() {
381 // While the PAC script is being downloaded, block requests.
374 if (IsFetchingPacScript()) 382 if (IsFetchingPacScript())
375 return; 383 return false;
376
377 // Get the next request to process (FIFO).
378 PacRequest* req = pending_requests_.front().get();
379 if (req->is_started_)
380 return;
381
382 // The configuration may have changed since |req| was added to the
383 // queue. It could be this request now completes synchronously.
384 if (req != recent_req) {
385 UpdateConfigIfOld();
386 int rv = TryToCompleteSynchronously(req->url_, req->results_);
387 if (rv != ERR_IO_PENDING) {
388 req->PostCallback(rv);
389 RemoveFrontOfRequestQueue(req);
390 return;
391 }
392 }
393 384
394 // Check if a new PAC script needs to be downloaded. 385 // Check if a new PAC script needs to be downloaded.
395 DCHECK(config_.id() != ProxyConfig::INVALID_ID); 386 DCHECK(config_.id() != ProxyConfig::INVALID_ID);
396 if (!resolver_->does_fetch() && config_.id() != fetched_pac_config_id_) { 387 if (resolver_->expects_pac_bytes() &&
388 config_.id() != fetched_pac_config_id_) {
397 // For auto-detect we use the well known WPAD url. 389 // For auto-detect we use the well known WPAD url.
398 GURL pac_url = config_.auto_detect ? 390 GURL pac_url = config_.auto_detect ?
399 GURL("http://wpad/wpad.dat") : config_.pac_url; 391 GURL("http://wpad/wpad.dat") : config_.pac_url;
400 392
401 in_progress_fetch_config_id_ = config_.id(); 393 in_progress_fetch_config_id_ = config_.id();
402 394
403 LOG(INFO) << "Starting fetch of PAC script " << pac_url 395 LOG(INFO) << "Starting fetch of PAC script " << pac_url
404 << " for config_id=" << in_progress_fetch_config_id_; 396 << " for config_id=" << in_progress_fetch_config_id_;
405 397
406 proxy_script_fetcher_->Fetch( 398 proxy_script_fetcher_->Fetch(
407 pac_url, &in_progress_fetch_bytes_, &proxy_script_fetcher_callback_); 399 pac_url, &in_progress_fetch_bytes_, &proxy_script_fetcher_callback_);
408 return; 400 return false;
409 } 401 }
410 402
411 // The only choice left now is to actually run the ProxyResolver on 403 // We are good to go.
412 // the PAC thread. 404 return true;
413 InitPacThread();
414 req->Query();
415 }
416
417 void ProxyService::RemoveFrontOfRequestQueue(PacRequest* expected_req) {
418 DCHECK(pending_requests_.front().get() == expected_req);
419 pending_requests_.pop_front();
420
421 // Start next work item.
422 ProcessPendingRequests(NULL);
423 } 405 }
424 406
425 void ProxyService::OnScriptFetchCompletion(int result) { 407 void ProxyService::OnScriptFetchCompletion(int result) {
426 DCHECK(IsFetchingPacScript()); 408 DCHECK(IsFetchingPacScript());
427 DCHECK(!resolver_->does_fetch()); 409 DCHECK(resolver_->expects_pac_bytes());
428 410
429 LOG(INFO) << "Completed PAC script fetch for config_id=" 411 LOG(INFO) << "Completed PAC script fetch for config_id="
430 << in_progress_fetch_config_id_ 412 << in_progress_fetch_config_id_
431 << " with error " << ErrorToString(result) 413 << " with error " << ErrorToString(result)
432 << ". Fetched a total of " << in_progress_fetch_bytes_.size() 414 << ". Fetched a total of " << in_progress_fetch_bytes_.size()
433 << " bytes"; 415 << " bytes";
434 416
435 // Notify the ProxyResolver of the new script data (will be empty string if 417 // Notify the ProxyResolver of the new script data (will be empty string if
436 // result != OK). 418 // result != OK).
437 InitPacThread(); 419 resolver_->SetPacScriptByData(in_progress_fetch_bytes_);
438 pac_thread()->message_loop()->PostTask(FROM_HERE,
439 new NotifyFetchCompletionTask(
440 resolver_.get(), in_progress_fetch_bytes_));
441 420
442 fetched_pac_config_id_ = in_progress_fetch_config_id_; 421 fetched_pac_config_id_ = in_progress_fetch_config_id_;
443 fetched_pac_error_ = result; 422 fetched_pac_error_ = result;
444 in_progress_fetch_config_id_ = ProxyConfig::INVALID_ID; 423 in_progress_fetch_config_id_ = ProxyConfig::INVALID_ID;
445 in_progress_fetch_bytes_.clear(); 424 in_progress_fetch_bytes_.clear();
446 425
447 // Start a pending request if any. 426 // Resume any requests which we had to defer until the PAC script was
448 ProcessPendingRequests(NULL); 427 // downloaded.
428 ResumeAllPendingRequests();
449 } 429 }
450 430
451 int ProxyService::ReconsiderProxyAfterError(const GURL& url, 431 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
452 ProxyInfo* result, 432 ProxyInfo* result,
453 CompletionCallback* callback, 433 CompletionCallback* callback,
454 PacRequest** pac_request) { 434 PacRequest** pac_request) {
455 // Check to see if we have a new config since ResolveProxy was called. We 435 // Check to see if we have a new config since ResolveProxy was called. We
456 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a 436 // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
457 // direct connection failed and we never tried the current config. 437 // direct connection failed and we never tried the current config.
458 438
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 471
492 // If we already tried a direct connection, then just give up. 472 // If we already tried a direct connection, then just give up.
493 if (was_direct) 473 if (was_direct)
494 return ERR_FAILED; 474 return ERR_FAILED;
495 475
496 // Try going direct. 476 // Try going direct.
497 result->UseDirect(); 477 result->UseDirect();
498 return OK; 478 return OK;
499 } 479 }
500 480
501 // There are four states of the request we need to handle:
502 // (1) Not started (just sitting in the queue).
503 // (2) Executing PacRequest::DoQuery in the PAC thread.
504 // (3) Waiting for PacRequest::QueryComplete to be run on the origin thread.
505 // (4) Waiting for PacRequest::DoCallback to be run on the origin thread.
506 void ProxyService::CancelPacRequest(PacRequest* req) { 481 void ProxyService::CancelPacRequest(PacRequest* req) {
507 DCHECK(req); 482 DCHECK(req);
483 req->Cancel();
484 RemovePendingRequest(req);
485 }
508 486
509 bool is_active_request = req->is_started_ && !pending_requests_.empty() && 487 bool ProxyService::ContainsPendingRequest(PacRequest* req) {
510 pending_requests_.front().get() == req; 488 PendingRequests::iterator it = std::find(
489 pending_requests_.begin(), pending_requests_.end(), req);
490 return pending_requests_.end() != it;
491 }
511 492
512 req->Cancel(); 493 void ProxyService::RemovePendingRequest(PacRequest* req) {
513 494 DCHECK(ContainsPendingRequest(req));
514 if (is_active_request) { 495 PendingRequests::iterator it = std::find(
515 RemoveFrontOfRequestQueue(req);
516 return;
517 }
518
519 // Otherwise just delete the request from the queue.
520 PendingRequestsQueue::iterator it = std::find(
521 pending_requests_.begin(), pending_requests_.end(), req); 496 pending_requests_.begin(), pending_requests_.end(), req);
522 if (it != pending_requests_.end()) { 497 pending_requests_.erase(it);
523 pending_requests_.erase(it);
524 }
525 } 498 }
526 499
527 void ProxyService::SetProxyScriptFetcher( 500 void ProxyService::SetProxyScriptFetcher(
528 ProxyScriptFetcher* proxy_script_fetcher) { 501 ProxyScriptFetcher* proxy_script_fetcher) {
529 proxy_script_fetcher_.reset(proxy_script_fetcher); 502 proxy_script_fetcher_.reset(proxy_script_fetcher);
530 } 503 }
531 504
532 void ProxyService::ResetConfigService( 505 void ProxyService::ResetConfigService(
533 ProxyConfigService* new_proxy_config_service) { 506 ProxyConfigService* new_proxy_config_service) {
534 config_service_.reset(new_proxy_config_service); 507 config_service_.reset(new_proxy_config_service);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 config_ = config; 587 config_ = config;
615 588
616 // Increment the ID to reflect that the config has changed. 589 // Increment the ID to reflect that the config has changed.
617 config_.set_id(next_config_id_++); 590 config_.set_id(next_config_id_++);
618 591
619 LOG(INFO) << "New proxy configuration was loaded:\n" << config_; 592 LOG(INFO) << "New proxy configuration was loaded:\n" << config_;
620 593
621 // Reset state associated with latest config. 594 // Reset state associated with latest config.
622 config_is_bad_ = false; 595 config_is_bad_ = false;
623 proxy_retry_info_.clear(); 596 proxy_retry_info_.clear();
597
598 // Tell the resolver to use the new PAC URL (for resolver's that fetch the
599 // PAC script internally).
600 // TODO(eroman): this isn't quite right. See http://crbug.com/9985
601 if ((config_.pac_url.is_valid() || config_.auto_detect) &&
602 !resolver_->expects_pac_bytes()) {
603 const GURL pac_url = config_.auto_detect ? GURL() : config_.pac_url;
604 resolver_->SetPacScriptByUrl(pac_url);
605 }
624 } 606 }
625 607
626 void ProxyService::UpdateConfigIfOld() { 608 void ProxyService::UpdateConfigIfOld() {
627 // The overhead of calling ProxyConfigService::GetProxyConfig is very low. 609 // The overhead of calling ProxyConfigService::GetProxyConfig is very low.
628 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5); 610 const TimeDelta kProxyConfigMaxAge = TimeDelta::FromSeconds(5);
629 611
630 // Periodically check for a new config. 612 // Periodically check for a new config.
631 if (!config_has_been_initialized() || 613 if (!config_has_been_initialized() ||
632 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge) 614 (TimeTicks::Now() - config_last_update_time_) > kProxyConfigMaxAge)
633 UpdateConfig(); 615 UpdateConfig();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 OnCompletion(result_); 743 OnCompletion(result_);
762 } 744 }
763 } 745 }
764 746
765 void SyncProxyServiceHelper::OnCompletion(int rv) { 747 void SyncProxyServiceHelper::OnCompletion(int rv) {
766 result_ = rv; 748 result_ = rv;
767 event_.Signal(); 749 event_.Signal();
768 } 750 }
769 751
770 } // namespace net 752 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_service.h ('k') | net/proxy/proxy_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698