OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/dns/host_resolver_impl.h" | 5 #include "net/dns/host_resolver_impl.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <Winsock2.h> | 8 #include <Winsock2.h> |
9 #elif defined(OS_POSIX) | 9 #elif defined(OS_POSIX) |
10 #include <netdb.h> | 10 #include <netdb.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include <cmath> | 13 #include <cmath> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/basictypes.h" | 17 #include "base/basictypes.h" |
18 #include "base/bind.h" | 18 #include "base/bind.h" |
19 #include "base/bind_helpers.h" | 19 #include "base/bind_helpers.h" |
20 #include "base/callback.h" | 20 #include "base/callback.h" |
21 #include "base/compiler_specific.h" | 21 #include "base/compiler_specific.h" |
22 #include "base/debug/debugger.h" | 22 #include "base/debug/debugger.h" |
23 #include "base/debug/stack_trace.h" | 23 #include "base/debug/stack_trace.h" |
24 #include "base/message_loop/message_loop_proxy.h" | |
25 #include "base/metrics/field_trial.h" | 24 #include "base/metrics/field_trial.h" |
26 #include "base/metrics/histogram.h" | 25 #include "base/metrics/histogram.h" |
27 #include "base/profiler/scoped_tracker.h" | 26 #include "base/profiler/scoped_tracker.h" |
27 #include "base/single_thread_task_runner.h" | |
28 #include "base/stl_util.h" | 28 #include "base/stl_util.h" |
29 #include "base/strings/string_util.h" | 29 #include "base/strings/string_util.h" |
30 #include "base/strings/utf_string_conversions.h" | 30 #include "base/strings/utf_string_conversions.h" |
31 #include "base/thread_task_runner_handle.h" | |
31 #include "base/threading/worker_pool.h" | 32 #include "base/threading/worker_pool.h" |
32 #include "base/time/time.h" | 33 #include "base/time/time.h" |
33 #include "base/values.h" | 34 #include "base/values.h" |
34 #include "net/base/address_family.h" | 35 #include "net/base/address_family.h" |
35 #include "net/base/address_list.h" | 36 #include "net/base/address_list.h" |
36 #include "net/base/dns_reloader.h" | 37 #include "net/base/dns_reloader.h" |
37 #include "net/base/dns_util.h" | 38 #include "net/base/dns_util.h" |
38 #include "net/base/host_port_pair.h" | 39 #include "net/base/host_port_pair.h" |
39 #include "net/base/ip_endpoint.h" | 40 #include "net/base/ip_endpoint.h" |
40 #include "net/base/net_errors.h" | 41 #include "net/base/net_errors.h" |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 typedef base::Callback<void(int net_error, | 567 typedef base::Callback<void(int net_error, |
567 const AddressList& addr_list)> Callback; | 568 const AddressList& addr_list)> Callback; |
568 | 569 |
569 ProcTask(const Key& key, | 570 ProcTask(const Key& key, |
570 const ProcTaskParams& params, | 571 const ProcTaskParams& params, |
571 const Callback& callback, | 572 const Callback& callback, |
572 const BoundNetLog& job_net_log) | 573 const BoundNetLog& job_net_log) |
573 : key_(key), | 574 : key_(key), |
574 params_(params), | 575 params_(params), |
575 callback_(callback), | 576 callback_(callback), |
576 origin_loop_(base::MessageLoopProxy::current()), | 577 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
577 attempt_number_(0), | 578 attempt_number_(0), |
578 completed_attempt_number_(0), | 579 completed_attempt_number_(0), |
579 completed_attempt_error_(ERR_UNEXPECTED), | 580 completed_attempt_error_(ERR_UNEXPECTED), |
580 had_non_speculative_request_(false), | 581 had_non_speculative_request_(false), |
581 net_log_(job_net_log) { | 582 net_log_(job_net_log) { |
582 if (!params_.resolver_proc.get()) | 583 if (!params_.resolver_proc.get()) |
583 params_.resolver_proc = HostResolverProc::GetDefault(); | 584 params_.resolver_proc = HostResolverProc::GetDefault(); |
584 // If default is unset, use the system proc. | 585 // If default is unset, use the system proc. |
585 if (!params_.resolver_proc.get()) | 586 if (!params_.resolver_proc.get()) |
586 params_.resolver_proc = new SystemHostResolverProc(); | 587 params_.resolver_proc = new SystemHostResolverProc(); |
587 } | 588 } |
588 | 589 |
589 void Start() { | 590 void Start() { |
590 DCHECK(origin_loop_->BelongsToCurrentThread()); | 591 DCHECK(task_runner_->BelongsToCurrentThread()); |
591 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); | 592 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); |
592 StartLookupAttempt(); | 593 StartLookupAttempt(); |
593 } | 594 } |
594 | 595 |
595 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve | 596 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve |
596 // attempts running on worker threads will continue running. Only once all the | 597 // attempts running on worker threads will continue running. Only once all the |
597 // attempts complete will the final reference to this ProcTask be released. | 598 // attempts complete will the final reference to this ProcTask be released. |
598 void Cancel() { | 599 void Cancel() { |
599 DCHECK(origin_loop_->BelongsToCurrentThread()); | 600 DCHECK(task_runner_->BelongsToCurrentThread()); |
600 | 601 |
601 if (was_canceled() || was_completed()) | 602 if (was_canceled() || was_completed()) |
602 return; | 603 return; |
603 | 604 |
604 callback_.Reset(); | 605 callback_.Reset(); |
605 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); | 606 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); |
606 } | 607 } |
607 | 608 |
608 void set_had_non_speculative_request() { | 609 void set_had_non_speculative_request() { |
609 DCHECK(origin_loop_->BelongsToCurrentThread()); | 610 DCHECK(task_runner_->BelongsToCurrentThread()); |
610 had_non_speculative_request_ = true; | 611 had_non_speculative_request_ = true; |
611 } | 612 } |
612 | 613 |
613 bool was_canceled() const { | 614 bool was_canceled() const { |
614 DCHECK(origin_loop_->BelongsToCurrentThread()); | 615 DCHECK(task_runner_->BelongsToCurrentThread()); |
615 return callback_.is_null(); | 616 return callback_.is_null(); |
616 } | 617 } |
617 | 618 |
618 bool was_completed() const { | 619 bool was_completed() const { |
619 DCHECK(origin_loop_->BelongsToCurrentThread()); | 620 DCHECK(task_runner_->BelongsToCurrentThread()); |
620 return completed_attempt_number_ > 0; | 621 return completed_attempt_number_ > 0; |
621 } | 622 } |
622 | 623 |
623 private: | 624 private: |
624 friend class base::RefCountedThreadSafe<ProcTask>; | 625 friend class base::RefCountedThreadSafe<ProcTask>; |
625 ~ProcTask() {} | 626 ~ProcTask() {} |
626 | 627 |
627 void StartLookupAttempt() { | 628 void StartLookupAttempt() { |
628 DCHECK(origin_loop_->BelongsToCurrentThread()); | 629 DCHECK(task_runner_->BelongsToCurrentThread()); |
629 base::TimeTicks start_time = base::TimeTicks::Now(); | 630 base::TimeTicks start_time = base::TimeTicks::Now(); |
630 ++attempt_number_; | 631 ++attempt_number_; |
631 // Dispatch the lookup attempt to a worker thread. | 632 // Dispatch the lookup attempt to a worker thread. |
632 if (!base::WorkerPool::PostTask( | 633 if (!base::WorkerPool::PostTask( |
633 FROM_HERE, | 634 FROM_HERE, |
634 base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), | 635 base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), |
635 true)) { | 636 true)) { |
636 NOTREACHED(); | 637 NOTREACHED(); |
637 | 638 |
638 // Since we could be running within Resolve() right now, we can't just | 639 // Since we could be running within Resolve() right now, we can't just |
639 // call OnLookupComplete(). Instead we must wait until Resolve() has | 640 // call OnLookupComplete(). Instead we must wait until Resolve() has |
640 // returned (IO_PENDING). | 641 // returned (IO_PENDING). |
641 origin_loop_->PostTask( | 642 task_runner_->PostTask(FROM_HERE, |
642 FROM_HERE, | 643 base::Bind(&ProcTask::OnLookupComplete, |
643 base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), | 644 this, |
644 start_time, attempt_number_, ERR_UNEXPECTED, 0)); | 645 AddressList(), |
646 start_time, | |
647 attempt_number_, | |
648 ERR_UNEXPECTED, | |
649 0)); | |
645 return; | 650 return; |
646 } | 651 } |
647 | 652 |
648 net_log_.AddEvent( | 653 net_log_.AddEvent( |
649 NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, | 654 NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, |
650 NetLog::IntegerCallback("attempt_number", attempt_number_)); | 655 NetLog::IntegerCallback("attempt_number", attempt_number_)); |
651 | 656 |
652 // If we don't get the results within a given time, RetryIfNotComplete | 657 // If we don't get the results within a given time, RetryIfNotComplete |
653 // will start a new attempt on a different worker thread if none of our | 658 // will start a new attempt on a different worker thread if none of our |
654 // outstanding attempts have completed yet. | 659 // outstanding attempts have completed yet. |
655 if (attempt_number_ <= params_.max_retry_attempts) { | 660 if (attempt_number_ <= params_.max_retry_attempts) { |
656 origin_loop_->PostDelayedTask( | 661 task_runner_->PostDelayedTask( |
657 FROM_HERE, | 662 FROM_HERE, |
658 base::Bind(&ProcTask::RetryIfNotComplete, this), | 663 base::Bind(&ProcTask::RetryIfNotComplete, this), |
659 params_.unresponsive_delay); | 664 params_.unresponsive_delay); |
660 } | 665 } |
661 } | 666 } |
662 | 667 |
663 // WARNING: This code runs inside a worker pool. The shutdown code cannot | 668 // WARNING: This code runs inside a worker pool. The shutdown code cannot |
664 // wait for it to finish, so we must be very careful here about using other | 669 // wait for it to finish, so we must be very careful here about using other |
665 // objects (like MessageLoops, Singletons, etc). During shutdown these objects | 670 // objects (like MessageLoops, Singletons, etc). During shutdown these objects |
666 // may no longer exist. Multiple DoLookups() could be running in parallel, so | 671 // may no longer exist. Multiple DoLookups() could be running in parallel, so |
(...skipping 13 matching lines...) Expand all Loading... | |
680 // block of kIcanNameCollisionIp for details on why. | 685 // block of kIcanNameCollisionIp for details on why. |
681 for (const auto& it : results) { | 686 for (const auto& it : results) { |
682 const IPAddressNumber& cur = it.address(); | 687 const IPAddressNumber& cur = it.address(); |
683 if (cur.size() == arraysize(kIcanNameCollisionIp) && | 688 if (cur.size() == arraysize(kIcanNameCollisionIp) && |
684 0 == memcmp(&cur.front(), kIcanNameCollisionIp, cur.size())) { | 689 0 == memcmp(&cur.front(), kIcanNameCollisionIp, cur.size())) { |
685 error = ERR_ICANN_NAME_COLLISION; | 690 error = ERR_ICANN_NAME_COLLISION; |
686 break; | 691 break; |
687 } | 692 } |
688 } | 693 } |
689 | 694 |
690 origin_loop_->PostTask( | 695 task_runner_->PostTask(FROM_HERE, |
691 FROM_HERE, | 696 base::Bind(&ProcTask::OnLookupComplete, |
692 base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, | 697 this, |
693 attempt_number, error, os_error)); | 698 results, |
699 start_time, | |
700 attempt_number, | |
701 error, | |
702 os_error)); | |
694 } | 703 } |
695 | 704 |
696 // Makes next attempt if DoLookup() has not finished (runs on origin thread). | 705 // Makes next attempt if DoLookup() has not finished (runs on task runner |
706 // thread). | |
697 void RetryIfNotComplete() { | 707 void RetryIfNotComplete() { |
698 DCHECK(origin_loop_->BelongsToCurrentThread()); | 708 DCHECK(task_runner_->BelongsToCurrentThread()); |
699 | 709 |
700 if (was_completed() || was_canceled()) | 710 if (was_completed() || was_canceled()) |
701 return; | 711 return; |
702 | 712 |
703 params_.unresponsive_delay *= params_.retry_factor; | 713 params_.unresponsive_delay *= params_.retry_factor; |
704 StartLookupAttempt(); | 714 StartLookupAttempt(); |
705 } | 715 } |
706 | 716 |
707 // Callback for when DoLookup() completes (runs on origin thread). | 717 // Callback for when DoLookup() completes (runs on task runner thread). |
708 void OnLookupComplete(const AddressList& results, | 718 void OnLookupComplete(const AddressList& results, |
709 const base::TimeTicks& start_time, | 719 const base::TimeTicks& start_time, |
710 const uint32 attempt_number, | 720 const uint32 attempt_number, |
711 int error, | 721 int error, |
712 const int os_error) { | 722 const int os_error) { |
713 DCHECK(origin_loop_->BelongsToCurrentThread()); | 723 DCHECK(task_runner_->BelongsToCurrentThread()); |
714 // If results are empty, we should return an error. | 724 // If results are empty, we should return an error. |
715 bool empty_list_on_ok = (error == OK && results.empty()); | 725 bool empty_list_on_ok = (error == OK && results.empty()); |
716 UMA_HISTOGRAM_BOOLEAN("DNS.EmptyAddressListAndNoError", empty_list_on_ok); | 726 UMA_HISTOGRAM_BOOLEAN("DNS.EmptyAddressListAndNoError", empty_list_on_ok); |
717 if (empty_list_on_ok) | 727 if (empty_list_on_ok) |
718 error = ERR_NAME_NOT_RESOLVED; | 728 error = ERR_NAME_NOT_RESOLVED; |
719 | 729 |
720 bool was_retry_attempt = attempt_number > 1; | 730 bool was_retry_attempt = attempt_number > 1; |
721 | 731 |
722 // Ideally the following code would be part of host_resolver_proc.cc, | 732 // Ideally the following code would be part of host_resolver_proc.cc, |
723 // however it isn't safe to call NetworkChangeNotifier from worker threads. | 733 // however it isn't safe to call NetworkChangeNotifier from worker threads. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
770 } | 780 } |
771 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, | 781 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, |
772 net_log_callback); | 782 net_log_callback); |
773 | 783 |
774 callback_.Run(error, results_); | 784 callback_.Run(error, results_); |
775 } | 785 } |
776 | 786 |
777 void RecordPerformanceHistograms(const base::TimeTicks& start_time, | 787 void RecordPerformanceHistograms(const base::TimeTicks& start_time, |
778 const int error, | 788 const int error, |
779 const int os_error) const { | 789 const int os_error) const { |
780 DCHECK(origin_loop_->BelongsToCurrentThread()); | 790 DCHECK(task_runner_->BelongsToCurrentThread()); |
781 enum Category { // Used in UMA_HISTOGRAM_ENUMERATION. | 791 enum Category { // Used in UMA_HISTOGRAM_ENUMERATION. |
782 RESOLVE_SUCCESS, | 792 RESOLVE_SUCCESS, |
783 RESOLVE_FAIL, | 793 RESOLVE_FAIL, |
784 RESOLVE_SPECULATIVE_SUCCESS, | 794 RESOLVE_SPECULATIVE_SUCCESS, |
785 RESOLVE_SPECULATIVE_FAIL, | 795 RESOLVE_SPECULATIVE_FAIL, |
786 RESOLVE_MAX, // Bounding value. | 796 RESOLVE_MAX, // Bounding value. |
787 }; | 797 }; |
788 int category = RESOLVE_MAX; // Illegal value for later DCHECK only. | 798 int category = RESOLVE_MAX; // Illegal value for later DCHECK only. |
789 | 799 |
790 base::TimeDelta duration = base::TimeTicks::Now() - start_time; | 800 base::TimeDelta duration = base::TimeTicks::Now() - start_time; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 } | 847 } |
838 DCHECK_LT(category, static_cast<int>(RESOLVE_MAX)); // Be sure it was set. | 848 DCHECK_LT(category, static_cast<int>(RESOLVE_MAX)); // Be sure it was set. |
839 | 849 |
840 UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX); | 850 UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX); |
841 } | 851 } |
842 | 852 |
843 void RecordAttemptHistograms(const base::TimeTicks& start_time, | 853 void RecordAttemptHistograms(const base::TimeTicks& start_time, |
844 const uint32 attempt_number, | 854 const uint32 attempt_number, |
845 const int error, | 855 const int error, |
846 const int os_error) const { | 856 const int os_error) const { |
847 DCHECK(origin_loop_->BelongsToCurrentThread()); | 857 DCHECK(task_runner_->BelongsToCurrentThread()); |
848 bool first_attempt_to_complete = | 858 bool first_attempt_to_complete = |
849 completed_attempt_number_ == attempt_number; | 859 completed_attempt_number_ == attempt_number; |
850 bool is_first_attempt = (attempt_number == 1); | 860 bool is_first_attempt = (attempt_number == 1); |
851 | 861 |
852 if (first_attempt_to_complete) { | 862 if (first_attempt_to_complete) { |
853 // If this was first attempt to complete, then record the resolution | 863 // If this was first attempt to complete, then record the resolution |
854 // status of the attempt. | 864 // status of the attempt. |
855 if (completed_attempt_error_ == OK) { | 865 if (completed_attempt_error_ == OK) { |
856 UMA_HISTOGRAM_ENUMERATION( | 866 UMA_HISTOGRAM_ENUMERATION( |
857 "DNS.AttemptFirstSuccess", attempt_number, 100); | 867 "DNS.AttemptFirstSuccess", attempt_number, 100); |
(...skipping 26 matching lines...) Expand all Loading... | |
884 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); | 894 UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); |
885 } | 895 } |
886 | 896 |
887 base::TimeDelta duration = base::TimeTicks::Now() - start_time; | 897 base::TimeDelta duration = base::TimeTicks::Now() - start_time; |
888 if (error == OK) | 898 if (error == OK) |
889 DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); | 899 DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); |
890 else | 900 else |
891 DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); | 901 DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); |
892 } | 902 } |
893 | 903 |
894 // Set on the origin thread, read on the worker thread. | 904 // Set on the task runner thread, read on the worker thread. |
895 Key key_; | 905 Key key_; |
896 | 906 |
897 // Holds an owning reference to the HostResolverProc that we are going to use. | 907 // Holds an owning reference to the HostResolverProc that we are going to use. |
898 // This may not be the current resolver procedure by the time we call | 908 // This may not be the current resolver procedure by the time we call |
899 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning | 909 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning |
900 // reference ensures that it remains valid until we are done. | 910 // reference ensures that it remains valid until we are done. |
901 ProcTaskParams params_; | 911 ProcTaskParams params_; |
902 | 912 |
903 // The listener to the results of this ProcTask. | 913 // The listener to the results of this ProcTask. |
904 Callback callback_; | 914 Callback callback_; |
905 | 915 |
906 // Used to post ourselves onto the origin thread. | 916 // Used to post ourselves onto the task runner thread. |
asanka
2015/05/14 18:38:40
.. on to the originating thread.
anujsharma
2015/05/20 13:13:16
Done.
| |
907 scoped_refptr<base::MessageLoopProxy> origin_loop_; | 917 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
908 | 918 |
909 // Keeps track of the number of attempts we have made so far to resolve the | 919 // Keeps track of the number of attempts we have made so far to resolve the |
910 // host. Whenever we start an attempt to resolve the host, we increase this | 920 // host. Whenever we start an attempt to resolve the host, we increase this |
911 // number. | 921 // number. |
912 uint32 attempt_number_; | 922 uint32 attempt_number_; |
913 | 923 |
914 // The index of the attempt which finished first (or 0 if the job is still in | 924 // The index of the attempt which finished first (or 0 if the job is still in |
915 // progress). | 925 // progress). |
916 uint32 completed_attempt_number_; | 926 uint32 completed_attempt_number_; |
917 | 927 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
959 void DoProbe() { | 969 void DoProbe() { |
960 result_ = HaveOnlyLoopbackAddresses(); | 970 result_ = HaveOnlyLoopbackAddresses(); |
961 } | 971 } |
962 | 972 |
963 void OnProbeComplete() { | 973 void OnProbeComplete() { |
964 if (!resolver_.get()) | 974 if (!resolver_.get()) |
965 return; | 975 return; |
966 resolver_->SetHaveOnlyLoopbackAddresses(result_); | 976 resolver_->SetHaveOnlyLoopbackAddresses(result_); |
967 } | 977 } |
968 | 978 |
969 // Used/set only on origin thread. | 979 // Used/set only on task runner thread. |
970 base::WeakPtr<HostResolverImpl> resolver_; | 980 base::WeakPtr<HostResolverImpl> resolver_; |
971 | 981 |
972 bool result_; | 982 bool result_; |
973 | 983 |
974 DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); | 984 DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); |
975 }; | 985 }; |
976 | 986 |
977 //----------------------------------------------------------------------------- | 987 //----------------------------------------------------------------------------- |
978 | 988 |
979 // Resolves the hostname using DnsTransaction. | 989 // Resolves the hostname using DnsTransaction. |
(...skipping 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2392 dns_client_->SetConfig(dns_config); | 2402 dns_client_->SetConfig(dns_config); |
2393 num_dns_failures_ = 0; | 2403 num_dns_failures_ = 0; |
2394 if (dns_client_->GetConfig()) | 2404 if (dns_client_->GetConfig()) |
2395 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); | 2405 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); |
2396 } | 2406 } |
2397 | 2407 |
2398 AbortDnsTasks(); | 2408 AbortDnsTasks(); |
2399 } | 2409 } |
2400 | 2410 |
2401 } // namespace net | 2411 } // namespace net |
OLD | NEW |