Set up HostResolverImpl to flush cache on IP address change.
BUG=http://crbug.com/26159
Review URL: http://codereview.chromium.org/545003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35956 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
index 36975f8..5644223 100644
--- a/net/base/host_resolver_impl.cc
+++ b/net/base/host_resolver_impl.cc
@@ -15,6 +15,7 @@
#include "net/base/host_resolver_proc.h"
#include "net/base/load_log.h"
#include "net/base/net_errors.h"
+#include "net/base/network_change_notifier.h"
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
@@ -22,7 +23,9 @@
namespace net {
-HostResolver* CreateSystemHostResolver() {
+namespace {
+
+HostCache* CreateDefaultCache() {
static const size_t kMaxHostCacheEntries = 100;
HostCache* cache = new HostCache(
@@ -30,7 +33,14 @@
base::TimeDelta::FromMinutes(1),
base::TimeDelta::FromSeconds(1));
- return new HostResolverImpl(NULL, cache);
+ return cache;
+}
+
+} // anonymous namespace
+
+HostResolver* CreateSystemHostResolver() {
+ // TODO(willchan): Pass in the NetworkChangeNotifier.
+ return new HostResolverImpl(NULL, CreateDefaultCache(), NULL);
}
static int ResolveAddrInfo(HostResolverProc* resolver_proc,
@@ -279,16 +289,21 @@
//-----------------------------------------------------------------------------
-HostResolverImpl::HostResolverImpl(HostResolverProc* resolver_proc,
- HostCache* cache)
+HostResolverImpl::HostResolverImpl(
+ HostResolverProc* resolver_proc,
+ HostCache* cache,
+ const scoped_refptr<NetworkChangeNotifier>& network_change_notifier)
: cache_(cache),
next_request_id_(0),
resolver_proc_(resolver_proc),
default_address_family_(ADDRESS_FAMILY_UNSPECIFIED),
- shutdown_(false) {
+ shutdown_(false),
+ network_change_notifier_(network_change_notifier) {
#if defined(OS_WIN)
EnsureWinsockInit();
#endif
+ if (network_change_notifier_)
+ network_change_notifier_->AddObserver(this);
}
HostResolverImpl::~HostResolverImpl() {
@@ -300,6 +315,9 @@
// In case we are being deleted during the processing of a callback.
if (cur_completing_job_)
cur_completing_job_->Cancel();
+
+ if (network_change_notifier_)
+ network_change_notifier_->RemoveObserver(this);
}
// TODO(eroman): Don't create cache entries for hostnames which are simply IP
@@ -408,11 +426,11 @@
OnCancelRequest(req->load_log(), req->id(), req->info());
}
-void HostResolverImpl::AddObserver(Observer* observer) {
+void HostResolverImpl::AddObserver(HostResolver::Observer* observer) {
observers_.push_back(observer);
}
-void HostResolverImpl::RemoveObserver(Observer* observer) {
+void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) {
ObserversList::iterator it =
std::find(observers_.begin(), observers_.end(), observer);
@@ -555,4 +573,9 @@
LoadLog::EndEvent(load_log, LoadLog::TYPE_HOST_RESOLVER_IMPL);
}
+void HostResolverImpl::OnIPAddressChanged() {
+ if (cache_.get())
+ cache_->clear();
+}
+
} // namespace net
diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h
index 84acdc2..6cabcf96 100644
--- a/net/base/host_resolver_impl.h
+++ b/net/base/host_resolver_impl.h
@@ -12,6 +12,7 @@
#include "net/base/host_cache.h"
#include "net/base/host_resolver.h"
#include "net/base/host_resolver_proc.h"
+#include "net/base/network_change_notifier.h"
namespace net {
@@ -40,7 +41,8 @@
// Thread safety: This class is not threadsafe, and must only be called
// from one thread!
//
-class HostResolverImpl : public HostResolver {
+class HostResolverImpl : public HostResolver,
+ public NetworkChangeNotifier::Observer {
public:
// Creates a HostResolver that first uses the local cache |cache|, and then
// falls back to |resolver_proc|.
@@ -52,7 +54,9 @@
// thread-safe since it is run from multiple worker threads. If
// |resolver_proc| is NULL then the default host resolver procedure is
// used (which is SystemHostResolverProc except if overridden).
- HostResolverImpl(HostResolverProc* resolver_proc, HostCache* cache);
+ HostResolverImpl(HostResolverProc* resolver_proc,
+ HostCache* cache,
+ const scoped_refptr<NetworkChangeNotifier>& notifier);
// HostResolver methods:
virtual int Resolve(const RequestInfo& info,
@@ -61,8 +65,8 @@
RequestHandle* out_req,
LoadLog* load_log);
virtual void CancelRequest(RequestHandle req);
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
+ virtual void AddObserver(HostResolver::Observer* observer);
+ virtual void RemoveObserver(HostResolver::Observer* observer);
virtual HostCache* GetHostCache();
// TODO(eroman): temp hack for http://crbug.com/15513
@@ -78,7 +82,7 @@
typedef std::vector<Request*> RequestsList;
typedef HostCache::Key Key;
typedef std::map<Key, scoped_refptr<Job> > JobMap;
- typedef std::vector<Observer*> ObserversList;
+ typedef std::vector<HostResolver::Observer*> ObserversList;
// If any completion callbacks are pending when the resolver is destroyed,
// the host resolutions are cancelled, and the completion callbacks will not
@@ -119,6 +123,9 @@
int request_id,
const RequestInfo& info);
+ // NetworkChangeNotifier::Observer methods:
+ virtual void OnIPAddressChanged();
+
// Cache of host resolution results.
scoped_ptr<HostCache> cache_;
@@ -146,6 +153,8 @@
// TODO(eroman): temp hack for http://crbug.com/15513
bool shutdown_;
+ const scoped_refptr<NetworkChangeNotifier> network_change_notifier_;
+
DISALLOW_COPY_AND_ASSIGN(HostResolverImpl);
};
diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index 09436e34..68bd8a6b 100644
--- a/net/base/host_resolver_impl_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -13,6 +13,7 @@
#include "net/base/completion_callback.h"
#include "net/base/load_log_unittest.h"
#include "net/base/mock_host_resolver.h"
+#include "net/base/mock_network_change_notifier.h"
#include "net/base/net_errors.h"
#include "net/base/sys_addrinfo.h"
#include "net/base/test_completion_callback.h"
@@ -185,7 +186,7 @@
resolver_proc->AddRule("just.testing", "192.168.1.42");
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
HostResolver::RequestInfo info("just.testing", kPortnum);
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
@@ -217,7 +218,7 @@
resolver_proc->AddRule("just.testing", "192.168.1.42");
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
HostResolver::RequestInfo info("just.testing", kPortnum);
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
@@ -254,7 +255,7 @@
scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
{
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
AddressList adrlist;
const int kPortnum = 80;
@@ -289,7 +290,7 @@
resolver_proc->AllowDirectLookup("*");
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
AddressList adrlist;
const int kPortnum = 5555;
HostResolver::RequestInfo info("127.1.2.3", kPortnum);
@@ -314,7 +315,7 @@
// Resolve a plain IPv6 address. Don't worry about [brackets], because
// the caller should have removed them.
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
AddressList adrlist;
const int kPortnum = 5555;
HostResolver::RequestInfo info("2001:db8::1", kPortnum);
@@ -349,7 +350,7 @@
resolver_proc->AllowDirectLookup("*");
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
AddressList adrlist;
const int kPortnum = 5555;
HostResolver::RequestInfo info("", kPortnum);
@@ -410,7 +411,7 @@
new CapturingHostResolverProc(NULL);
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -461,7 +462,7 @@
new CapturingHostResolverProc(NULL);
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -548,7 +549,7 @@
new CapturingHostResolverProc(NULL);
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, CreateDefaultCache()));
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -609,7 +610,7 @@
// checks that the right things happened. Note that the verifier holds the
// only reference to |host_resolver|, so it can delete it within callback.
HostResolver* host_resolver =
- new HostResolverImpl(resolver_proc, CreateDefaultCache());
+ new HostResolverImpl(resolver_proc, CreateDefaultCache(), NULL);
DeleteWithinCallbackVerifier verifier(host_resolver);
// Start 4 requests, duplicating hosts "a". Since the resolver_proc is
@@ -662,7 +663,7 @@
// Turn off caching for this host resolver.
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(resolver_proc, NULL));
+ new HostResolverImpl(resolver_proc, NULL, NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -727,7 +728,7 @@
TEST_F(HostResolverImplTest, BypassCache) {
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(NULL, CreateDefaultCache()));
+ new HostResolverImpl(NULL, CreateDefaultCache(), NULL));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -811,7 +812,7 @@
// synchronous.
TEST_F(HostResolverImplTest, Observers) {
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(NULL, CreateDefaultCache()));
+ new HostResolverImpl(NULL, CreateDefaultCache(), NULL));
CapturingObserver observer;
@@ -897,7 +898,7 @@
{
// Create a host resolver and attach an observer.
scoped_refptr<HostResolver> host_resolver(
- new HostResolverImpl(NULL, CreateDefaultCache()));
+ new HostResolverImpl(NULL, CreateDefaultCache(), NULL));
host_resolver->AddObserver(&observer);
TestCompletionCallback callback;
@@ -960,5 +961,37 @@
CapturingObserver::StartOrCancelEntry(1, info));
}
+// Test that IP address changes flush the cache.
+TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) {
+ scoped_refptr<MockNetworkChangeNotifier> mock_network_change_notifier(
+ new MockNetworkChangeNotifier);
+ scoped_refptr<HostResolver> host_resolver(
+ new HostResolverImpl(NULL, CreateDefaultCache(),
+ mock_network_change_notifier));
+
+ AddressList addrlist;
+
+ // Resolve "host1".
+ HostResolver::RequestInfo info1("host1", 70);
+ TestCompletionCallback callback;
+ int rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Resolve "host1" again -- this time it will be served from cache, but it
+ // should still notify of completion.
+ rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL);
+ ASSERT_EQ(OK, rv); // Should complete synchronously.
+
+ // Flush cache by triggering an IP address change.
+ mock_network_change_notifier->NotifyIPAddressChange();
+
+ // Resolve "host1" again -- this time it won't be served from cache, so it
+ // will complete asynchronously.
+ rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL);
+ ASSERT_EQ(ERR_IO_PENDING, rv); // Should complete asynchronously.
+ EXPECT_EQ(OK, callback.WaitForResult());
+}
+
} // namespace
} // namespace net
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc
index cf38490..0bac1ff 100644
--- a/net/base/mock_host_resolver.cc
+++ b/net/base/mock_host_resolver.cc
@@ -102,7 +102,7 @@
base::TimeDelta::FromSeconds(0));
}
- impl_ = new HostResolverImpl(proc, cache);
+ impl_ = new HostResolverImpl(proc, cache, NULL);
}
//-----------------------------------------------------------------------------