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

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: 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
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"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // During this time window, any resolve requests sent to the ProxyService will 58 // 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 59 // 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. 60 // auto-config step will be run, and the queued requests resumed.
61 // 61 //
62 // The reason we play this game is that our signal for detecting network 62 // The reason we play this game is that our signal for detecting network
63 // changes (NetworkChangeNotifier) may fire *before* the system's networking 63 // changes (NetworkChangeNotifier) may fire *before* the system's networking
64 // dependencies are fully configured. This is a problem since it means if 64 // 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 65 // 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.) 66 // DNS failures. (see http://crbug.com/50779 for more details.)
67 // 67 //
68 // By adding the wait window, we give things a chance to get properly set up. 68 // 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 69 // set up. Network failures can happen at any time though, so we additionally
70 // getting transient DNS / connect failures. 70 // poll the PAC script for changes, which will allow us to recover from these
71 // 71 // 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; 72 const int64 kNumMillisToStallAfterNetworkChanges = 2000;
92 73
93 // Config getter that always returns direct settings. 74 // Config getter that always returns direct settings.
94 class ProxyConfigServiceDirect : public ProxyConfigService { 75 class ProxyConfigServiceDirect : public ProxyConfigService {
95 public: 76 public:
96 // ProxyConfigService implementation: 77 // ProxyConfigService implementation:
97 virtual void AddObserver(Observer* observer) OVERRIDE {} 78 virtual void AddObserver(Observer* observer) OVERRIDE {}
98 virtual void RemoveObserver(Observer* observer) OVERRIDE {} 79 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
99 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) 80 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
100 OVERRIDE { 81 OVERRIDE {
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 297
317 } // namespace 298 } // namespace
318 299
319 // ProxyService::InitProxyResolver -------------------------------------------- 300 // ProxyService::InitProxyResolver --------------------------------------------
320 301
321 // This glues together two asynchronous steps: 302 // This glues together two asynchronous steps:
322 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o 303 // (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts t o
323 // figure out what we should configure against. 304 // figure out what we should configure against.
324 // (2) Feed the fetched PAC script into the ProxyResolver. 305 // (2) Feed the fetched PAC script into the ProxyResolver.
325 // 306 //
326 // TODO(eroman): This is something of a temporary shim while refactoring to keep 307 // InitProxyResolver is a single-use class which encapsulates cancellation as
327 // things similar. It will probably end up changing while solving bug 90581. 308 // part of its destructor. Start() or StartSkipDecider() should be called just
309 // once. The instance can be destroyed at any time, and the request will be
310 // cancelled.
328 311
329 class ProxyService::InitProxyResolver { 312 class ProxyService::InitProxyResolver {
330 public: 313 public:
331 InitProxyResolver(ProxyResolver* proxy_resolver, 314 InitProxyResolver()
332 ProxyScriptFetcher* proxy_script_fetcher, 315 : proxy_resolver_(NULL),
333 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, 316 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 } 317 }
339 318
340 ~InitProxyResolver() { 319 ~InitProxyResolver() {
341 // Note that the destruction of ProxyScriptDecider will automatically cancel 320 // Note that the destruction of ProxyScriptDecider will automatically cancel
342 // any outstanding work. 321 // any outstanding work.
343 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) { 322 if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
344 proxy_resolver_->CancelSetPacScript(); 323 proxy_resolver_->CancelSetPacScript();
345 } 324 }
346 } 325 }
347 326
348 int Init(const ProxyConfig& config, 327 // Begins initializing the proxy resolver; calls |callback| when done.
349 base::TimeDelta wait_delay, 328 int Start(ProxyResolver* proxy_resolver,
350 ProxyConfig* effective_config, 329 ProxyScriptFetcher* proxy_script_fetcher,
351 const CompletionCallback& callback) { 330 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
331 NetLog* net_log,
332 const ProxyConfig& config,
333 base::TimeDelta wait_delay,
334 const CompletionCallback& callback) {
335 DCHECK_EQ(STATE_NONE, next_state_);
336 proxy_resolver_ = proxy_resolver;
337
338 decider_.reset(new ProxyScriptDecider(
339 proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
352 config_ = config; 340 config_ = config;
353 wait_delay_ = wait_delay; 341 wait_delay_ = wait_delay;
354 effective_config_ = effective_config;
355 callback_ = callback; 342 callback_ = callback;
356 343
357 next_state_ = STATE_DECIDE_PROXY_SCRIPT; 344 next_state_ = STATE_DECIDE_PROXY_SCRIPT;
358 return DoLoop(OK); 345 return DoLoop(OK);
359 } 346 }
360 347
348 // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
349 // |effective_config|, |decider_result|, |script_data| will be used as the
wtc 2012/01/03 23:54:45 Nit: add "and" before |script_data|.
eroman 2012/01/04 03:41:47 Done.
350 // inputs for initializing the ProxyResolver.
351 int StartSkipDecider(ProxyResolver* proxy_resolver,
352 const ProxyConfig& effective_config,
353 int decider_result,
354 ProxyResolverScriptData* script_data,
355 const CompletionCallback& callback) {
356 DCHECK_EQ(STATE_NONE, next_state_);
357 proxy_resolver_ = proxy_resolver;
358
359 effective_config_ = effective_config;
360 script_data_ = script_data;
361 callback_ = callback;
362
363 if (decider_result != OK)
364 return decider_result;
wtc 2012/01/03 23:54:45 IMPORTANT: do we need to call callback in this cas
eroman 2012/01/04 00:11:24 |callback| should not be called in this case. The
365
366 next_state_ = STATE_SET_PAC_SCRIPT;
367 return DoLoop(OK);
368 }
369
370 // Returns the proxy configuration that was selected by ProxyScriptDecider.
371 // Should only be called upon completion of the initialization.
372 const ProxyConfig& effective_config() const {
373 DCHECK_EQ(STATE_NONE, next_state_);
374 return effective_config_;
375 }
376
377 // Returns the PAC script data that was selected by ProxyScriptDecider.
378 // Should only be called upon completion of the initialization.
379 ProxyResolverScriptData* script_data() {
380 DCHECK_EQ(STATE_NONE, next_state_);
381 return script_data_.get();
382 }
383
361 private: 384 private:
362 enum State { 385 enum State {
363 STATE_NONE, 386 STATE_NONE,
364 STATE_DECIDE_PROXY_SCRIPT, 387 STATE_DECIDE_PROXY_SCRIPT,
365 STATE_DECIDE_PROXY_SCRIPT_COMPLETE, 388 STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
366 STATE_SET_PAC_SCRIPT, 389 STATE_SET_PAC_SCRIPT,
367 STATE_SET_PAC_SCRIPT_COMPLETE, 390 STATE_SET_PAC_SCRIPT_COMPLETE,
368 }; 391 };
369 392
370 int DoLoop(int result) { 393 int DoLoop(int result) {
(...skipping 22 matching lines...) Expand all
393 rv = ERR_UNEXPECTED; 416 rv = ERR_UNEXPECTED;
394 break; 417 break;
395 } 418 }
396 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 419 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
397 return rv; 420 return rv;
398 } 421 }
399 422
400 int DoDecideProxyScript() { 423 int DoDecideProxyScript() {
401 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE; 424 next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
402 425
403 return decider_.Start( 426 return decider_->Start(
404 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(), 427 config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
405 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 428 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
406 } 429 }
407 430
408 int DoDecideProxyScriptComplete(int result) { 431 int DoDecideProxyScriptComplete(int result) {
409 if (result != OK) 432 if (result != OK)
410 return result; 433 return result;
411 434
412 *effective_config_ = decider_.effective_config(); 435 effective_config_ = decider_->effective_config();
436 script_data_ = decider_->script_data();
437
413 next_state_ = STATE_SET_PAC_SCRIPT; 438 next_state_ = STATE_SET_PAC_SCRIPT;
414 return OK; 439 return OK;
415 } 440 }
416 441
417 int DoSetPacScript() { 442 int DoSetPacScript() {
418 DCHECK(decider_.script_data()); 443 DCHECK(script_data_);
419 // TODO(eroman): Should log this latency to the NetLog. 444 // TODO(eroman): Should log this latency to the NetLog.
420 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; 445 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
421 return proxy_resolver_->SetPacScript( 446 return proxy_resolver_->SetPacScript(
422 decider_.script_data(), 447 script_data_,
423 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this))); 448 base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
424 } 449 }
425 450
426 int DoSetPacScriptComplete(int result) { 451 int DoSetPacScriptComplete(int result) {
427 return result; 452 return result;
428 } 453 }
429 454
430 void OnIOCompletion(int result) { 455 void OnIOCompletion(int result) {
431 DCHECK_NE(STATE_NONE, next_state_); 456 DCHECK_NE(STATE_NONE, next_state_);
432 int rv = DoLoop(result); 457 int rv = DoLoop(result);
433 if (rv != ERR_IO_PENDING) 458 if (rv != ERR_IO_PENDING)
434 DoCallback(rv); 459 DoCallback(rv);
435 } 460 }
436 461
437 void DoCallback(int result) { 462 void DoCallback(int result) {
438 DCHECK_NE(ERR_IO_PENDING, result); 463 DCHECK_NE(ERR_IO_PENDING, result);
439 callback_.Run(result); 464 callback_.Run(result);
440 } 465 }
441 466
442 ProxyConfig config_; 467 ProxyConfig config_;
468 ProxyConfig effective_config_;
469 scoped_refptr<ProxyResolverScriptData> script_data_;
443 base::TimeDelta wait_delay_; 470 base::TimeDelta wait_delay_;
444 ProxyScriptDecider decider_; 471 scoped_ptr<ProxyScriptDecider> decider_;
445 ProxyConfig* effective_config_;
446 ProxyResolver* proxy_resolver_; 472 ProxyResolver* proxy_resolver_;
447 CompletionCallback callback_; 473 CompletionCallback callback_;
448 State next_state_; 474 State next_state_;
449 475
450 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver); 476 DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
451 }; 477 };
452 478
479 // ProxyService::ProxyScriptDeciderPoller -------------------------------------
480
481 // This helper class encapsulates the logic to schedule and run periodic
482 // background checks to see if the PAC script (or effective proxy configuration)
483 // has changed. If a change is detected, then the caller will be notified via
484 // the ChangeCallback.
485 class ProxyService::ProxyScriptDeciderPoller {
486 public:
487 typedef base::Callback<void(int, ProxyResolverScriptData*,
488 const ProxyConfig& )> ChangeCallback;
wtc 2012/01/03 23:54:45 Nit: is the space before the closing parenthesis '
eroman 2012/01/04 03:41:47 Done.
489
490 ProxyScriptDeciderPoller(ChangeCallback callback,
491 const ProxyConfig& config,
492 bool proxy_resolver_expects_pac_bytes,
493 ProxyScriptFetcher* proxy_script_fetcher,
494 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
495 int init_net_error,
496 ProxyResolverScriptData* init_script_data,
497 NetLog* net_log)
wtc 2012/01/03 23:54:45 Nit: document at least the more important paramete
eroman 2012/01/04 03:41:47 Done.
498 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
499 change_callback_(callback),
500 config_(config),
501 proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
502 proxy_script_fetcher_(proxy_script_fetcher),
503 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
504 last_error_(init_net_error),
505 last_script_data_(init_script_data) {
506 // Set the initial poll delay -- we check more aggressively right after a
507 // failure in case it was due to a spurious network error.
508 current_poll_delay_ms_ = GetInitialWaitDelayMs(init_net_error);
509
510 StartPollTimer();
511 }
512
513 // ----------------------------------
514 // Policy for the retry scheduling.
515 // ----------------------------------
516
517 static int64 GetInitialWaitDelayMs(int error) {
518 switch (poll_policy_) {
519 case POLL_POLICY_REGULAR:
520 // Wait 4 seconds before trying after an error, and 16 seconds after
521 // success.
522 return (error == OK) ? 4000 : 16000;
wtc 2012/01/03 23:54:45 BUG(?): if we check more aggressively right after
eroman 2012/01/04 00:11:24 You are correct, this is a bug! I'll have to thin
eroman 2012/01/04 03:41:47 Done.
523 case POLL_POLICY_IMMEDIATE:
524 // Wait a mere 1 millisecond.
525 return 1;
526 case POLL_POLICY_NEVER:
527 // Unreasonably large wait delay, will never fire the check.
528 return 0xFFFFFFFF;
529 }
530
531 // Shouldn't be reached
532 return -1;
wtc 2012/01/03 23:54:45 Nit: it seems better to do this as a default case.
eroman 2012/01/04 00:11:24 I prefer not to use default cases, since if I do t
533 }
534
535 static int64 GetNextWaitDelayMs(int64 current_delay_ms) {
536 switch (poll_policy_) {
537 case POLL_POLICY_REGULAR:
538 // Increase the delay exponentially up to 2 minutes.
539 return std::min(current_delay_ms * 2, static_cast<int64>(120000));
wtc 2012/01/03 23:54:45 IMPORTANT: it would be nice to define constants fo
eroman 2012/01/04 03:41:47 Done.
540 case POLL_POLICY_IMMEDIATE:
541 case POLL_POLICY_NEVER:
542 return current_delay_ms;
543 }
544
545 // Shouldn't be reached
546 return -1;
547 }
548
549 static PollPolicy set_policy(PollPolicy policy) {
550 PollPolicy prev = poll_policy_;
551 poll_policy_ = policy;
552 return prev;
553 }
554
555 private:
556 void StartPollTimer() {
557 DCHECK(!decider_.get());
558
559 MessageLoop::current()->PostDelayedTask(
560 FROM_HERE,
561 method_factory_.NewRunnableMethod(
562 &ProxyScriptDeciderPoller::OnPollTimerFired),
563 current_poll_delay_ms_);
564 }
565
566 void OnPollTimerFired() {
567 // Start the proxy script decider to see if anything has changed.
568 // TODO(eroman): Pass a proper NetLog rather than NULL.
569 decider_.reset(new ProxyScriptDecider(
570 proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
571 int result = decider_->Start(
572 config_, base::TimeDelta(), proxy_resolver_expects_pac_bytes_,
573 base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
574 base::Unretained(this)));
575
576 if (result != ERR_IO_PENDING)
577 OnProxyScriptDeciderCompleted(result);
578 }
579
580 void OnProxyScriptDeciderCompleted(int result) {
581 if (HasScriptDataChanged(result, decider_->script_data())) {
582 // Something has changed, we must notify the ProxyService so it can
583 // re-initialize its ProxyResolver. Note that we post a notification task
584 // rather than calling it directly -- this is done to avoid an ugly
585 // destruction sequence, since |this| might be destroyed as a result of
586 // the notification.
587 MessageLoop::current()->PostTask(
588 FROM_HERE,
589 method_factory_.NewRunnableMethod(
wtc 2012/01/03 23:54:45 IMPORTANT: I think the new way is to use a WeakPtr
eroman 2012/01/04 00:11:24 Thanks, I will look into this and update.
eroman 2012/01/04 03:41:47 Done.
590 &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
591 result,
592 make_scoped_refptr(decider_->script_data()),
593 decider_->effective_config()));
594 return;
595 }
596
597 decider_.reset();
598
599 // Schedule the next poll check.
600 current_poll_delay_ms_ = GetNextWaitDelayMs(current_poll_delay_ms_);
601 StartPollTimer();
602 }
603
604 bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
605 if (result != last_error_) {
606 // Something changed -- it was failing before and now it succeeded, or
607 // conversely it succeeded before and now it failed.
wtc 2012/01/03 23:54:45 IMPORTANT: A third case is that it was failing bef
eroman 2012/01/04 00:11:24 Correct -- if the error code changes (but it is st
608 return true;
609 }
610
611 if (result != OK) {
612 // If it failed last time and failed again this time, then nothing has
613 // actually changed (even though the specific error code might be
614 // different).
615 return false;
616 }
617
618 // Otherwise if it succeeded both this time and last time, we need to look
619 // closer and see if we ended up downloading different content for the PAC
620 // script.
621 if (proxy_resolver_expects_pac_bytes_)
622 return script_data->utf16() != last_script_data_->utf16();
623 return script_data->url() != last_script_data_->url();
624 }
625
626 void NotifyProxyServiceOfChange(
627 int result,
628 const scoped_refptr<ProxyResolverScriptData>& script_data,
629 const ProxyConfig& effective_config) {
630 // Note that |this| may be deleted after calling into the ProxyService.
631 change_callback_.Run(result, script_data, effective_config);
632 }
633
634 ScopedRunnableMethodFactory<ProxyScriptDeciderPoller> method_factory_;
635
636 ChangeCallback change_callback_;
637 ProxyConfig config_;
638 bool proxy_resolver_expects_pac_bytes_;
639 ProxyScriptFetcher* proxy_script_fetcher_;
640 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
641
642 int last_error_;
643 scoped_refptr<ProxyResolverScriptData> last_script_data_;
644
645 scoped_ptr<ProxyScriptDecider> decider_;
646 int64 current_poll_delay_ms_;
647
648 static PollPolicy poll_policy_;
649
650 DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
651 };
652
653 ProxyService::PollPolicy ProxyService::ProxyScriptDeciderPoller::poll_policy_ =
wtc 2012/01/03 23:54:45 Nit: add a // static comment? Not sure if it's
eroman 2012/01/04 03:41:47 Done.
654 ProxyService::POLL_POLICY_REGULAR;
655
453 // ProxyService::PacRequest --------------------------------------------------- 656 // ProxyService::PacRequest ---------------------------------------------------
454 657
455 class ProxyService::PacRequest 658 class ProxyService::PacRequest
456 : public base::RefCounted<ProxyService::PacRequest> { 659 : public base::RefCounted<ProxyService::PacRequest> {
457 public: 660 public:
458 PacRequest(ProxyService* service, 661 PacRequest(ProxyService* service,
459 const GURL& url, 662 const GURL& url,
460 ProxyInfo* results, 663 ProxyInfo* results,
461 const net::CompletionCallback& user_callback, 664 const net::CompletionCallback& user_callback,
462 const BoundNetLog& net_log) 665 const BoundNetLog& net_log)
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 ProxyConfigService::ConfigAvailability availability = 1054 ProxyConfigService::ConfigAvailability availability =
852 config_service_->GetLatestProxyConfig(&config); 1055 config_service_->GetLatestProxyConfig(&config);
853 if (availability != ProxyConfigService::CONFIG_PENDING) 1056 if (availability != ProxyConfigService::CONFIG_PENDING)
854 OnProxyConfigChanged(config, availability); 1057 OnProxyConfigChanged(config, availability);
855 } 1058 }
856 1059
857 void ProxyService::OnInitProxyResolverComplete(int result) { 1060 void ProxyService::OnInitProxyResolverComplete(int result) {
858 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_); 1061 DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
859 DCHECK(init_proxy_resolver_.get()); 1062 DCHECK(init_proxy_resolver_.get());
860 DCHECK(fetched_config_.HasAutomaticSettings()); 1063 DCHECK(fetched_config_.HasAutomaticSettings());
1064 config_ = init_proxy_resolver_->effective_config();
1065
1066 // At this point we have decided which proxy settings to use (i.e. which PAC
1067 // script if any). We start up a background poller to periodically revisit
1068 // this decision. If the contents of the PAC script change, or if the
1069 // result of proxy auto-discovery changes, this instance will notice it and
wtc 2012/01/03 23:54:45 Nit: instance => poller "instance" is vague.
1070 // will trigger a re-initialization using the newly discovered PAC.
1071 script_poller_.reset(new ProxyScriptDeciderPoller(
1072 base::Bind(&ProxyService::InitializeUsingDecidedConfig,
1073 base::Unretained(this)),
1074 fetched_config_,
1075 resolver_->expects_pac_bytes(),
1076 proxy_script_fetcher_.get(),
1077 dhcp_proxy_script_fetcher_.get(),
1078 result,
1079 init_proxy_resolver_->script_data(),
1080 NULL));
1081
861 init_proxy_resolver_.reset(); 1082 init_proxy_resolver_.reset();
862 1083
863 if (result != OK) { 1084 if (result != OK) {
864 if (fetched_config_.pac_mandatory()) { 1085 if (fetched_config_.pac_mandatory()) {
865 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all " 1086 VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
866 "traffic."; 1087 "traffic.";
867 config_ = fetched_config_; 1088 config_ = fetched_config_;
868 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED; 1089 result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
869 } else { 1090 } else {
870 VLOG(1) << "Failed configuring with PAC script, falling-back to manual " 1091 VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
871 "proxy servers."; 1092 "proxy servers.";
872 config_ = fetched_config_; 1093 config_ = fetched_config_;
873 config_.ClearAutomaticSettings(); 1094 config_.ClearAutomaticSettings();
874 result = OK; 1095 result = OK;
875 } 1096 }
876 } 1097 }
877 permanent_error_ = result; 1098 permanent_error_ = result;
878 1099
1100 // TODO(eroman): Make this ID unique in the case where configuration changed
1101 // due to ProxyScriptDeciderPoller.
879 config_.set_id(fetched_config_.id()); 1102 config_.set_id(fetched_config_.id());
880 1103
881 // Resume any requests which we had to defer until the PAC script was 1104 // Resume any requests which we had to defer until the PAC script was
882 // downloaded. 1105 // downloaded.
883 SetReady(); 1106 SetReady();
884 } 1107 }
885 1108
886 int ProxyService::ReconsiderProxyAfterError(const GURL& url, 1109 int ProxyService::ReconsiderProxyAfterError(const GURL& url,
887 ProxyInfo* result, 1110 ProxyInfo* result,
888 const CompletionCallback& callback, 1111 const CompletionCallback& callback,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 DCHECK(CalledOnValidThread()); 1238 DCHECK(CalledOnValidThread());
1016 return proxy_script_fetcher_.get(); 1239 return proxy_script_fetcher_.get();
1017 } 1240 }
1018 1241
1019 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) { 1242 ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
1020 DCHECK(CalledOnValidThread()); 1243 DCHECK(CalledOnValidThread());
1021 State previous_state = current_state_; 1244 State previous_state = current_state_;
1022 1245
1023 permanent_error_ = OK; 1246 permanent_error_ = OK;
1024 proxy_retry_info_.clear(); 1247 proxy_retry_info_.clear();
1248 script_poller_.reset();
1025 init_proxy_resolver_.reset(); 1249 init_proxy_resolver_.reset();
1026 SuspendAllPendingRequests(); 1250 SuspendAllPendingRequests();
1027 config_ = ProxyConfig(); 1251 config_ = ProxyConfig();
1028 if (reset_fetched_config) 1252 if (reset_fetched_config)
1029 fetched_config_ = ProxyConfig(); 1253 fetched_config_ = ProxyConfig();
1030 current_state_ = STATE_NONE; 1254 current_state_ = STATE_NONE;
1031 1255
1032 return previous_state; 1256 return previous_state;
1033 } 1257 }
1034 1258
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 static_cast<MessageLoopForIO*>(file_loop)); 1316 static_cast<MessageLoopForIO*>(file_loop));
1093 1317
1094 return linux_config_service; 1318 return linux_config_service;
1095 #else 1319 #else
1096 LOG(WARNING) << "Failed to choose a system proxy settings fetcher " 1320 LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
1097 "for this platform."; 1321 "for this platform.";
1098 return new ProxyConfigServiceDirect(); 1322 return new ProxyConfigServiceDirect();
1099 #endif 1323 #endif
1100 } 1324 }
1101 1325
1326 // static
1327 ProxyService::PollPolicy ProxyService::set_pac_script_poll_policy(
1328 PollPolicy policy) {
1329 return ProxyScriptDeciderPoller::set_policy(policy);
1330 }
1331
1102 void ProxyService::OnProxyConfigChanged( 1332 void ProxyService::OnProxyConfigChanged(
1103 const ProxyConfig& config, 1333 const ProxyConfig& config,
1104 ProxyConfigService::ConfigAvailability availability) { 1334 ProxyConfigService::ConfigAvailability availability) {
1105 // Retrieve the current proxy configuration from the ProxyConfigService. 1335 // Retrieve the current proxy configuration from the ProxyConfigService.
1106 // If a configuration is not available yet, we will get called back later 1336 // If a configuration is not available yet, we will get called back later
1107 // by our ProxyConfigService::Observer once it changes. 1337 // by our ProxyConfigService::Observer once it changes.
1108 ProxyConfig effective_config; 1338 ProxyConfig effective_config;
1109 switch (availability) { 1339 switch (availability) {
1110 case ProxyConfigService::CONFIG_PENDING: 1340 case ProxyConfigService::CONFIG_PENDING:
1111 // ProxyConfigService implementors should never pass CONFIG_PENDING. 1341 // ProxyConfigService implementors should never pass CONFIG_PENDING.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1377
1148 if (!fetched_config_.HasAutomaticSettings()) { 1378 if (!fetched_config_.HasAutomaticSettings()) {
1149 config_ = fetched_config_; 1379 config_ = fetched_config_;
1150 SetReady(); 1380 SetReady();
1151 return; 1381 return;
1152 } 1382 }
1153 1383
1154 // Start downloading + testing the PAC scripts for this new configuration. 1384 // Start downloading + testing the PAC scripts for this new configuration.
1155 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER; 1385 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1156 1386
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. 1387 // If we changed networks recently, we should delay running proxy auto-config.
1164 base::TimeDelta wait_delay = 1388 base::TimeDelta wait_delay =
1165 stall_proxy_autoconfig_until_ - base::TimeTicks::Now(); 1389 stall_proxy_autoconfig_until_ - base::TimeTicks::Now();
1166 1390
1167 int rv = init_proxy_resolver_->Init( 1391 init_proxy_resolver_.reset(new InitProxyResolver());
1168 fetched_config_, wait_delay, &config_, 1392 int rv = init_proxy_resolver_->Start(
1393 resolver_.get(),
1394 proxy_script_fetcher_.get(),
1395 dhcp_proxy_script_fetcher_.get(),
1396 net_log_,
1397 fetched_config_,
1398 wait_delay,
1169 base::Bind(&ProxyService::OnInitProxyResolverComplete, 1399 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1170 base::Unretained(this))); 1400 base::Unretained(this)));
1171 1401
1402 if (rv != ERR_IO_PENDING)
1403 OnInitProxyResolverComplete(rv);
1404 }
1405
1406 void ProxyService::InitializeUsingDecidedConfig(
1407 int decider_result,
1408 ProxyResolverScriptData* script_data,
1409 const ProxyConfig& effective_config) {
1410 DCHECK(fetched_config_.is_valid());
1411 DCHECK(fetched_config_.HasAutomaticSettings());
1412
1413 ResetProxyConfig(false);
1414
1415 current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
1416
1417 init_proxy_resolver_.reset(new InitProxyResolver());
1418 int rv = init_proxy_resolver_->StartSkipDecider(
1419 resolver_.get(),
1420 effective_config,
1421 decider_result,
1422 script_data,
1423 base::Bind(&ProxyService::OnInitProxyResolverComplete,
1424 base::Unretained(this)));
1425
1172 if (rv != ERR_IO_PENDING) 1426 if (rv != ERR_IO_PENDING)
1173 OnInitProxyResolverComplete(rv); 1427 OnInitProxyResolverComplete(rv);
1174 } 1428 }
1175 1429
1176 void ProxyService::OnIPAddressChanged() { 1430 void ProxyService::OnIPAddressChanged() {
1177 // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info. 1431 // See the comment block by |kNumMillisToStallAfterNetworkChanges| for info.
1178 stall_proxy_autoconfig_until_ = 1432 stall_proxy_autoconfig_until_ =
1179 base::TimeTicks::Now() + stall_proxy_auto_config_delay_; 1433 base::TimeTicks::Now() + stall_proxy_auto_config_delay_;
1180 1434
1181 State previous_state = ResetProxyConfig(false); 1435 State previous_state = ResetProxyConfig(false);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 OnCompletion(result_); 1502 OnCompletion(result_);
1249 } 1503 }
1250 } 1504 }
1251 1505
1252 void SyncProxyServiceHelper::OnCompletion(int rv) { 1506 void SyncProxyServiceHelper::OnCompletion(int rv) {
1253 result_ = rv; 1507 result_ = rv;
1254 event_.Signal(); 1508 event_.Signal();
1255 } 1509 }
1256 1510
1257 } // namespace net 1511 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698