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

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

Issue 9078003: Poll PAC scripts for content changes. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: address wtc comments Created 8 years, 11 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
« 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) 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/proxy_service.h" 5 #include "net/proxy/proxy_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 14 #include "base/message_loop.h"
14 #include "base/message_loop_proxy.h" 15 #include "base/message_loop_proxy.h"
15 #include "base/string_util.h" 16 #include "base/string_util.h"
16 #include "base/values.h" 17 #include "base/values.h"
17 #include "googleurl/src/gurl.h" 18 #include "googleurl/src/gurl.h"
18 #include "net/base/completion_callback.h" 19 #include "net/base/completion_callback.h"
19 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h" 21 #include "net/base/net_log.h"
21 #include "net/base/net_util.h" 22 #include "net/base/net_util.h"
22 #include "net/proxy/dhcp_proxy_script_fetcher.h" 23 #include "net/proxy/dhcp_proxy_script_fetcher.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // During this time window, any resolve requests sent to the ProxyService will 59 // During this time window, any resolve requests sent to the ProxyService will
59 // be queued. Once we have waited the required amount of them, the proxy 60 // be queued. Once we have waited the required amount of them, the proxy
60 // auto-config step will be run, and the queued requests resumed. 61 // auto-config step will be run, and the queued requests resumed.
61 // 62 //
62 // The reason we play this game is that our signal for detecting network 63 // The reason we play this game is that our signal for detecting network
63 // changes (NetworkChangeNotifier) may fire *before* the system's networking 64 // changes (NetworkChangeNotifier) may fire *before* the system's networking
64 // dependencies are fully configured. This is a problem since it means if 65 // dependencies are fully configured. This is a problem since it means if
65 // we were to run proxy auto-config right away, it could fail due to spurious 66 // we were to run proxy auto-config right away, it could fail due to spurious
66 // DNS failures. (see http://crbug.com/50779 for more details.) 67 // DNS failures. (see http://crbug.com/50779 for more details.)
67 // 68 //
68 // By adding the wait window, we give things a chance to get properly set up. 69 // By adding the wait window, we give things a better chance to get properly
69 // Now by the time we run the proxy-autoconfig there is a lower chance of 70 // set up. Network failures can happen at any time though, so we additionally
70 // getting transient DNS / connect failures. 71 // poll the PAC script for changes, which will allow us to recover from these
71 // 72 // sorts of problems.
72 // Admittedly this is a hack. Ideally we would have NetworkChangeNotifier
73 // deliver a reliable signal indicating that the network has changed AND is
74 // ready for action... But until then, we can reduce the likelihood of users
75 // getting wedged because of proxy detection failures on network switch.
76 //
77 // The obvious downside to this strategy is it introduces an additional
78 // latency when switching networks. This delay shouldn't be too disruptive
79 // assuming network switches are infrequent and user initiated. However if
80 // NetworkChangeNotifier delivers network changes more frequently this could
81 // cause jankiness. (NetworkChangeNotifier broadcasts a change event when ANY
82 // interface goes up/down. So in theory if the non-primary interface were
83 // hopping on and off wireless networks our constant delayed reconfiguration
84 // could add noticeable jank.)
85 //
86 // The specific hard-coded wait time below is arbitrary.
87 // Basically I ran some experiments switching between wireless networks on
88 // a Linux Ubuntu (Lucid) laptop, and experimentally found this timeout fixes
89 // things. It is entirely possible that the value is insufficient for other
90 // setups.
91 const int64 kNumMillisToStallAfterNetworkChanges = 2000; 73 const int64 kNumMillisToStallAfterNetworkChanges = 2000;
wtc 2012/01/04 22:14:15 Nit: rename this constant kDelayAfterNetworkChange
eroman 2012/01/04 22:40:12 Done.
92 74
75 // The initial number of milliseconds to wait before refetching PAC script after
76 // a fetch error/success.
77 const int64 kInitialPollDelayForErrorMs = 4000;
78 const int64 kInitialPollDelayForSuccessMs = 16000;
79
80 // The maximum poll delay for checking PAC scripts.
81 const int64 kMaxPollDelayMs = 120000; // 2 minutes.
82
93 // Config getter that always returns direct settings. 83 // Config getter that always returns direct settings.
94 class ProxyConfigServiceDirect : public ProxyConfigService { 84 class ProxyConfigServiceDirect : public ProxyConfigService {
95 public: 85 public:
96 // ProxyConfigService implementation: 86 // ProxyConfigService implementation:
97 virtual void AddObserver(Observer* observer) OVERRIDE {} 87 virtual void AddObserver(Observer* observer) OVERRIDE {}
98 virtual void RemoveObserver(Observer* observer) OVERRIDE {} 88 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
99 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) 89 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
100 OVERRIDE { 90 OVERRIDE {
101 *config = ProxyConfig::CreateDirect(); 91 *config = ProxyConfig::CreateDirect();
102 return CONFIG_VALID; 92 return CONFIG_VALID;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 306
317 } // namespace 307 } // namespace
318 308
319 // ProxyService::InitProxyResolver -------------------------------------------- 309 // ProxyService::InitProxyResolver --------------------------------------------
320 310
321 // This glues together two asynchronous steps: 311 // This glues together two asynchronous steps:
322 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o 312 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o
323 // figure out what we should configure against. 313 // figure out what we should configure against.
324 // (2) Feed the fetched PAC script into the ProxyResolver. 314 // (2) Feed the fetched PAC script into the ProxyResolver.
325 // 315 //
326 // TODO(eroman): This is something of a temporary shim while refactoring to keep 316 // InitProxyResolver is a single-use class which encapsulates cancellation as
327 // things similar. It will probably end up changing while solving bug 90581. 317 // part of its destructor. Start() or StartSkipDecider() should be called just
318 // once. The instance can be destroyed at any time, and the request will be
319 // cancelled.
328 320
329 class ProxyService::InitProxyResolver { 321 class ProxyService::InitProxyResolver {
330 public: 322 public:
331 InitProxyResolver(ProxyResolver* proxy_resolver, 323 InitProxyResolver()
332 ProxyScriptFetcher* proxy_script_fetcher, 324 : proxy_resolver_(NULL),
333 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, 325 next_state_(STATE_NONE) {
334 NetLog* net_log)
335 : decider_(proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log),
336 effective_config_(NULL),
337 proxy_resolver_(proxy_resolver) {
338 } 326 }
339 327
340 ~InitProxyResolver() { 328 ~InitProxyResolver() {
341 // Note that the destruction of ProxyScriptDecider will automatically cancel 329 // Note that the destruction of ProxyScriptDecider will automatically cancel
342 // any outstanding work. 330 // any outstanding work.
343 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) { 331 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
344 proxy_resolver_->CancelSetPacScript(); 332 proxy_resolver_->CancelSetPacScript();
345 } 333 }
346 } 334 }
347 335
348 int Init(const ProxyConfig& config, 336 // Begins initializing the proxy resolver; calls |callback| when done.
349 base::TimeDelta wait_delay, 337 int Start(ProxyResolver* proxy_resolver,
350 ProxyConfig* effective_config, 338 ProxyScriptFetcher* proxy_script_fetcher,
351 const CompletionCallback& callback) { 339 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
340 NetLog* net_log,
341 const ProxyConfig& config,
342 base::TimeDelta wait_delay,
343 const CompletionCallback& callback) {
344 DCHECK_EQ(STATE_NONE, next_state_);
345 proxy_resolver_ = proxy_resolver;
346
347 decider_.reset(new ProxyScriptDecider(
348 proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
352 config_ = config; 349 config_ = config;
353 wait_delay_ = wait_delay; 350 wait_delay_ = wait_delay;
354 effective_config_ = effective_config;
355 callback_ = callback; 351 callback_ = callback;
356 352
357 next_state_ = STATE_DECIDE_PROXY_SCRIPT; 353 next_state_ = STATE_DECIDE_PROXY_SCRIPT;
358 return DoLoop(OK); 354 return DoLoop(OK);
359 } 355 }
360 356
357 // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
358 // |effective_config|, |decider_result| and |script_data| will be used as the
359 // inputs for initializing the ProxyResolver.
360 int StartSkipDecider(ProxyResolver* proxy_resolver,
361 const ProxyConfig& effective_config,
362 int decider_result,
363 ProxyResolverScriptData* script_data,
364 const CompletionCallback& callback) {
365 DCHECK_EQ(STATE_NONE, next_state_);
366 proxy_resolver_ = proxy_resolver;
367
368 effective_config_ = effective_config;
369 script_data_ = script_data;
370 callback_ = callback;
371
372 if (decider_result != OK)
373 return decider_result;
374
375 next_state_ = STATE_SET_PAC_SCRIPT;
376 return DoLoop(OK);
377 }
378
379 // Returns the proxy configuration that was selected by ProxyScriptDecider.
380 // Should only be called upon completion of the initialization.
381 const ProxyConfig& effective_config() const {
382 DCHECK_EQ(STATE_NONE, next_state_);
383 return effective_config_;
384 }
385
386 // Returns the PAC script data that was selected by ProxyScriptDecider.
387 // Should only be called upon completion of the initialization.
388 ProxyResolverScriptData* script_data() {
389 DCHECK_EQ(STATE_NONE, next_state_);
390 return script_data_.get();
391 }
392
361 private: 393 private:
362 enum State { 394 enum State {
363 STATE_NONE, 395 STATE_NONE,
364 STATE_DECIDE_PROXY_SCRIPT, 396 STATE_DECIDE_PROXY_SCRIPT,
365 STATE_DECIDE_PROXY_SCRIPT_COMPLETE, 397 STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
366 STATE_SET_PAC_SCRIPT, 398 STATE_SET_PAC_SCRIPT,
367 STATE_SET_PAC_SCRIPT_COMPLETE, 399 STATE_SET_PAC_SCRIPT_COMPLETE,
368 }; 400 };
369 401
370 int DoLoop(int result) { 402 int DoLoop(int result) {
(...skipping 22 matching lines...) Expand all
393 rv = ERR_UNEXPECTED; 425 rv = ERR_UNEXPECTED;
394 break; 426 break;
395 } 427 }
396 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 428 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
397 return rv; 429 return rv;
398 } 430 }
399 431
400 int DoDecideProxyScript() { 432 int DoDecideProxyScript() {
401 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE; 433 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
402 434
403 return decider_.Start( 435 return decider_->Start(
404 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(), 436 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
405 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 437 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
406 } 438 }
407 439
408 int DoDecideProxyScriptComplete(int result) { 440 int DoDecideProxyScriptComplete(int result) {
409 if (result != OK) 441 if (result != OK)
410 return result; 442 return result;
411 443
412 *effective_config_ = decider_.effective_config(); 444 effective_config_ = decider_->effective_config();
445 script_data_ = decider_->script_data();
446
413 next_state_ = STATE_SET_PAC_SCRIPT; 447 next_state_ = STATE_SET_PAC_SCRIPT;
414 return OK; 448 return OK;
415 } 449 }
416 450
417 int DoSetPacScript() { 451 int DoSetPacScript() {
418 DCHECK(decider_.script_data()); 452 DCHECK(script_data_);
419 // TODO(eroman): Should log this latency to the NetLog. 453 // TODO(eroman): Should log this latency to the NetLog.
420 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; 454 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
421 return proxy_resolver_->SetPacScript( 455 return proxy_resolver_->SetPacScript(
422 decider_.script_data(), 456 script_data_,
423 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 457 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
424 } 458 }
425 459
426 int DoSetPacScriptComplete(int result) { 460 int DoSetPacScriptComplete(int result) {
427 return result; 461 return result;
428 } 462 }
429 463
430 void OnIOCompletion(int result) { 464 void OnIOCompletion(int result) {
431 DCHECK_NE(STATE_NONE, next_state_); 465 DCHECK_NE(STATE_NONE, next_state_);
432 int rv = DoLoop(result); 466 int rv = DoLoop(result);
433 if (rv != ERR_IO_PENDING) 467 if (rv != ERR_IO_PENDING)
434 DoCallback(rv); 468 DoCallback(rv);
435 } 469 }
436 470
437 void DoCallback(int result) { 471 void DoCallback(int result) {
438 DCHECK_NE(ERR_IO_PENDING, result); 472 DCHECK_NE(ERR_IO_PENDING, result);
439 callback_.Run(result); 473 callback_.Run(result);
440 } 474 }
441 475
442 ProxyConfig config_; 476 ProxyConfig config_;
477 ProxyConfig effective_config_;
478 scoped_refptr<ProxyResolverScriptData> script_data_;
443 base::TimeDelta wait_delay_; 479 base::TimeDelta wait_delay_;
444 ProxyScriptDecider decider_; 480 scoped_ptr<ProxyScriptDecider> decider_;
445 ProxyConfig* effective_config_;
446 ProxyResolver* proxy_resolver_; 481 ProxyResolver* proxy_resolver_;
447 CompletionCallback callback_; 482 CompletionCallback callback_;
448 State next_state_; 483 State next_state_;
449 484
450 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver); 485 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
451 }; 486 };
452 487
488 // ProxyService::ProxyScriptDeciderPoller -------------------------------------
489
490 // This helper class encapsulates the logic to schedule and run periodic
491 // background checks to see if the PAC script (or effective proxy configuration)
492 // has changed. If a change is detected, then the caller will be notified via
493 // the ChangeCallback.
494 class ProxyService::ProxyScriptDeciderPoller {
495 public:
496 typedef base::Callback<void(int, ProxyResolverScriptData*,
497 const ProxyConfig&)> ChangeCallback;
498
499 // Builds a poller helper, and starts polling for updates. Whenever a change
500 // is observed, |callback| will be invoked with the details.
501 //
502 // |config| specifies the (unresolved) proxy configuration to poll.
503 // |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
504 // to use the resulting script data with
505 // (so it can choose the right format).
506 // |proxy_script_fetcher| this pointer must remain alive throughout our
507 // lifetime. It is the dependency that will be used
508 // for downloading proxy scripts.
509 // |dhcp_proxy_script_fetcher| similar to |proxy_script_fetcher|, but for
510 // the DHCP dependency.
511 // |init_net_error| This is the initial network error (possibly success)
512 // encountered by the first PAC fetch attempt. We use it
513 // to schedule updates more aggressively if the initial
514 // fetch resulted in an error.
515 // |init_script_data| the initial script data from the PAC fetch attempt.
516 // This is the baseline used to determine when the
517 // script's contents have changed.
518 // |net_log| the NetLog to log progress into.
519 ProxyScriptDeciderPoller(ChangeCallback callback,
520 const ProxyConfig& config,
521 bool proxy_resolver_expects_pac_bytes,
522 ProxyScriptFetcher* proxy_script_fetcher,
523 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
524 int init_net_error,
525 ProxyResolverScriptData* init_script_data,
526 NetLog* net_log)
527 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
528 change_callback_(callback),
529 config_(config),
530 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
531 proxy_script_fetcher_(proxy_script_fetcher),
532 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
533 last_error_(init_net_error),
534 last_script_data_(init_script_data) {
535 // Set the initial poll delay -- we check more aggressively right after a
536 // failure in case it was due to a spurious network error.
537 current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error);
538
539 StartPollTimer();
540 }
541
542 // ----------------------------------
543 // Policy for the retry scheduling.
544 // ----------------------------------
545
546 static int64 GetInitialWaitDelayMs(int error) {
547 switch (poll_policy_) {
548 case POLL_POLICY_REGULAR:
549 // Use a shorter wait delay if the initial fetch resulted in an error.
550 return (error != OK) ?
551 kInitialPollDelayForErrorMs : kInitialPollDelayForSuccessMs;
552 case POLL_POLICY_IMMEDIATE:
553 // Wait a mere 1 millisecond.
554 return 1;
555 case POLL_POLICY_NEVER:
556 // Unreasonably large wait delay, will never fire the check.
557 return 0xFFFFFFFF;
558 }
559
560 // Shouldn't be reached
561 return -1;
562 }
563
564 static int64 GetNextWaitDelayMs(int64 current_delay_ms) {
565 switch (poll_policy_) {
566 case POLL_POLICY_REGULAR:
567 // Increase the delay exponentially up to 2 minutes.
568 return std::min(current_delay_ms * 2, kMaxPollDelayMs);
569 case POLL_POLICY_IMMEDIATE:
570 case POLL_POLICY_NEVER:
571 return current_delay_ms;
572 }
573
574 // Shouldn't be reached
575 return -1;
576 }
577
578 static PollPolicy set_policy(PollPolicy policy) {
579 PollPolicy prev = poll_policy_;
580 poll_policy_ = policy;
581 return prev;
582 }
583
584 private:
585 void StartPollTimer() {
586 DCHECK(!decider_.get());
587
588 MessageLoop::current()->PostDelayedTask(
589 FROM_HERE,
590 base::Bind(&ProxyScriptDeciderPoller::OnPollTimerFired,
591 weak_factory_.GetWeakPtr()),
592 current_poll_delay_ms_);
593 }
594
595 void OnPollTimerFired() {
596 // Start the proxy script decider to see if anything has changed.
597 // TODO(eroman): Pass a proper NetLog rather than NULL.
598 decider_.reset(new ProxyScriptDecider(
599 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
600 int result = decider_->Start(
601 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
602 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
603 base::Unretained(this)));
604
605 if (result != ERR_IO_PENDING)
606 OnProxyScriptDeciderCompleted(result);
607 }
608
609 void OnProxyScriptDeciderCompleted(int result) {
610 if (HasScriptDataChanged(result, decider_->script_data())) {
611 // Something has changed, we must notify the ProxyService so it can
612 // re-initialize its ProxyResolver. Note that we post a notification task
613 // rather than calling it directly -- this is done to avoid an ugly
614 // destruction sequence, since |this| might be destroyed as a result of
615 // the notification.
616 MessageLoop::current()->PostTask(
617 FROM_HERE,
618 base::Bind(
619 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
620 weak_factory_.GetWeakPtr(),
621 result,
622 make_scoped_refptr(decider_->script_data()),
623 decider_->effective_config()));
624 return;
625 }
626
627 decider_.reset();
628
629 // Schedule the next poll check.
630 current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_);
631 StartPollTimer();
632 }
633
634 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
635 if (result != last_error_) {
636 // Something changed -- it was failing before and now it succeeded, or
637 // conversely it succeeded before and now it failed. Or it failed in
638 // both cases, however the specific failure error codes differ.
639 return true;
640 }
641
642 if (result != OK) {
643 // If it failed last time and failed again this time, then nothing has
644 // actually changed (even though the specific error code might be
645 // different).
wtc 2012/01/04 22:14:15 The comment "(even though the specific error code
eroman 2012/01/04 22:40:12 Done.
646 return false;
647 }
648
649 // Otherwise if it succeeded both this time and last time, we need to look
650 // closer and see if we ended up downloading different content for the PAC
651 // script.
652 if (proxy_resolver_expects_pac_bytes_)
653 return script_data->utf16() != last_script_data_->utf16();
wtc 2012/01/05 22:08:27 The code in the new Equals() method seems to imply
654 return script_data->url() != last_script_data_->url();
655 }
656
657 void NotifyProxyServiceOfChange(
658 int result,
659 const scoped_refptr<ProxyResolverScriptData>& script_data,
660 const ProxyConfig& effective_config) {
661 // Note that |this| may be deleted after calling into the ProxyService.
662 change_callback_.Run(result, script_data, effective_config);
663 }
664
665 base::WeakPtrFactory<ProxyScriptDeciderPoller> weak_factory_;
666
667 ChangeCallback change_callback_;
668 ProxyConfig config_;
669 bool proxy_resolver_expects_pac_bytes_;
670 ProxyScriptFetcher* proxy_script_fetcher_;
671 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
672
673 int last_error_;
674 scoped_refptr<ProxyResolverScriptData> last_script_data_;
675
676 scoped_ptr<ProxyScriptDecider> decider_;
677 int64 current_poll_delay_ms_;
678
679 static PollPolicy poll_policy_;
680
681 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
682 };
683
684 // static
685 ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ =
686 ProxyService::POLL_POLICY_REGULAR;
687
453 // ProxyService::PacRequest --------------------------------------------------- 688 // ProxyService::PacRequest ---------------------------------------------------
454 689
455 class ProxyService::PacRequest 690 class ProxyService::PacRequest
456 : public base::RefCounted<ProxyService::PacRequest> { 691 : public base::RefCounted<ProxyService::PacRequest> {
457 public: 692 public:
458 PacRequest(ProxyService* service, 693 PacRequest(ProxyService* service,
459 const GURL& url, 694 const GURL& url,
460 ProxyInfo* results, 695 ProxyInfo* results,
461 const net::CompletionCallback& user_callback, 696 const net::CompletionCallback& user_callback,
462 const BoundNetLog& net_log) 697 const BoundNetLog& net_log)
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 ProxyConfigService::ConfigAvailability availability = 1086 ProxyConfigService::ConfigAvailability availability =
852 config_service_->GetLatestProxyConfig(&config); 1087 config_service_->GetLatestProxyConfig(&config);
853 if (availability != ProxyConfigService::CONFIG_PENDING) 1088 if (availability != ProxyConfigService::CONFIG_PENDING)
854 OnProxyConfigChanged(config, availability); 1089 OnProxyConfigChanged(config, availability);
855 } 1090 }
856 1091
857 void ProxyService::OnInitProxyResolverComplete(int result) { 1092 void ProxyService::OnInitProxyResolverComplete(int result) {
858 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_); 1093 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
859 DCHECK(init_proxy_resolver_.get()); 1094 DCHECK(init_proxy_resolver_.get());
860 DCHECK(fetched_config_.HasAutomaticSettings()); 1095 DCHECK(fetched_config_.HasAutomaticSettings());
1096 config_ = init_proxy_resolver_->effective_config();
1097
1098 // At this point we have decided which proxy settings to use (i.e. which PAC
1099 // script if any). We start up a background poller to periodically revisit
1100 // this decision. If the contents of the PAC script change, or if the
1101 // result of proxy auto-discovery changes, this poller will notice it and
1102 // will trigger a re-initialization using the newly discovered PAC.
1103 script_poller_.reset(new ProxyScriptDeciderPoller(
1104 base::Bind(&ProxyService::InitializeUsingDecidedConfig,
1105 base::Unretained(this)),
1106 fetched_config_,
1107 resolver_->expects_pac_bytes(),
1108 proxy_script_fetcher_.get(),
1109 dhcp_proxy_script_fetcher_.get(),
1110 result,
1111 init_proxy_resolver_->script_data(),
1112 NULL));
1113
861 init_proxy_resolver_.reset(); 1114 init_proxy_resolver_.reset();
862 1115
863 if (result != OK) { 1116 if (result != OK) {
864 if (fetched_config_.pac_mandatory()) { 1117 if (fetched_config_.pac_mandatory()) {
865 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all " 1118 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
866 "traffic."; 1119 "traffic.";
867 config_ = fetched_config_; 1120 config_ = fetched_config_;
868 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED; 1121 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
869 } else { 1122 } else {
870 VLOG(1) << "Failed configuring with PAC script, falling-back to manual " 1123 VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
871 "proxy servers."; 1124 "proxy servers.";
872 config_ = fetched_config_; 1125 config_ = fetched_config_;
873 config_.ClearAutomaticSettings(); 1126 config_.ClearAutomaticSettings();
874 result = OK; 1127 result = OK;
875 } 1128 }
876 } 1129 }
877 permanent_error_ = result; 1130 permanent_error_ = result;
878 1131
1132 // TODO(eroman): Make this ID unique in the case where configuration changed
1133 // due to ProxyScriptDeciderPoller.
879 config_.set_id(fetched_config_.id()); 1134 config_.set_id(fetched_config_.id());
880 1135
881 // Resume any requests which we had to defer until the PAC script was 1136 // Resume any requests which we had to defer until the PAC script was
882 // downloaded. 1137 // downloaded.
883 SetReady(); 1138 SetReady();
884 } 1139 }
885 1140
886 int ProxyService::ReconsiderProxyAfterError(const GURL& url, 1141 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
887 ProxyInfo* result, 1142 ProxyInfo* result,
888 const CompletionCallback& callback, 1143 const CompletionCallback& callback,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 DCHECK(CalledOnValidThread()); 1270 DCHECK(CalledOnValidThread());
1016 return proxy_script_fetcher_.get(); 1271 return proxy_script_fetcher_.get();
1017 } 1272 }
1018 1273
1019 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) { 1274 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
1020 DCHECK(CalledOnValidThread()); 1275 DCHECK(CalledOnValidThread());
1021 State previous_state = current_state_; 1276 State previous_state = current_state_;
1022 1277
1023 permanent_error_ = OK; 1278 permanent_error_ = OK;
1024 proxy_retry_info_.clear(); 1279 proxy_retry_info_.clear();
1280 script_poller_.reset();
1025 init_proxy_resolver_.reset(); 1281 init_proxy_resolver_.reset();
1026 SuspendAllPendingRequests(); 1282 SuspendAllPendingRequests();
1027 config_ = ProxyConfig(); 1283 config_ = ProxyConfig();
1028 if (reset_fetched_config) 1284 if (reset_fetched_config)
1029 fetched_config_ = ProxyConfig(); 1285 fetched_config_ = ProxyConfig();
1030 current_state_ = STATE_NONE; 1286 current_state_ = STATE_NONE;
1031 1287
1032 return previous_state; 1288 return previous_state;
1033 } 1289 }
1034 1290
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 static_cast<MessageLoopForIO*>(file_loop)); 1348 static_cast<MessageLoopForIO*>(file_loop));
1093 1349
1094 return linux_config_service; 1350 return linux_config_service;
1095 #else 1351 #else
1096 LOG(WARNING) << "Failed to choose a system proxy settings fetcher " 1352 LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1097 "for this platform."; 1353 "for this platform.";
1098 return new ProxyConfigServiceDirect(); 1354 return new ProxyConfigServiceDirect();
1099 #endif 1355 #endif
1100 } 1356 }
1101 1357
1358 // static
1359 ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy(
1360 PollPolicy policy) {
1361 return ProxyScriptDeciderPoller::set_policy(policy);
1362 }
1363
1102 void ProxyService::OnProxyConfigChanged( 1364 void ProxyService::OnProxyConfigChanged(
1103 const ProxyConfig& config, 1365 const ProxyConfig& config,
1104 ProxyConfigService::ConfigAvailability availability) { 1366 ProxyConfigService::ConfigAvailability availability) {
1105 // Retrieve the current proxy configuration from the ProxyConfigService. 1367 // Retrieve the current proxy configuration from the ProxyConfigService.
1106 // If a configuration is not available yet, we will get called back later 1368 // If a configuration is not available yet, we will get called back later
1107 // by our ProxyConfigService::Observer once it changes. 1369 // by our ProxyConfigService::Observer once it changes.
1108 ProxyConfig effective_config; 1370 ProxyConfig effective_config;
1109 switch (availability) { 1371 switch (availability) {
1110 case ProxyConfigService::CONFIG_PENDING: 1372 case ProxyConfigService::CONFIG_PENDING:
1111 // ProxyConfigService implementors should never pass CONFIG_PENDING. 1373 // ProxyConfigService implementors should never pass CONFIG_PENDING.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1409
1148 if (!fetched_config_.HasAutomaticSettings()) { 1410 if (!fetched_config_.HasAutomaticSettings()) {
1149 config_ = fetched_config_; 1411 config_ = fetched_config_;
1150 SetReady(); 1412 SetReady();
1151 return; 1413 return;
1152 } 1414 }
1153 1415
1154 // Start downloading + testing the PAC scripts for this new configuration. 1416 // Start downloading + testing the PAC scripts for this new configuration.
1155 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER; 1417 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1156 1418
1157 init_proxy_resolver_.reset(
1158 new InitProxyResolver(resolver_.get(),
1159 proxy_script_fetcher_.get(),
1160 dhcp_proxy_script_fetcher_.get(),
1161 net_log_));
1162
1163 // If we changed networks recently, we should delay running proxy auto-config. 1419 // If we changed networks recently, we should delay running proxy auto-config.
1164 base::TimeDelta wait_delay = 1420 base::TimeDelta wait_delay =
1165 stall_proxy_autoconfig_until_ - base::TimeTicks::Now(); 1421 stall_proxy_autoconfig_until_ - base::TimeTicks::Now();
1166 1422
1167 int rv = init_proxy_resolver_->Init( 1423 init_proxy_resolver_.reset(new InitProxyResolver());
1168 fetched_config_, wait_delay, &config_, 1424 int rv = init_proxy_resolver_->Start(
1425 resolver_.get(),
1426 proxy_script_fetcher_.get(),
1427 dhcp_proxy_script_fetcher_.get(),
1428 net_log_,
1429 fetched_config_,
1430 wait_delay,
1169 base::Bind(&ProxyService::OnInitProxyResolverComplete, 1431 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1170 base::Unretained(this))); 1432 base::Unretained(this)));
1171 1433
1434 if (rv != ERR_IO_PENDING)
1435 OnInitProxyResolverComplete(rv);
1436 }
1437
1438 void ProxyService::InitializeUsingDecidedConfig(
1439 int decider_result,
1440 ProxyResolverScriptData* script_data,
1441 const ProxyConfig& effective_config) {
1442 DCHECK(fetched_config_.is_valid());
1443 DCHECK(fetched_config_.HasAutomaticSettings());
1444
1445 ResetProxyConfig(false);
1446
1447 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1448
1449 init_proxy_resolver_.reset(new InitProxyResolver());
1450 int rv = init_proxy_resolver_->StartSkipDecider(
1451 resolver_.get(),
1452 effective_config,
1453 decider_result,
1454 script_data,
1455 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1456 base::Unretained(this)));
1457
1172 if (rv != ERR_IO_PENDING) 1458 if (rv != ERR_IO_PENDING)
1173 OnInitProxyResolverComplete(rv); 1459 OnInitProxyResolverComplete(rv);
1174 } 1460 }
1175 1461
1176 void ProxyService::OnIPAddressChanged() { 1462 void ProxyService::OnIPAddressChanged() {
1177 // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info. 1463 // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info.
1178 stall_proxy_autoconfig_until_ = 1464 stall_proxy_autoconfig_until_ =
1179 base::TimeTicks::Now() + stall_proxy_auto_config_delay_; 1465 base::TimeTicks::Now() + stall_proxy_auto_config_delay_;
1180 1466
1181 State previous_state = ResetProxyConfig(false); 1467 State previous_state = ResetProxyConfig(false);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 OnCompletion(result_); 1534 OnCompletion(result_);
1249 } 1535 }
1250 } 1536 }
1251 1537
1252 void SyncProxyServiceHelper::OnCompletion(int rv) { 1538 void SyncProxyServiceHelper::OnCompletion(int rv) {
1253 result_ = rv; 1539 result_ = rv;
1254 event_.Signal(); 1540 event_.Signal();
1255 } 1541 }
1256 1542
1257 } // namespace net 1543 } // 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