| Index: net/base/host_resolver_impl.cc
|
| ===================================================================
|
| --- net/base/host_resolver_impl.cc (revision 41742)
|
| +++ net/base/host_resolver_impl.cc (working copy)
|
| @@ -21,6 +21,7 @@
|
| #include "net/base/host_resolver_proc.h"
|
| #include "net/base/net_log.h"
|
| #include "net/base/net_errors.h"
|
| +#include "net/base/net_util.h"
|
| #include "net/base/network_change_notifier.h"
|
|
|
| #if defined(OS_WIN)
|
| @@ -192,7 +193,8 @@
|
| public:
|
| Job(int id, HostResolverImpl* resolver, const Key& key,
|
| RequestsTrace* requests_trace)
|
| - : id_(id), key_(key),
|
| + : id_(id),
|
| + key_(key),
|
| resolver_(resolver),
|
| origin_loop_(MessageLoop::current()),
|
| resolver_proc_(resolver->effective_resolver_proc()),
|
| @@ -421,6 +423,91 @@
|
|
|
| //-----------------------------------------------------------------------------
|
|
|
| +// This class represents a request to the worker pool for a "probe for IPv6
|
| +// support" call.
|
| +class HostResolverImpl::IPv6ProbeJob
|
| + : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> {
|
| + public:
|
| + explicit IPv6ProbeJob(HostResolverImpl* resolver)
|
| + : resolver_(resolver),
|
| + origin_loop_(MessageLoop::current()) {
|
| + }
|
| +
|
| + void Start() {
|
| + DCHECK(IsOnOriginThread());
|
| + const bool IS_SLOW = true;
|
| + WorkerPool::PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &IPv6ProbeJob::DoProbe), IS_SLOW);
|
| + }
|
| +
|
| + // Cancels the current job.
|
| + void Cancel() {
|
| + DCHECK(IsOnOriginThread());
|
| + resolver_ = NULL; // Read/write ONLY on origin thread.
|
| + {
|
| + AutoLock locked(origin_loop_lock_);
|
| + // Origin loop may be destroyed before we can use it!
|
| + origin_loop_ = NULL;
|
| + }
|
| + }
|
| +
|
| + bool was_cancelled() const {
|
| + DCHECK(IsOnOriginThread());
|
| + return resolver_ == NULL;
|
| + }
|
| +
|
| + private:
|
| + friend class base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob>;
|
| +
|
| + ~IPv6ProbeJob() {
|
| + }
|
| +
|
| + // Run on worker thread.
|
| + void DoProbe() {
|
| + // Do actual testing on this thread, as it takes 40-100ms.
|
| + AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED
|
| + : ADDRESS_FAMILY_IPV4;
|
| +
|
| + Task* reply = NewRunnableMethod(this, &IPv6ProbeJob::OnProbeComplete,
|
| + family);
|
| +
|
| + // The origin loop could go away while we are trying to post to it, so we
|
| + // need to call its PostTask method inside a lock. See ~HostResolver.
|
| + {
|
| + AutoLock locked(origin_loop_lock_);
|
| + if (origin_loop_) {
|
| + origin_loop_->PostTask(FROM_HERE, reply);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // We didn't post, so delete the reply.
|
| + delete reply;
|
| + }
|
| +
|
| + // Callback for when DoProbe() completes (runs on origin thread).
|
| + void OnProbeComplete(AddressFamily address_family) {
|
| + DCHECK(IsOnOriginThread());
|
| + if (!was_cancelled())
|
| + resolver_->IPv6ProbeSetDefaultAddressFamily(address_family);
|
| + }
|
| +
|
| + bool IsOnOriginThread() const {
|
| + return !MessageLoop::current() || origin_loop_ == MessageLoop::current();
|
| + }
|
| +
|
| + // Used/set only on origin thread.
|
| + HostResolverImpl* resolver_;
|
| +
|
| + // Used to post ourselves onto the origin thread.
|
| + Lock origin_loop_lock_;
|
| + MessageLoop* origin_loop_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob);
|
| +};
|
| +
|
| +//-----------------------------------------------------------------------------
|
| +
|
| // We rely on the priority enum values being sequential having starting at 0,
|
| // and increasing for lower priorities.
|
| COMPILE_ASSERT(HIGHEST == 0u &&
|
| @@ -581,7 +668,8 @@
|
| resolver_proc_(resolver_proc),
|
| default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
|
| shutdown_(false),
|
| - network_change_notifier_(network_change_notifier) {
|
| + network_change_notifier_(network_change_notifier),
|
| + ipv6_probe_monitoring_(false) {
|
| DCHECK_GT(max_jobs, 0u);
|
|
|
| // It is cumbersome to expose all of the constraints in the constructor,
|
| @@ -598,6 +686,8 @@
|
| HostResolverImpl::~HostResolverImpl() {
|
| // Cancel the outstanding jobs. Those jobs may contain several attached
|
| // requests, which will also be cancelled.
|
| + DiscardIPv6ProbeJob();
|
| +
|
| for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
|
| it->second->Cancel();
|
|
|
| @@ -742,6 +832,18 @@
|
| observers_.erase(it);
|
| }
|
|
|
| +void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) {
|
| + ipv6_probe_monitoring_ = false;
|
| + DiscardIPv6ProbeJob();
|
| + default_address_family_ = address_family;
|
| +}
|
| +
|
| +void HostResolverImpl::ProbeIPv6Support() {
|
| + DCHECK(!ipv6_probe_monitoring_);
|
| + ipv6_probe_monitoring_ = true;
|
| + OnIPAddressChanged(); // Give initial setup call.
|
| +}
|
| +
|
| void HostResolverImpl::Shutdown() {
|
| shutdown_ = true;
|
|
|
| @@ -975,8 +1077,34 @@
|
| void HostResolverImpl::OnIPAddressChanged() {
|
| if (cache_.get())
|
| cache_->clear();
|
| + if (ipv6_probe_monitoring_) {
|
| + DiscardIPv6ProbeJob();
|
| + ipv6_probe_job_ = new IPv6ProbeJob(this);
|
| + ipv6_probe_job_->Start();
|
| + }
|
| }
|
|
|
| +void HostResolverImpl::DiscardIPv6ProbeJob() {
|
| + if (ipv6_probe_job_.get()) {
|
| + ipv6_probe_job_->Cancel();
|
| + ipv6_probe_job_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily(
|
| + AddressFamily address_family) {
|
| + DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED ||
|
| + address_family == ADDRESS_FAMILY_IPV4);
|
| + if (default_address_family_ != address_family)
|
| + LOG(INFO) << "IPv6Probe forced AddressFamily setting to "
|
| + << ((address_family == ADDRESS_FAMILY_UNSPECIFIED)
|
| + ? "ADDRESS_FAMILY_UNSPECIFIED"
|
| + : "ADDRESS_FAMILY_IPV4");
|
| + default_address_family_ = address_family;
|
| + // Drop reference since the job has called us back.
|
| + DiscardIPv6ProbeJob();
|
| +}
|
| +
|
| // static
|
| HostResolverImpl::JobPoolIndex HostResolverImpl::GetJobPoolIndexForRequest(
|
| const Request* req) {
|
|
|