summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser_unittest.cc20
-rw-r--r--chrome/browser/net/dns_global.cc6
-rw-r--r--chrome/browser/net/dns_master_unittest.cc88
-rw-r--r--chrome/browser/search_engines/template_url_scraper_unittest.cc8
-rw-r--r--chrome/test/in_process_browser_test.cc19
-rw-r--r--chrome/test/in_process_browser_test.h10
-rw-r--r--chrome/test/unit/chrome_test_suite.h24
-rw-r--r--net/base/address_list_unittest.cc23
-rw-r--r--net/base/host_resolver.cc608
-rw-r--r--net/base/host_resolver.h159
-rw-r--r--net/base/host_resolver_impl.cc483
-rw-r--r--net/base/host_resolver_impl.h136
-rw-r--r--net/base/host_resolver_impl_unittest.cc (renamed from net/base/host_resolver_unittest.cc)236
-rw-r--r--net/base/host_resolver_proc.cc180
-rw-r--r--net/base/host_resolver_proc.h69
-rw-r--r--net/base/mock_host_resolver.cc154
-rw-r--r--net/base/mock_host_resolver.h143
-rw-r--r--net/base/run_all_unittests.cc12
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc11
-rw-r--r--net/http/http_network_layer_unittest.cc8
-rw-r--r--net/http/http_network_transaction_unittest.cc25
-rw-r--r--net/net.gyp10
-rw-r--r--net/proxy/proxy_resolver_perftest.cc4
-rw-r--r--net/proxy/proxy_resolver_v8.h2
-rw-r--r--net/proxy/proxy_resolver_v8_unittest.cc14
-rw-r--r--net/proxy/proxy_script_fetcher_unittest.cc2
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc11
-rw-r--r--net/socket/socks5_client_socket_unittest.cc22
-rw-r--r--net/socket/socks_client_socket_unittest.cc23
-rw-r--r--net/socket/ssl_client_socket_unittest.cc22
-rw-r--r--net/socket/ssl_test_util.cc2
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc22
-rw-r--r--net/socket/tcp_client_socket_unittest.cc2
-rw-r--r--net/socket/tcp_pinger_unittest.cc4
-rw-r--r--net/tools/fetch/fetch_client.cc4
-rw-r--r--net/url_request/url_request_unittest.cc2
-rw-r--r--net/url_request/url_request_unittest.h4
-rw-r--r--webkit/tools/test_shell/test_shell_request_context.cc2
38 files changed, 1503 insertions, 1071 deletions
diff --git a/chrome/browser/browser_unittest.cc b/chrome/browser/browser_unittest.cc
index 1ef86da..702d1dce 100644
--- a/chrome/browser/browser_unittest.cc
+++ b/chrome/browser/browser_unittest.cc
@@ -4,21 +4,21 @@
#include "chrome/browser/browser.h"
#include "chrome/test/in_process_browser_test.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
class BrowserTest : public InProcessBrowserTest {
public:
BrowserTest() {
- host_mapper_ = new net::RuleBasedHostMapper();
+ host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
// Avoid making external DNS lookups. In this test we don't need this
// to succeed.
- host_mapper_->AddSimulatedFailure("*.google.com");
- scoped_host_mapper_.Init(host_mapper_.get());
+ host_resolver_proc_->AddSimulatedFailure("*.google.com");
+ scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
}
private:
- scoped_refptr<net::RuleBasedHostMapper> host_mapper_;
- net::ScopedHostMapper scoped_host_mapper_;
+ scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
+ net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
};
/*
@@ -38,7 +38,7 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, NoTabsInPopups) {
// Now try opening another tab in the popup browser.
popup_browser->AddTabWithURL(GURL("about:blank"), GURL(),
PageTransition::TYPED, true, -1, NULL);
-
+
// The popup should still only have one tab.
EXPECT_EQ(1, popup_browser->tab_count());
@@ -54,7 +54,7 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, NoTabsInPopups) {
// Now try opening another tab in the app browser.
app_browser->AddTabWithURL(GURL("about:blank"), GURL(),
PageTransition::TYPED, true, -1, NULL);
-
+
// The popup should still only have one tab.
EXPECT_EQ(1, app_browser->tab_count());
@@ -70,7 +70,7 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, NoTabsInPopups) {
// Now try opening another tab in the app popup browser.
app_popup_browser->AddTabWithURL(GURL("about:blank"), GURL(),
PageTransition::TYPED, true, -1, NULL);
-
+
// The popup should still only have one tab.
EXPECT_EQ(1, app_popup_browser->tab_count());
@@ -82,4 +82,4 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, NoTabsInPopups) {
app_browser->CloseAllTabs();
app_popup_browser->CloseAllTabs();
}
-*/ \ No newline at end of file
+*/
diff --git a/chrome/browser/net/dns_global.cc b/chrome/browser/net/dns_global.cc
index d18ea45..25829e7 100644
--- a/chrome/browser/net/dns_global.cc
+++ b/chrome/browser/net/dns_global.cc
@@ -476,11 +476,7 @@ static void DiscardAllPrefetchState() {
net::HostResolver* GetGlobalHostResolver() {
// Called from UI thread.
if (!global_host_resolver) {
- static const size_t kMaxHostCacheEntries = 100;
- static const size_t kHostCacheExpirationSeconds = 60; // 1 minute.
-
- global_host_resolver = new net::HostResolver(
- kMaxHostCacheEntries, kHostCacheExpirationSeconds * 1000);
+ global_host_resolver = net::CreateSystemHostResolver();
}
return global_host_resolver;
}
diff --git a/chrome/browser/net/dns_master_unittest.cc b/chrome/browser/net/dns_master_unittest.cc
index 61ffd68..c3746bb 100644
--- a/chrome/browser/net/dns_master_unittest.cc
+++ b/chrome/browser/net/dns_master_unittest.cc
@@ -10,13 +10,13 @@
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
+#include "base/string_util.h"
#include "base/timer.h"
#include "chrome/browser/net/dns_global.h"
#include "chrome/browser/net/dns_host_info.h"
#include "chrome/common/net/dns.h"
#include "net/base/address_list.h"
-#include "net/base/host_resolver.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/winsock_init.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -59,10 +59,9 @@ class WaitForResolutionHelper {
class DnsMasterTest : public testing::Test {
public:
DnsMasterTest()
- : mapper_(new net::RuleBasedHostMapper()),
+ : host_resolver_(new net::MockHostResolver()),
default_max_queueing_delay_(TimeDelta::FromMilliseconds(
- DnsPrefetcherInit::kMaxQueueingDelayMs)),
- scoped_mapper_(mapper_.get()) {
+ DnsPrefetcherInit::kMaxQueueingDelayMs)) {
}
protected:
@@ -70,10 +69,11 @@ class DnsMasterTest : public testing::Test {
#if defined(OS_WIN)
net::EnsureWinsockInit();
#endif
- mapper_->AddRuleWithLatency("www.google.com", "127.0.0.1", 50);
- mapper_->AddRuleWithLatency("gmail.google.com.com", "127.0.0.1", 70);
- mapper_->AddRuleWithLatency("mail.google.com", "127.0.0.1", 44);
- mapper_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63);
+ net::RuleBasedHostResolverProc* rules = host_resolver_->rules();
+ rules->AddRuleWithLatency("www.google.com", "127.0.0.1", 50);
+ rules->AddRuleWithLatency("gmail.google.com.com", "127.0.0.1", 70);
+ rules->AddRuleWithLatency("mail.google.com", "127.0.0.1", 44);
+ rules->AddRuleWithLatency("gmail.com", "127.0.0.1", 63);
}
void WaitForResolution(DnsMaster* master, const NameList& hosts) {
@@ -84,15 +84,18 @@ class DnsMasterTest : public testing::Test {
MessageLoop::current()->Run();
}
- scoped_refptr<net::RuleBasedHostMapper> mapper_;
+ private:
+ // IMPORTANT: do not move this below |host_resolver_|; the host resolver
+ // must not outlive the message loop, otherwise bad things can happen
+ // (like posting to a deleted message loop).
+ MessageLoop loop;
+
+ protected:
+ scoped_refptr<net::MockHostResolver> host_resolver_;
// Shorthand to access TimeDelta of DnsPrefetcherInit::kMaxQueueingDelayMs.
// (It would be a static constant... except style rules preclude that :-/ ).
const TimeDelta default_max_queueing_delay_;
-
- private:
- MessageLoop loop;
- net::ScopedHostMapper scoped_mapper_;
};
//------------------------------------------------------------------------------
@@ -113,15 +116,15 @@ static std::string GetNonexistantDomain() {
//------------------------------------------------------------------------------
// Use a blocking function to contrast results we get via async services.
//------------------------------------------------------------------------------
-TimeDelta BlockingDnsLookup(const std::string& hostname) {
- Time start = Time::Now();
+TimeDelta BlockingDnsLookup(net::HostResolver* resolver,
+ const std::string& hostname) {
+ Time start = Time::Now();
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
- net::AddressList addresses;
- net::HostResolver::RequestInfo info(hostname, 80);
- resolver->Resolve(info, &addresses, NULL, NULL);
+ net::AddressList addresses;
+ net::HostResolver::RequestInfo info(hostname, 80);
+ resolver->Resolve(info, &addresses, NULL, NULL);
- return Time::Now() - start;
+ return Time::Now() - start;
}
//------------------------------------------------------------------------------
@@ -129,7 +132,9 @@ TimeDelta BlockingDnsLookup(const std::string& hostname) {
// First test to be sure the OS is caching lookups, which is the whole premise
// of DNS prefetching.
TEST_F(DnsMasterTest, OsCachesLookupsTest) {
- mapper_->AllowDirectLookup("*.google.com");
+ // Make sure caching is disabled in the mock host resolver.
+ host_resolver_->Reset(NULL, 0, 0);
+ host_resolver_->rules()->AllowDirectLookup("*.google.com");
const Time start = Time::Now();
int all_lookups = 0;
@@ -140,13 +145,13 @@ TEST_F(DnsMasterTest, OsCachesLookupsTest) {
std::string badname;
badname = GetNonexistantDomain();
- TimeDelta duration = BlockingDnsLookup(badname);
+ TimeDelta duration = BlockingDnsLookup(host_resolver_, badname);
// Produce more than one result and remove the largest one
// to reduce flakiness.
std::vector<TimeDelta> cached_results;
for (int j = 0; j < 3; j++)
- cached_results.push_back(BlockingDnsLookup(badname));
+ cached_results.push_back(BlockingDnsLookup(host_resolver_, badname));
std::sort(cached_results.begin(), cached_results.end());
cached_results.pop_back();
@@ -168,14 +173,14 @@ TEST_F(DnsMasterTest, OsCachesLookupsTest) {
}
TEST_F(DnsMasterTest, StartupShutdownTest) {
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
testing_master->Shutdown();
}
TEST_F(DnsMasterTest, BenefitLookupTest) {
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
@@ -236,10 +241,11 @@ TEST_F(DnsMasterTest, BenefitLookupTest) {
}
TEST_F(DnsMasterTest, ShutdownWhenResolutionIsPendingTest) {
- scoped_refptr<net::WaitingHostMapper> mapper = new net::WaitingHostMapper();
- net::ScopedHostMapper scoped_mapper(mapper.get());
+ scoped_refptr<net::WaitingHostResolverProc> resolver_proc =
+ new net::WaitingHostResolverProc(NULL);
+ host_resolver_->Reset(resolver_proc, 0, 0);
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
@@ -258,12 +264,12 @@ TEST_F(DnsMasterTest, ShutdownWhenResolutionIsPendingTest) {
testing_master->Shutdown();
// Clean up after ourselves.
- mapper->Signal();
+ resolver_proc->Signal();
MessageLoop::current()->RunAllPending();
}
TEST_F(DnsMasterTest, SingleLookupTest) {
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
@@ -291,9 +297,9 @@ TEST_F(DnsMasterTest, SingleLookupTest) {
}
TEST_F(DnsMasterTest, ConcurrentLookupTest) {
- mapper_->AddSimulatedFailure("*.notfound");
+ host_resolver_->rules()->AddSimulatedFailure("*.notfound");
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
@@ -313,12 +319,6 @@ TEST_F(DnsMasterTest, ConcurrentLookupTest) {
names.insert(names.end(), goog4);
names.insert(names.end(), goog);
- // Warm up the *OS* cache for all the goog domains.
- BlockingDnsLookup(goog);
- BlockingDnsLookup(goog2);
- BlockingDnsLookup(goog3);
- BlockingDnsLookup(goog4);
-
// Try to flood the master with many concurrent requests.
for (int i = 0; i < 10; i++)
testing_master->ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
@@ -346,9 +346,9 @@ TEST_F(DnsMasterTest, ConcurrentLookupTest) {
}
TEST_F(DnsMasterTest, DISABLED_MassiveConcurrentLookupTest) {
- mapper_->AddSimulatedFailure("*.notfound");
+ host_resolver_->rules()->AddSimulatedFailure("*.notfound");
- scoped_refptr<DnsMaster> testing_master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> testing_master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
@@ -453,7 +453,7 @@ int GetLatencyFromSerialization(const std::string& motivation,
// Make sure nil referral lists really have no entries, and no latency listed.
TEST_F(DnsMasterTest, ReferrerSerializationNilTest) {
- scoped_refptr<DnsMaster> master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
ListValue referral_list;
@@ -469,7 +469,7 @@ TEST_F(DnsMasterTest, ReferrerSerializationNilTest) {
// deserialized into the database, and can be extracted back out via
// serialization without being changed.
TEST_F(DnsMasterTest, ReferrerSerializationSingleReferrerTest) {
- scoped_refptr<DnsMaster> master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
std::string motivation_hostname = "www.google.com";
@@ -494,7 +494,7 @@ TEST_F(DnsMasterTest, ReferrerSerializationSingleReferrerTest) {
// Make sure the Trim() functionality works as expected.
TEST_F(DnsMasterTest, ReferrerSerializationTrimTest) {
- scoped_refptr<DnsMaster> master = new DnsMaster(new net::HostResolver,
+ scoped_refptr<DnsMaster> master = new DnsMaster(host_resolver_,
MessageLoop::current(), default_max_queueing_delay_,
DnsPrefetcherInit::kMaxConcurrentLookups);
std::string motivation_hostname = "www.google.com";
diff --git a/chrome/browser/search_engines/template_url_scraper_unittest.cc b/chrome/browser/search_engines/template_url_scraper_unittest.cc
index 71aace7..a93790f 100644
--- a/chrome/browser/search_engines/template_url_scraper_unittest.cc
+++ b/chrome/browser/search_engines/template_url_scraper_unittest.cc
@@ -11,7 +11,7 @@
#include "chrome/common/notification_type.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/net_util.h"
namespace {
@@ -21,10 +21,10 @@ class TemplateURLScraperTest : public InProcessBrowserTest {
}
protected:
- virtual void ConfigureHostMapper(net::RuleBasedHostMapper* host_mapper) {
- InProcessBrowserTest::ConfigureHostMapper(host_mapper);
+ virtual void ConfigureHostResolverProc(net::RuleBasedHostResolverProc* proc) {
+ InProcessBrowserTest::ConfigureHostResolverProc(proc);
// We use foo.com in our tests.
- host_mapper->AddRule("*.foo.com", "localhost");
+ proc->AddRule("*.foo.com", "localhost");
}
private:
diff --git a/chrome/test/in_process_browser_test.cc b/chrome/test/in_process_browser_test.cc
index b43edd2..7544b49 100644
--- a/chrome/test/in_process_browser_test.cc
+++ b/chrome/test/in_process_browser_test.cc
@@ -26,7 +26,7 @@
#include "chrome/common/main_function_params.h"
#include "chrome/test/testing_browser_process.h"
#include "chrome/test/ui_test_utils.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "sandbox/src/dep.h"
extern int BrowserMain(const MainFunctionParams&);
@@ -140,10 +140,11 @@ void InProcessBrowserTest::SetUp() {
params.ui_task =
NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
- scoped_refptr<net::RuleBasedHostMapper> host_mapper(
- new net::RuleBasedHostMapper());
- ConfigureHostMapper(host_mapper.get());
- net::ScopedHostMapper scoped_host_mapper(host_mapper.get());
+ scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc(
+ new net::RuleBasedHostResolverProc(NULL));
+ ConfigureHostResolverProc(host_resolver_proc);
+ net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
+ host_resolver_proc);
BrowserMain(params);
}
@@ -241,12 +242,12 @@ void InProcessBrowserTest::RunTestOnMainThreadLoop() {
MessageLoopForUI::current()->Quit();
}
-void InProcessBrowserTest::ConfigureHostMapper(
- net::RuleBasedHostMapper* host_mapper) {
- host_mapper->AllowDirectLookup("*.google.com");
+void InProcessBrowserTest::ConfigureHostResolverProc(
+ net::RuleBasedHostResolverProc* host_resolver_proc) {
+ host_resolver_proc->AllowDirectLookup("*.google.com");
// See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
// We don't want the test code to use it.
- host_mapper->AddSimulatedFailure("wpad");
+ host_resolver_proc->AddSimulatedFailure("wpad");
}
void InProcessBrowserTest::TimedOut() {
diff --git a/chrome/test/in_process_browser_test.h b/chrome/test/in_process_browser_test.h
index bec71d9..11a2880 100644
--- a/chrome/test/in_process_browser_test.h
+++ b/chrome/test/in_process_browser_test.h
@@ -11,7 +11,7 @@
class Browser;
class Profile;
namespace net {
-class RuleBasedHostMapper;
+class RuleBasedHostResolverProc;
}
// Base class for tests wanting to bring up a browser in the unit test process.
@@ -66,10 +66,10 @@ class InProcessBrowserTest : public testing::Test {
// main thread before the browser is torn down.
virtual void CleanUpOnMainThread() {}
- // Allows subclasses to configure the host mapper. By default this blocks
- // requests to google.com as Chrome pings that on startup and we don't want to
- // do that during testing.
- virtual void ConfigureHostMapper(net::RuleBasedHostMapper* host_mapper);
+ // Allows subclasses to configure the host resolver procedure. By default
+ // this blocks requests to google.com as Chrome pings that on startup and we
+ // don't want to do that during testing.
+ virtual void ConfigureHostResolverProc(net::RuleBasedHostResolverProc* proc);
// Invoked when a test is not finishing in a timely manner.
void TimedOut();
diff --git a/chrome/test/unit/chrome_test_suite.h b/chrome/test/unit/chrome_test_suite.h
index 7c49d72..7f8733b 100644
--- a/chrome/test/unit/chrome_test_suite.h
+++ b/chrome/test/unit/chrome_test_suite.h
@@ -28,15 +28,17 @@
#include "chrome/common/mac_app_names.h"
#endif
#include "chrome/test/testing_browser_process.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/net_util.h"
// In many cases it may be not obvious that a test makes a real DNS lookup.
// We generally don't want to rely on external DNS servers for our tests,
-// so this mapper catches external queries.
-class WarningHostMapper : public net::HostMapper {
+// so this host resolver procedure catches external queries.
+class WarningHostResolverProc : public net::HostResolverProc {
public:
- virtual std::string Map(const std::string& host) {
+ WarningHostResolverProc() : HostResolverProc(NULL) {}
+
+ virtual int Resolve(const std::string& host, net::AddressList* addrlist) {
const char* kLocalHostNames[] = {"localhost", "127.0.0.1"};
bool local = false;
@@ -51,11 +53,11 @@ class WarningHostMapper : public net::HostMapper {
}
// Make the test fail so it's harder to ignore.
- // If you really need to make real DNS query, use net::RuleBasedHostMapper
- // and its AllowDirectLookup method.
+ // If you really need to make real DNS query, use
+ // net::RuleBasedHostResolverProc and its AllowDirectLookup method.
EXPECT_TRUE(local) << "Making external DNS lookup of " << host;
- return MapUsingPrevious(host);
+ return ResolveUsingPrevious(host, addrlist);
}
};
@@ -71,8 +73,8 @@ class ChromeTestSuite : public TestSuite {
TestSuite::Initialize();
- host_mapper_ = new WarningHostMapper();
- scoped_host_mapper_.Init(host_mapper_.get());
+ host_resolver_proc_ = new WarningHostResolverProc();
+ scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
chrome::RegisterPathProvider();
app::RegisterPathProvider();
@@ -140,8 +142,8 @@ class ChromeTestSuite : public TestSuite {
StatsTable* stats_table_;
ScopedOleInitializer ole_initializer_;
- scoped_refptr<WarningHostMapper> host_mapper_;
- net::ScopedHostMapper scoped_host_mapper_;
+ scoped_refptr<WarningHostResolverProc> host_resolver_proc_;
+ net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
};
#endif // CHROME_TEST_UNIT_CHROME_TEST_SUITE_H_
diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc
index d594c85..d8ab3c1 100644
--- a/net/base/address_list_unittest.cc
+++ b/net/base/address_list_unittest.cc
@@ -4,15 +4,8 @@
#include "net/base/address_list.h"
-#if defined(OS_WIN)
-#include <ws2tcpip.h>
-#include <wspiapi.h> // Needed for Win2k compat.
-#elif defined(OS_POSIX)
-#include <netdb.h>
-#include <sys/socket.h>
-#endif
-
#include "base/string_util.h"
+#include "net/base/host_resolver_proc.h"
#include "net/base/net_util.h"
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
@@ -26,17 +19,9 @@ void CreateAddressList(net::AddressList* addrlist, int port) {
#if defined(OS_WIN)
net::EnsureWinsockInit();
#endif
- std::string portstr = IntToString(port);
-
- struct addrinfo* result = NULL;
- struct addrinfo hints = {0};
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = SOCK_STREAM;
-
- int err = getaddrinfo("192.168.1.1", portstr.c_str(), &hints, &result);
- EXPECT_EQ(0, err);
- addrlist->Adopt(result);
+ int rv = SystemHostResolverProc("192.168.1.1", addrlist);
+ EXPECT_EQ(0, rv);
+ addrlist->SetPort(port);
}
TEST(AddressListTest, GetPort) {
diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc
index 4f0ede5..1d17296 100644
--- a/net/base/host_resolver.cc
+++ b/net/base/host_resolver.cc
@@ -4,616 +4,12 @@
#include "net/base/host_resolver.h"
-#if defined(OS_WIN)
-#include <ws2tcpip.h>
-#include <wspiapi.h> // Needed for Win2k compat.
-#elif defined(OS_POSIX)
-#include <netdb.h>
-#include <sys/socket.h>
-#endif
-#if defined(OS_LINUX)
-#include <resolv.h>
-#endif
-
#include "base/compiler_specific.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "base/string_util.h"
-#include "base/time.h"
-#include "base/worker_pool.h"
-#include "net/base/address_list.h"
+#include "base/logging.h"
#include "net/base/net_errors.h"
-#if defined(OS_LINUX)
-#include "base/singleton.h"
-#include "base/thread_local_storage.h"
-#endif
-
-#if defined(OS_WIN)
-#include "net/base/winsock_init.h"
-#endif
-
namespace net {
-//-----------------------------------------------------------------------------
-
-static HostMapper* host_mapper;
-
-std::string HostMapper::MapUsingPrevious(const std::string& host) {
- return previous_mapper_.get() ? previous_mapper_->Map(host) : host;
-}
-
-HostMapper* SetHostMapper(HostMapper* value) {
- std::swap(host_mapper, value);
- return value;
-}
-
-#if defined(OS_LINUX)
-// On Linux changes to /etc/resolv.conf can go unnoticed thus resulting in
-// DNS queries failing either because nameservers are unknown on startup
-// or because nameserver info has changed as a result of e.g. connecting to
-// a new network. Some distributions patch glibc to stat /etc/resolv.conf
-// to try to automatically detect such changes but these patches are not
-// universal and even patched systems such as Jaunty appear to need calls
-// to res_ninit to reload the nameserver information in different threads.
-//
-// We adopt the Mozilla solution here which is to call res_ninit when
-// lookups fail and to rate limit the reloading to once per second per
-// thread.
-
-// Keep a timer per calling thread to rate limit the calling of res_ninit.
-class DnsReloadTimer {
- public:
- DnsReloadTimer() {
- tls_index_.Initialize(SlotReturnFunction);
- }
-
- ~DnsReloadTimer() { }
-
- // Check if the timer for the calling thread has expired. When no
- // timer exists for the calling thread, create one.
- bool Expired() {
- const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1);
- base::TimeTicks now = base::TimeTicks::Now();
- base::TimeTicks* timer_ptr =
- static_cast<base::TimeTicks*>(tls_index_.Get());
-
- if (!timer_ptr) {
- timer_ptr = new base::TimeTicks();
- *timer_ptr = base::TimeTicks::Now();
- tls_index_.Set(timer_ptr);
- // Return true to reload dns info on the first call for each thread.
- return true;
- } else if (now - *timer_ptr > kRetryTime) {
- *timer_ptr = now;
- return true;
- } else {
- return false;
- }
- }
-
- // Free the allocated timer.
- static void SlotReturnFunction(void* data) {
- base::TimeTicks* tls_data = static_cast<base::TimeTicks*>(data);
- delete tls_data;
- }
-
- private:
- // We use thread local storage to identify which base::TimeTicks to
- // interact with.
- static ThreadLocalStorage::Slot tls_index_ ;
-
- DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer);
-};
-
-// A TLS slot to the TimeTicks for the current thread.
-// static
-ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED);
-
-#endif // defined(OS_LINUX)
-
-static int HostResolverProc(const std::string& host, struct addrinfo** out) {
- struct addrinfo hints = {0};
- hints.ai_family = AF_UNSPEC;
-
-#if defined(OS_WIN)
- // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
- //
- // The following comment in <winsock2.h> is the best documentation I found
- // on AI_ADDRCONFIG for Windows:
- // Flags used in "hints" argument to getaddrinfo()
- // - AI_ADDRCONFIG is supported starting with Vista
- // - default is AI_ADDRCONFIG ON whether the flag is set or not
- // because the performance penalty in not having ADDRCONFIG in
- // the multi-protocol stack environment is severe;
- // this defaulting may be disabled by specifying the AI_ALL flag,
- // in that case AI_ADDRCONFIG must be EXPLICITLY specified to
- // enable ADDRCONFIG behavior
- //
- // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
- // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
- // to fail with WSANO_DATA (11004) for "localhost", probably because of the
- // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
- // The IPv4 or IPv6 loopback address is not considered a valid global
- // address.
- // See http://crbug.com/5234.
- hints.ai_flags = 0;
-#else
- hints.ai_flags = AI_ADDRCONFIG;
-#endif
-
- // Restrict result set to only this socket type to avoid duplicates.
- hints.ai_socktype = SOCK_STREAM;
-
- int err = getaddrinfo(host.c_str(), NULL, &hints, out);
-#if defined(OS_LINUX)
- net::DnsReloadTimer* dns_timer = Singleton<net::DnsReloadTimer>::get();
- // If we fail, re-initialise the resolver just in case there have been any
- // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info.
- if (err && dns_timer->Expired()) {
- res_nclose(&_res);
- if (!res_ninit(&_res))
- err = getaddrinfo(host.c_str(), NULL, &hints, out);
- }
-#endif
-
- return err ? ERR_NAME_NOT_RESOLVED : OK;
-}
-
-static int ResolveAddrInfo(HostMapper* mapper, const std::string& host,
- struct addrinfo** out) {
- if (mapper) {
- std::string mapped_host = mapper->Map(host);
-
- if (mapped_host.empty())
- return ERR_NAME_NOT_RESOLVED;
-
- return HostResolverProc(mapped_host, out);
- } else {
- return HostResolverProc(host, out);
- }
-}
-
-//-----------------------------------------------------------------------------
-
-class HostResolver::Request {
- public:
- Request(int id, const RequestInfo& info, CompletionCallback* callback,
- AddressList* addresses)
- : id_(id), info_(info), job_(NULL), callback_(callback),
- addresses_(addresses) {}
-
- // Mark the request as cancelled.
- void MarkAsCancelled() {
- job_ = NULL;
- callback_ = NULL;
- addresses_ = NULL;
- }
-
- bool was_cancelled() const {
- return callback_ == NULL;
- }
-
- void set_job(Job* job) {
- DCHECK(job != NULL);
- // Identify which job the request is waiting on.
- job_ = job;
- }
-
- void OnComplete(int error, const AddressList& addrlist) {
- if (error == OK)
- addresses_->SetFrom(addrlist, port());
- callback_->Run(error);
- }
-
- int port() const {
- return info_.port();
- }
-
- Job* job() const {
- return job_;
- }
-
- int id() const {
- return id_;
- }
-
- const RequestInfo& info() const {
- return info_;
- }
-
- private:
- // Unique ID for this request. Used by observers to identify requests.
- int id_;
-
- // The request info that started the request.
- RequestInfo info_;
-
- // The resolve job (running in worker pool) that this request is dependent on.
- Job* job_;
-
- // The user's callback to invoke when the request completes.
- CompletionCallback* callback_;
-
- // The address list to save result into.
- AddressList* addresses_;
-
- DISALLOW_COPY_AND_ASSIGN(Request);
-};
-
-//-----------------------------------------------------------------------------
-
-// This class represents a request to the worker pool for a "getaddrinfo()"
-// call.
-class HostResolver::Job : public base::RefCountedThreadSafe<HostResolver::Job> {
- public:
- Job(HostResolver* resolver, const std::string& host)
- : host_(host),
- resolver_(resolver),
- origin_loop_(MessageLoop::current()),
- host_mapper_(host_mapper),
- error_(OK),
- results_(NULL) {
- }
-
- ~Job() {
- if (results_)
- freeaddrinfo(results_);
-
- // Free the requests attached to this job.
- STLDeleteElements(&requests_);
- }
-
- // Attaches a request to this job. The job takes ownership of |req| and will
- // take care to delete it.
- void AddRequest(HostResolver::Request* req) {
- req->set_job(this);
- requests_.push_back(req);
- }
-
- // Called from origin loop.
- void Start() {
- // Dispatch the job to a worker thread.
- if (!WorkerPool::PostTask(FROM_HERE,
- NewRunnableMethod(this, &Job::DoLookup), true)) {
- NOTREACHED();
-
- // Since we could be running within Resolve() right now, we can't just
- // call OnLookupComplete(). Instead we must wait until Resolve() has
- // returned (IO_PENDING).
- error_ = ERR_UNEXPECTED;
- MessageLoop::current()->PostTask(
- FROM_HERE, NewRunnableMethod(this, &Job::OnLookupComplete));
- }
- }
-
- // Cancels the current job. Callable from origin thread.
- void Cancel() {
- HostResolver* resolver = resolver_;
- resolver_ = NULL;
-
- // Mark the job as cancelled, so when worker thread completes it will
- // not try to post completion to origin loop.
- {
- AutoLock locked(origin_loop_lock_);
- origin_loop_ = NULL;
- }
-
- // We don't have to do anything further to actually cancel the requests
- // that were attached to this job (since they are unreachable now).
- // But we will call HostResolver::CancelRequest(Request*) on each one
- // in order to notify any observers.
- for (RequestsList::const_iterator it = requests_.begin();
- it != requests_.end(); ++it) {
- HostResolver::Request* req = *it;
- if (!req->was_cancelled())
- resolver->CancelRequest(req);
- }
- }
-
- // Called from origin thread.
- bool was_cancelled() const {
- return resolver_ == NULL;
- }
-
- // Called from origin thread.
- const std::string& host() const {
- return host_;
- }
-
- // Called from origin thread.
- const RequestsList& requests() const {
- return requests_;
- }
-
- private:
- void DoLookup() {
- // Running on the worker thread
- error_ = ResolveAddrInfo(host_mapper_, host_, &results_);
-
- Task* reply = NewRunnableMethod(this, &Job::OnLookupComplete);
-
- // 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);
- reply = NULL;
- }
- }
-
- // Does nothing if it got posted.
- delete reply;
- }
-
- // Callback for when DoLookup() completes (runs on origin thread).
- void OnLookupComplete() {
- // Should be running on origin loop.
- // TODO(eroman): this is being hit by URLRequestTest.CancelTest*,
- // because MessageLoop::current() == NULL.
- //DCHECK_EQ(origin_loop_, MessageLoop::current());
- DCHECK(error_ || results_);
-
- if (was_cancelled())
- return;
-
- DCHECK(!requests_.empty());
-
- // Adopt the address list using the port number of the first request.
- AddressList addrlist;
- if (error_ == OK) {
- addrlist.Adopt(results_);
- addrlist.SetPort(requests_[0]->port());
- results_ = NULL;
- }
-
- resolver_->OnJobComplete(this, error_, addrlist);
- }
-
- // Set on the origin thread, read on the worker thread.
- std::string host_;
-
- // Only used on the origin thread (where Resolve was called).
- HostResolver* resolver_;
- RequestsList requests_; // The requests waiting on this job.
-
- // Used to post ourselves onto the origin thread.
- Lock origin_loop_lock_;
- MessageLoop* origin_loop_;
-
- // Hold an owning reference to the host mapper that we are going to use.
- // This may not be the current host mapper by the time we call
- // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
- // reference ensures that it remains valid until we are done.
- scoped_refptr<HostMapper> host_mapper_;
-
- // Assigned on the worker thread, read on the origin thread.
- int error_;
- struct addrinfo* results_;
-
- DISALLOW_COPY_AND_ASSIGN(Job);
-};
-
-//-----------------------------------------------------------------------------
-
-HostResolver::HostResolver(int max_cache_entries, int cache_duration_ms)
- : cache_(max_cache_entries, cache_duration_ms), next_request_id_(0),
- shutdown_(false) {
-#if defined(OS_WIN)
- EnsureWinsockInit();
-#endif
-}
-
-HostResolver::~HostResolver() {
- // Cancel the outstanding jobs. Those jobs may contain several attached
- // requests, which will also be cancelled.
- for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
- it->second->Cancel();
-
- // In case we are being deleted during the processing of a callback.
- if (cur_completing_job_)
- cur_completing_job_->Cancel();
-}
-
-// TODO(eroman): Don't create cache entries for hostnames which are simply IP
-// address literals.
-int HostResolver::Resolve(const RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback,
- Request** out_req) {
- if (shutdown_)
- return ERR_UNEXPECTED;
-
- // Choose a unique ID number for observers to see.
- int request_id = next_request_id_++;
-
- // Notify registered observers.
- NotifyObserversStartRequest(request_id, info);
-
- // If we have an unexpired cache entry, use it.
- if (info.allow_cached_response()) {
- const HostCache::Entry* cache_entry = cache_.Lookup(
- info.hostname(), base::TimeTicks::Now());
- if (cache_entry) {
- addresses->SetFrom(cache_entry->addrlist, info.port());
- int error = OK;
-
- // Notify registered observers.
- NotifyObserversFinishRequest(request_id, info, error);
-
- return error;
- }
- }
-
- // If no callback was specified, do a synchronous resolution.
- if (!callback) {
- struct addrinfo* results;
- int error = ResolveAddrInfo(host_mapper, info.hostname(), &results);
-
- // Adopt the address list.
- AddressList addrlist;
- if (error == OK) {
- addrlist.Adopt(results);
- addrlist.SetPort(info.port());
- *addresses = addrlist;
- }
-
- // Write to cache.
- cache_.Set(info.hostname(), error, addrlist, base::TimeTicks::Now());
-
- // Notify registered observers.
- NotifyObserversFinishRequest(request_id, info, error);
-
- return error;
- }
-
- // Create a handle for this request, and pass it back to the user if they
- // asked for it (out_req != NULL).
- Request* req = new Request(request_id, info, callback, addresses);
- if (out_req)
- *out_req = req;
-
- // Next we need to attach our request to a "job". This job is responsible for
- // calling "getaddrinfo(hostname)" on a worker thread.
- scoped_refptr<Job> job;
-
- // If there is already an outstanding job to resolve |info.hostname()|, use
- // it. This prevents starting concurrent resolves for the same hostname.
- job = FindOutstandingJob(info.hostname());
- if (job) {
- job->AddRequest(req);
- } else {
- // Create a new job for this request.
- job = new Job(this, info.hostname());
- job->AddRequest(req);
- AddOutstandingJob(job);
- // TODO(eroman): Bound the total number of concurrent jobs.
- // http://crbug.com/9598
- job->Start();
- }
-
- // Completion happens during OnJobComplete(Job*).
- return ERR_IO_PENDING;
-}
-
-// See OnJobComplete(Job*) for why it is important not to clean out
-// cancelled requests from Job::requests_.
-void HostResolver::CancelRequest(Request* req) {
- DCHECK(req);
- DCHECK(req->job());
- // NULL out the fields of req, to mark it as cancelled.
- req->MarkAsCancelled();
- NotifyObserversCancelRequest(req->id(), req->info());
-}
-
-void HostResolver::AddObserver(Observer* observer) {
- observers_.push_back(observer);
-}
-
-void HostResolver::RemoveObserver(Observer* observer) {
- ObserversList::iterator it =
- std::find(observers_.begin(), observers_.end(), observer);
-
- // Observer must exist.
- DCHECK(it != observers_.end());
-
- observers_.erase(it);
-}
-
-void HostResolver::Shutdown() {
- shutdown_ = true;
-
- // Cancel the outstanding jobs.
- for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
- it->second->Cancel();
- jobs_.clear();
-}
-
-void HostResolver::AddOutstandingJob(Job* job) {
- scoped_refptr<Job>& found_job = jobs_[job->host()];
- DCHECK(!found_job);
- found_job = job;
-}
-
-HostResolver::Job* HostResolver::FindOutstandingJob(
- const std::string& hostname) {
- JobMap::iterator it = jobs_.find(hostname);
- if (it != jobs_.end())
- return it->second;
- return NULL;
-}
-
-void HostResolver::RemoveOutstandingJob(Job* job) {
- JobMap::iterator it = jobs_.find(job->host());
- DCHECK(it != jobs_.end());
- DCHECK_EQ(it->second.get(), job);
- jobs_.erase(it);
-}
-
-void HostResolver::OnJobComplete(Job* job,
- int error,
- const AddressList& addrlist) {
- RemoveOutstandingJob(job);
-
- // Write result to the cache.
- cache_.Set(job->host(), error, addrlist, base::TimeTicks::Now());
-
- // Make a note that we are executing within OnJobComplete() in case the
- // HostResolver is deleted by a callback invocation.
- DCHECK(!cur_completing_job_);
- cur_completing_job_ = job;
-
- // Complete all of the requests that were attached to the job.
- for (RequestsList::const_iterator it = job->requests().begin();
- it != job->requests().end(); ++it) {
- Request* req = *it;
- if (!req->was_cancelled()) {
- DCHECK_EQ(job, req->job());
-
- // Notify registered observers.
- NotifyObserversFinishRequest(req->id(), req->info(), error);
-
- req->OnComplete(error, addrlist);
-
- // Check if the job was cancelled as a result of running the callback.
- // (Meaning that |this| was deleted).
- if (job->was_cancelled())
- return;
- }
- }
-
- cur_completing_job_ = NULL;
-}
-
-void HostResolver::NotifyObserversStartRequest(int request_id,
- const RequestInfo& info) {
- for (ObserversList::iterator it = observers_.begin();
- it != observers_.end(); ++it) {
- (*it)->OnStartResolution(request_id, info);
- }
-}
-
-void HostResolver::NotifyObserversFinishRequest(int request_id,
- const RequestInfo& info,
- int error) {
- bool was_resolved = error == OK;
- for (ObserversList::iterator it = observers_.begin();
- it != observers_.end(); ++it) {
- (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
- }
-}
-
-void HostResolver::NotifyObserversCancelRequest(int request_id,
- const RequestInfo& info) {
- for (ObserversList::iterator it = observers_.begin();
- it != observers_.end(); ++it) {
- (*it)->OnCancelResolution(request_id, info);
- }
-}
-
-//-----------------------------------------------------------------------------
-
SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
: resolver_(resolver),
cur_request_(NULL),
@@ -634,7 +30,7 @@ int SingleRequestHostResolver::Resolve(const HostResolver::RequestInfo& info,
CompletionCallback* callback) {
DCHECK(!cur_request_ && !cur_request_callback_) << "resolver already in use";
- HostResolver::Request* request = NULL;
+ HostResolver::RequestHandle request = NULL;
// We need to be notified of completion before |callback| is called, so that
// we can clear out |cur_request_*|.
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index 5a6c548..c1ac13f 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -6,57 +6,26 @@
#define NET_BASE_HOST_RESOLVER_H_
#include <string>
-#include <vector>
-#include "base/basictypes.h"
-#include "base/lock.h"
#include "base/ref_counted.h"
#include "googleurl/src/gurl.h"
#include "net/base/completion_callback.h"
-#include "net/base/host_cache.h"
class MessageLoop;
namespace net {
class AddressList;
-class HostMapper;
// This class represents the task of resolving hostnames (or IP address
// literal) to an AddressList object.
//
-// HostResolver handles multiple requests at a time, so when cancelling a
-// request the Request* handle that was returned by Resolve() needs to be
+// HostResolver can handle multiple requests at a time, so when cancelling a
+// request the RequestHandle that was returned by Resolve() needs to be
// given. A simpler alternative for consumers that only have 1 outstanding
// request at a time is to create a SingleRequestHostResolver wrapper around
// HostResolver (which will automatically cancel the single request when it
// goes out of scope).
-//
-// For each hostname that is requested, HostResolver creates a
-// HostResolver::Job. This job gets dispatched to a thread in the global
-// WorkerPool, where it runs "getaddrinfo(hostname)". If requests for that same
-// host are made while the job is already outstanding, then they are attached
-// to the existing job rather than creating a new one. This avoids doing
-// parallel resolves for the same host.
-//
-// The way these classes fit together is illustrated by:
-//
-//
-// +------------- HostResolver ---------------+
-// | | |
-// Job Job Job
-// (for host1) (for host2) (for hostX)
-// / | | / | | / | |
-// Request ... Request Request ... Request Request ... Request
-// (port1) (port2) (port3) (port4) (port5) (portX)
-//
-//
-// When a HostResolver::Job finishes its work in the threadpool, the callbacks
-// of each waiting request are run on the origin thread.
-//
-// Thread safety: This class is not threadsafe, and must only be called
-// from one thread!
-//
class HostResolver : public base::RefCounted<HostResolver> {
public:
// The parameters for doing a Resolve(). |hostname| and |port| are required,
@@ -120,20 +89,15 @@ class HostResolver : public base::RefCounted<HostResolver> {
virtual void OnCancelResolution(int id, const RequestInfo& info) = 0;
};
- // Creates a HostResolver that caches up to |max_cache_entries| for
- // |cache_duration_ms| milliseconds.
- //
- // TODO(eroman): Get rid of the default parameters as it violate google
- // style. This is temporary to help with refactoring.
- HostResolver(int max_cache_entries = 100, int cache_duration_ms = 60000);
+ // Opaque type used to cancel a request.
+ typedef void* RequestHandle;
+
+ HostResolver() {}
// If any completion callbacks are pending when the resolver is destroyed,
// the host resolutions are cancelled, and the completion callbacks will not
// be called.
- ~HostResolver();
-
- // Opaque type used to cancel a request.
- class Request;
+ virtual ~HostResolver() {}
// Resolves the given hostname (or IP address literal), filling out the
// |addresses| object upon success. The |info.port| parameter will be set as
@@ -147,74 +111,23 @@ class HostResolver : public base::RefCounted<HostResolver> {
// result code will be passed to the completion callback. If |req| is
// non-NULL, then |*req| will be filled with a handle to the async request.
// This handle is not valid after the request has completed.
- int Resolve(const RequestInfo& info, AddressList* addresses,
- CompletionCallback* callback, Request** req);
+ virtual int Resolve(const RequestInfo& info, AddressList* addresses,
+ CompletionCallback* callback, RequestHandle* out_req) = 0;
// Cancels the specified request. |req| is the handle returned by Resolve().
// After a request is cancelled, its completion callback will not be called.
- void CancelRequest(Request* req);
+ virtual void CancelRequest(RequestHandle req) = 0;
// Adds an observer to this resolver. The observer will be notified of the
// start and completion of all requests (excluding cancellation). |observer|
// must remain valid for the duration of this HostResolver's lifetime.
- void AddObserver(Observer* observer);
+ virtual void AddObserver(Observer* observer) = 0;
// Unregisters an observer previously added by AddObserver().
- void RemoveObserver(Observer* observer);
-
- // TODO(eroman): temp hack for http://crbug.com/15513
- void Shutdown();
-
- private:
- class Job;
- typedef std::vector<Request*> RequestsList;
- typedef base::hash_map<std::string, scoped_refptr<Job> > JobMap;
- typedef std::vector<Observer*> ObserversList;
-
- // Adds a job to outstanding jobs list.
- void AddOutstandingJob(Job* job);
-
- // Returns the outstanding job for |hostname|, or NULL if there is none.
- Job* FindOutstandingJob(const std::string& hostname);
-
- // Removes |job| from the outstanding jobs list.
- void RemoveOutstandingJob(Job* job);
-
- // Callback for when |job| has completed with |error| and |addrlist|.
- void OnJobComplete(Job* job, int error, const AddressList& addrlist);
-
- // Notify all observers of the start of a resolve request.
- void NotifyObserversStartRequest(int request_id,
- const RequestInfo& info);
-
- // Notify all observers of the completion of a resolve request.
- void NotifyObserversFinishRequest(int request_id,
- const RequestInfo& info,
- int error);
-
- // Notify all observers of the cancellation of a resolve request.
- void NotifyObserversCancelRequest(int request_id,
- const RequestInfo& info);
-
- // Cache of host resolution results.
- HostCache cache_;
-
- // Map from hostname to outstanding job.
- JobMap jobs_;
-
- // The job that OnJobComplete() is currently processing (needed in case
- // HostResolver gets deleted from within the callback).
- scoped_refptr<Job> cur_completing_job_;
-
- // The observers to notify when a request starts/ends.
- ObserversList observers_;
-
- // Monotonically increasing ID number to assign to the next request.
- // Observers are the only consumers of this ID number.
- int next_request_id_;
+ virtual void RemoveObserver(Observer* observer) = 0;
// TODO(eroman): temp hack for http://crbug.com/15513
- bool shutdown_;
+ virtual void Shutdown() = 0;
DISALLOW_COPY_AND_ASSIGN(HostResolver);
};
@@ -245,7 +158,7 @@ class SingleRequestHostResolver {
scoped_refptr<HostResolver> resolver_;
// The current request (if any).
- HostResolver::Request* cur_request_;
+ HostResolver::RequestHandle cur_request_;
CompletionCallback* cur_request_callback_;
// Completion callback for when request to |resolver_| completes.
@@ -254,46 +167,10 @@ class SingleRequestHostResolver {
DISALLOW_COPY_AND_ASSIGN(SingleRequestHostResolver);
};
-// A helper class used in unit tests to alter hostname mappings. See
-// SetHostMapper for details.
-class HostMapper : public base::RefCountedThreadSafe<HostMapper> {
- public:
- virtual ~HostMapper() {}
-
- // Returns possibly altered hostname, or empty string to simulate
- // a failed lookup.
- virtual std::string Map(const std::string& host) = 0;
-
- protected:
- // Ask previous host mapper (if set) for mapping of given host.
- std::string MapUsingPrevious(const std::string& host);
-
- private:
- friend class ScopedHostMapper;
-
- // Set mapper to ask when this mapper doesn't want to modify the result.
- void set_previous_mapper(HostMapper* mapper) {
- previous_mapper_ = mapper;
- }
-
- scoped_refptr<HostMapper> previous_mapper_;
-};
-
-#ifdef UNIT_TEST
-// This function is designed to allow unit tests to override the behavior of
-// HostResolver. For example, a HostMapper instance can force all hostnames
-// to map to a fixed IP address such as 127.0.0.1.
-//
-// The previously set HostMapper (or NULL if there was none) is returned.
-//
-// NOTE: This function is not thread-safe, so take care to only call this
-// function while there are no outstanding HostResolver instances.
-//
-// NOTE: In most cases, you should use ScopedHostMapper instead, which is
-// defined in host_resolver_unittest.h
-//
-HostMapper* SetHostMapper(HostMapper* host_mapper);
-#endif
+// Creates a HostResolver implementation that queries the underlying system.
+// (Except if a unit-test has changed the global HostResolverProc using
+// ScopedHostResolverProc to intercept requests to the system).
+HostResolver* CreateSystemHostResolver();
} // namespace net
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc
new file mode 100644
index 0000000..2a0eb0f
--- /dev/null
+++ b/net/base/host_resolver_impl.cc
@@ -0,0 +1,483 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/host_resolver_impl.h"
+
+#if defined(OS_WIN)
+#include <ws2tcpip.h>
+#include <wspiapi.h> // Needed for Win2k compat.
+#elif defined(OS_POSIX)
+#include <netdb.h>
+#include <sys/socket.h>
+#endif
+#if defined(OS_LINUX)
+#include <resolv.h>
+#endif
+
+#include "base/compiler_specific.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "base/worker_pool.h"
+#include "net/base/address_list.h"
+#include "net/base/host_resolver_proc.h"
+#include "net/base/net_errors.h"
+
+#if defined(OS_WIN)
+#include "net/base/winsock_init.h"
+#endif
+
+namespace net {
+
+HostResolver* CreateSystemHostResolver() {
+ static const size_t kMaxHostCacheEntries = 100;
+ static const size_t kHostCacheExpirationMs = 60000; // 1 minute.
+ return new HostResolverImpl(
+ NULL, kMaxHostCacheEntries, kHostCacheExpirationMs);
+}
+
+static int ResolveAddrInfo(HostResolverProc* resolver_proc,
+ const std::string& host, AddressList* out) {
+ if (resolver_proc) {
+ // Use the custom procedure.
+ return resolver_proc->Resolve(host, out);
+ } else {
+ // Use the system procedure (getaddrinfo).
+ return SystemHostResolverProc(host, out);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+class HostResolverImpl::Request {
+ public:
+ Request(int id, const RequestInfo& info, CompletionCallback* callback,
+ AddressList* addresses)
+ : id_(id), info_(info), job_(NULL), callback_(callback),
+ addresses_(addresses) {}
+
+ // Mark the request as cancelled.
+ void MarkAsCancelled() {
+ job_ = NULL;
+ callback_ = NULL;
+ addresses_ = NULL;
+ }
+
+ bool was_cancelled() const {
+ return callback_ == NULL;
+ }
+
+ void set_job(Job* job) {
+ DCHECK(job != NULL);
+ // Identify which job the request is waiting on.
+ job_ = job;
+ }
+
+ void OnComplete(int error, const AddressList& addrlist) {
+ if (error == OK)
+ addresses_->SetFrom(addrlist, port());
+ callback_->Run(error);
+ }
+
+ int port() const {
+ return info_.port();
+ }
+
+ Job* job() const {
+ return job_;
+ }
+
+ int id() const {
+ return id_;
+ }
+
+ const RequestInfo& info() const {
+ return info_;
+ }
+
+ private:
+ // Unique ID for this request. Used by observers to identify requests.
+ int id_;
+
+ // The request info that started the request.
+ RequestInfo info_;
+
+ // The resolve job (running in worker pool) that this request is dependent on.
+ Job* job_;
+
+ // The user's callback to invoke when the request completes.
+ CompletionCallback* callback_;
+
+ // The address list to save result into.
+ AddressList* addresses_;
+
+ DISALLOW_COPY_AND_ASSIGN(Request);
+};
+
+//-----------------------------------------------------------------------------
+
+// This class represents a request to the worker pool for a "getaddrinfo()"
+// call.
+class HostResolverImpl::Job
+ : public base::RefCountedThreadSafe<HostResolverImpl::Job> {
+ public:
+ Job(HostResolverImpl* resolver, const std::string& host)
+ : host_(host),
+ resolver_(resolver),
+ origin_loop_(MessageLoop::current()),
+ resolver_proc_(resolver->effective_resolver_proc()),
+ error_(OK) {
+ }
+
+ ~Job() {
+ // Free the requests attached to this job.
+ STLDeleteElements(&requests_);
+ }
+
+ // Attaches a request to this job. The job takes ownership of |req| and will
+ // take care to delete it.
+ void AddRequest(Request* req) {
+ req->set_job(this);
+ requests_.push_back(req);
+ }
+
+ // Called from origin loop.
+ void Start() {
+ // Dispatch the job to a worker thread.
+ if (!WorkerPool::PostTask(FROM_HERE,
+ NewRunnableMethod(this, &Job::DoLookup), true)) {
+ NOTREACHED();
+
+ // Since we could be running within Resolve() right now, we can't just
+ // call OnLookupComplete(). Instead we must wait until Resolve() has
+ // returned (IO_PENDING).
+ error_ = ERR_UNEXPECTED;
+ MessageLoop::current()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &Job::OnLookupComplete));
+ }
+ }
+
+ // Cancels the current job. Callable from origin thread.
+ void Cancel() {
+ HostResolver* resolver = resolver_;
+ resolver_ = NULL;
+
+ // Mark the job as cancelled, so when worker thread completes it will
+ // not try to post completion to origin loop.
+ {
+ AutoLock locked(origin_loop_lock_);
+ origin_loop_ = NULL;
+ }
+
+ // We don't have to do anything further to actually cancel the requests
+ // that were attached to this job (since they are unreachable now).
+ // But we will call HostResolverImpl::CancelRequest(Request*) on each one
+ // in order to notify any observers.
+ for (RequestsList::const_iterator it = requests_.begin();
+ it != requests_.end(); ++it) {
+ HostResolverImpl::Request* req = *it;
+ if (!req->was_cancelled())
+ resolver->CancelRequest(req);
+ }
+ }
+
+ // Called from origin thread.
+ bool was_cancelled() const {
+ return resolver_ == NULL;
+ }
+
+ // Called from origin thread.
+ const std::string& host() const {
+ return host_;
+ }
+
+ // Called from origin thread.
+ const RequestsList& requests() const {
+ return requests_;
+ }
+
+ private:
+ void DoLookup() {
+ // Running on the worker thread
+ error_ = ResolveAddrInfo(resolver_proc_, host_, &results_);
+
+ Task* reply = NewRunnableMethod(this, &Job::OnLookupComplete);
+
+ // 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);
+ reply = NULL;
+ }
+ }
+
+ // Does nothing if it got posted.
+ delete reply;
+ }
+
+ // Callback for when DoLookup() completes (runs on origin thread).
+ void OnLookupComplete() {
+ // Should be running on origin loop.
+ // TODO(eroman): this is being hit by URLRequestTest.CancelTest*,
+ // because MessageLoop::current() == NULL.
+ //DCHECK_EQ(origin_loop_, MessageLoop::current());
+ DCHECK(error_ || results_.head());
+
+ if (was_cancelled())
+ return;
+
+ DCHECK(!requests_.empty());
+
+ // Use the port number of the first request.
+ if (error_ == OK)
+ results_.SetPort(requests_[0]->port());
+
+ resolver_->OnJobComplete(this, error_, results_);
+ }
+
+ // Set on the origin thread, read on the worker thread.
+ std::string host_;
+
+ // Only used on the origin thread (where Resolve was called).
+ HostResolverImpl* resolver_;
+ RequestsList requests_; // The requests waiting on this job.
+
+ // Used to post ourselves onto the origin thread.
+ Lock origin_loop_lock_;
+ MessageLoop* origin_loop_;
+
+ // Hold an owning reference to the HostResolverProc that we are going to use.
+ // This may not be the current resolver procedure by the time we call
+ // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
+ // reference ensures that it remains valid until we are done.
+ scoped_refptr<HostResolverProc> resolver_proc_;
+
+ // Assigned on the worker thread, read on the origin thread.
+ int error_;
+ AddressList results_;
+
+ DISALLOW_COPY_AND_ASSIGN(Job);
+};
+
+//-----------------------------------------------------------------------------
+
+HostResolverImpl::HostResolverImpl(HostResolverProc* resolver_proc,
+ int max_cache_entries,
+ int cache_duration_ms)
+ : cache_(max_cache_entries, cache_duration_ms), next_request_id_(0),
+ resolver_proc_(resolver_proc), shutdown_(false) {
+#if defined(OS_WIN)
+ EnsureWinsockInit();
+#endif
+}
+
+HostResolverImpl::~HostResolverImpl() {
+ // Cancel the outstanding jobs. Those jobs may contain several attached
+ // requests, which will also be cancelled.
+ for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
+ it->second->Cancel();
+
+ // In case we are being deleted during the processing of a callback.
+ if (cur_completing_job_)
+ cur_completing_job_->Cancel();
+}
+
+// TODO(eroman): Don't create cache entries for hostnames which are simply IP
+// address literals.
+int HostResolverImpl::Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req) {
+ if (shutdown_)
+ return ERR_UNEXPECTED;
+
+ // Choose a unique ID number for observers to see.
+ int request_id = next_request_id_++;
+
+ // Notify registered observers.
+ NotifyObserversStartRequest(request_id, info);
+
+ // If we have an unexpired cache entry, use it.
+ if (info.allow_cached_response()) {
+ const HostCache::Entry* cache_entry = cache_.Lookup(
+ info.hostname(), base::TimeTicks::Now());
+ if (cache_entry) {
+ addresses->SetFrom(cache_entry->addrlist, info.port());
+ int error = cache_entry->error;
+
+ // Notify registered observers.
+ NotifyObserversFinishRequest(request_id, info, error);
+
+ return error;
+ }
+ }
+
+ // If no callback was specified, do a synchronous resolution.
+ if (!callback) {
+ AddressList addrlist;
+ int error = ResolveAddrInfo(
+ effective_resolver_proc(), info.hostname(), &addrlist);
+ if (error == OK) {
+ addrlist.SetPort(info.port());
+ *addresses = addrlist;
+ }
+
+ // Write to cache.
+ cache_.Set(info.hostname(), error, addrlist, base::TimeTicks::Now());
+
+ // Notify registered observers.
+ NotifyObserversFinishRequest(request_id, info, error);
+
+ return error;
+ }
+
+ // Create a handle for this request, and pass it back to the user if they
+ // asked for it (out_req != NULL).
+ Request* req = new Request(request_id, info, callback, addresses);
+ if (out_req)
+ *out_req = reinterpret_cast<RequestHandle>(req);
+
+ // Next we need to attach our request to a "job". This job is responsible for
+ // calling "getaddrinfo(hostname)" on a worker thread.
+ scoped_refptr<Job> job;
+
+ // If there is already an outstanding job to resolve |info.hostname()|, use
+ // it. This prevents starting concurrent resolves for the same hostname.
+ job = FindOutstandingJob(info.hostname());
+ if (job) {
+ job->AddRequest(req);
+ } else {
+ // Create a new job for this request.
+ job = new Job(this, info.hostname());
+ job->AddRequest(req);
+ AddOutstandingJob(job);
+ // TODO(eroman): Bound the total number of concurrent jobs.
+ // http://crbug.com/9598
+ job->Start();
+ }
+
+ // Completion happens during OnJobComplete(Job*).
+ return ERR_IO_PENDING;
+}
+
+// See OnJobComplete(Job*) for why it is important not to clean out
+// cancelled requests from Job::requests_.
+void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
+ Request* req = reinterpret_cast<Request*>(req_handle);
+ DCHECK(req);
+ DCHECK(req->job());
+ // NULL out the fields of req, to mark it as cancelled.
+ req->MarkAsCancelled();
+ NotifyObserversCancelRequest(req->id(), req->info());
+}
+
+void HostResolverImpl::AddObserver(Observer* observer) {
+ observers_.push_back(observer);
+}
+
+void HostResolverImpl::RemoveObserver(Observer* observer) {
+ ObserversList::iterator it =
+ std::find(observers_.begin(), observers_.end(), observer);
+
+ // Observer must exist.
+ DCHECK(it != observers_.end());
+
+ observers_.erase(it);
+}
+
+void HostResolverImpl::Shutdown() {
+ shutdown_ = true;
+
+ // Cancel the outstanding jobs.
+ for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
+ it->second->Cancel();
+ jobs_.clear();
+}
+
+void HostResolverImpl::AddOutstandingJob(Job* job) {
+ scoped_refptr<Job>& found_job = jobs_[job->host()];
+ DCHECK(!found_job);
+ found_job = job;
+}
+
+HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(
+ const std::string& hostname) {
+ JobMap::iterator it = jobs_.find(hostname);
+ if (it != jobs_.end())
+ return it->second;
+ return NULL;
+}
+
+void HostResolverImpl::RemoveOutstandingJob(Job* job) {
+ JobMap::iterator it = jobs_.find(job->host());
+ DCHECK(it != jobs_.end());
+ DCHECK_EQ(it->second.get(), job);
+ jobs_.erase(it);
+}
+
+void HostResolverImpl::OnJobComplete(Job* job,
+ int error,
+ const AddressList& addrlist) {
+ RemoveOutstandingJob(job);
+
+ // Write result to the cache.
+ cache_.Set(job->host(), error, addrlist, base::TimeTicks::Now());
+
+ // Make a note that we are executing within OnJobComplete() in case the
+ // HostResolver is deleted by a callback invocation.
+ DCHECK(!cur_completing_job_);
+ cur_completing_job_ = job;
+
+ // Complete all of the requests that were attached to the job.
+ for (RequestsList::const_iterator it = job->requests().begin();
+ it != job->requests().end(); ++it) {
+ Request* req = *it;
+ if (!req->was_cancelled()) {
+ DCHECK_EQ(job, req->job());
+
+ // Notify registered observers.
+ NotifyObserversFinishRequest(req->id(), req->info(), error);
+
+ req->OnComplete(error, addrlist);
+
+ // Check if the job was cancelled as a result of running the callback.
+ // (Meaning that |this| was deleted).
+ if (job->was_cancelled())
+ return;
+ }
+ }
+
+ cur_completing_job_ = NULL;
+}
+
+void HostResolverImpl::NotifyObserversStartRequest(int request_id,
+ const RequestInfo& info) {
+ for (ObserversList::iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ (*it)->OnStartResolution(request_id, info);
+ }
+}
+
+void HostResolverImpl::NotifyObserversFinishRequest(int request_id,
+ const RequestInfo& info,
+ int error) {
+ bool was_resolved = error == OK;
+ for (ObserversList::iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
+ }
+}
+
+void HostResolverImpl::NotifyObserversCancelRequest(int request_id,
+ const RequestInfo& info) {
+ for (ObserversList::iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ (*it)->OnCancelResolution(request_id, info);
+ }
+}
+
+} // namespace net
diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h
new file mode 100644
index 0000000..6ece456
--- /dev/null
+++ b/net/base/host_resolver_impl.h
@@ -0,0 +1,136 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_HOST_RESOLVER_IMPL_H_
+#define NET_BASE_HOST_RESOLVER_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "net/base/host_cache.h"
+#include "net/base/host_resolver.h"
+#include "net/base/host_resolver_proc.h"
+
+namespace net {
+
+// For each hostname that is requested, HostResolver creates a
+// HostResolverImpl::Job. This job gets dispatched to a thread in the global
+// WorkerPool, where it runs SystemHostResolverProc(). If requests for that same
+// host are made while the job is already outstanding, then they are attached
+// to the existing job rather than creating a new one. This avoids doing
+// parallel resolves for the same host.
+//
+// The way these classes fit together is illustrated by:
+//
+//
+// +----------- HostResolverImpl -------------+
+// | | |
+// Job Job Job
+// (for host1) (for host2) (for hostX)
+// / | | / | | / | |
+// Request ... Request Request ... Request Request ... Request
+// (port1) (port2) (port3) (port4) (port5) (portX)
+//
+//
+// When a HostResolverImpl::Job finishes its work in the threadpool, the
+// callbacks of each waiting request are run on the origin thread.
+//
+// Thread safety: This class is not threadsafe, and must only be called
+// from one thread!
+//
+class HostResolverImpl : public HostResolver {
+ public:
+ // Creates a HostResolver that caches up to |max_cache_entries| for
+ // |cache_duration_ms| milliseconds. |resolver_proc| is used to perform
+ // the actual resolves; it must be 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,
+ int max_cache_entries,
+ int cache_duration_ms);
+
+ // If any completion callbacks are pending when the resolver is destroyed,
+ // the host resolutions are cancelled, and the completion callbacks will not
+ // be called.
+ virtual ~HostResolverImpl();
+
+ // HostResolver methods:
+ virtual int Resolve(const RequestInfo& info, AddressList* addresses,
+ CompletionCallback* callback, RequestHandle* out_req);
+ virtual void CancelRequest(RequestHandle req);
+ virtual void AddObserver(Observer* observer);
+ virtual void RemoveObserver(Observer* observer);
+
+ // TODO(eroman): temp hack for http://crbug.com/15513
+ virtual void Shutdown();
+
+ private:
+ class Job;
+ class Request;
+ typedef std::vector<Request*> RequestsList;
+ typedef base::hash_map<std::string, scoped_refptr<Job> > JobMap;
+ typedef std::vector<Observer*> ObserversList;
+
+ // Returns the HostResolverProc to use for this instance.
+ HostResolverProc* effective_resolver_proc() const {
+ return resolver_proc_ ?
+ resolver_proc_.get() : HostResolverProc::GetDefault();
+ }
+
+ // Adds a job to outstanding jobs list.
+ void AddOutstandingJob(Job* job);
+
+ // Returns the outstanding job for |hostname|, or NULL if there is none.
+ Job* FindOutstandingJob(const std::string& hostname);
+
+ // Removes |job| from the outstanding jobs list.
+ void RemoveOutstandingJob(Job* job);
+
+ // Callback for when |job| has completed with |error| and |addrlist|.
+ void OnJobComplete(Job* job, int error, const AddressList& addrlist);
+
+ // Notify all observers of the start of a resolve request.
+ void NotifyObserversStartRequest(int request_id,
+ const RequestInfo& info);
+
+ // Notify all observers of the completion of a resolve request.
+ void NotifyObserversFinishRequest(int request_id,
+ const RequestInfo& info,
+ int error);
+
+ // Notify all observers of the cancellation of a resolve request.
+ void NotifyObserversCancelRequest(int request_id,
+ const RequestInfo& info);
+
+ // Cache of host resolution results.
+ HostCache cache_;
+
+ // Map from hostname to outstanding job.
+ JobMap jobs_;
+
+ // The job that OnJobComplete() is currently processing (needed in case
+ // HostResolver gets deleted from within the callback).
+ scoped_refptr<Job> cur_completing_job_;
+
+ // The observers to notify when a request starts/ends.
+ ObserversList observers_;
+
+ // Monotonically increasing ID number to assign to the next request.
+ // Observers are the only consumers of this ID number.
+ int next_request_id_;
+
+ // The procedure to use for resolving host names. This will be NULL, except
+ // in the case of unit-tests which inject custom host resolving behaviors.
+ scoped_refptr<HostResolverProc> resolver_proc_;
+
+ // TODO(eroman): temp hack for http://crbug.com/15513
+ bool shutdown_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostResolverImpl);
+};
+
+} // namespace net
+
+#endif // NET_BASE_HOST_RESOLVER_IMPL_H_
diff --git a/net/base/host_resolver_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index 32b6af6..0ff345c 100644
--- a/net/base/host_resolver_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/host_resolver.h"
+#include "net/base/host_resolver_impl.h"
#if defined(OS_WIN)
#include <ws2tcpip.h>
@@ -18,39 +18,43 @@
#include "base/ref_counted.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::RuleBasedHostMapper;
-using net::ScopedHostMapper;
-using net::WaitingHostMapper;
+using net::HostResolverImpl;
+using net::RuleBasedHostResolverProc;
+using net::WaitingHostResolverProc;
// TODO(eroman):
// - Test mixing async with sync (in particular how does sync update the
// cache while an async is already pending).
namespace {
+static const int kMaxCacheEntries = 100;
+static const int kMaxCacheAgeMs = 60000;
-// A variant of WaitingHostMapper that pushes each host mapped into a list.
+// A variant of WaitingHostResolverProc that pushes each host mapped into a
+// list.
// (and uses a manual-reset event rather than auto-reset).
-class CapturingHostMapper : public net::HostMapper {
+class CapturingHostResolverProc : public net::HostResolverProc {
public:
- CapturingHostMapper() : event_(true, false) {
+ explicit CapturingHostResolverProc(HostResolverProc* previous)
+ : net::HostResolverProc(previous), event_(true, false) {
}
void Signal() {
event_.Signal();
}
- virtual std::string Map(const std::string& host) {
+ virtual int Resolve(const std::string& host, net::AddressList* addrlist) {
event_.Wait();
{
AutoLock l(lock_);
capture_list_.push_back(host);
}
- return MapUsingPrevious(host);
+ return ResolveUsingPrevious(host, addrlist);
}
std::vector<std::string> GetCaptureList() const {
@@ -134,7 +138,7 @@ class ResolveRequest {
// The request details.
net::HostResolver::RequestInfo info_;
- net::HostResolver::Request* req_;
+ net::HostResolver::RequestHandle req_;
// The result of the resolve.
int result_;
@@ -150,18 +154,18 @@ class ResolveRequest {
DISALLOW_COPY_AND_ASSIGN(ResolveRequest);
};
-class HostResolverTest : public testing::Test {
+class HostResolverImplTest : public testing::Test {
public:
- HostResolverTest()
+ HostResolverImplTest()
: callback_called_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(
- callback_(this, &HostResolverTest::OnLookupFinished)) {
+ callback_(this, &HostResolverImplTest::OnLookupFinished)) {
}
protected:
bool callback_called_;
int callback_result_;
- net::CompletionCallbackImpl<HostResolverTest> callback_;
+ net::CompletionCallbackImpl<HostResolverImplTest> callback_;
private:
void OnLookupFinished(int result) {
@@ -171,14 +175,16 @@ class HostResolverTest : public testing::Test {
}
};
-TEST_F(HostResolverTest, SynchronousLookup) {
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+TEST_F(HostResolverImplTest, SynchronousLookup) {
net::AddressList adrlist;
const int kPortnum = 80;
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper();
- mapper->AddRule("just.testing", "192.168.1.42");
- ScopedHostMapper scoped_mapper(mapper.get());
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
+ new RuleBasedHostResolverProc(NULL);
+ resolver_proc->AddRule("just.testing", "192.168.1.42");
+
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::HostResolver::RequestInfo info("just.testing", kPortnum);
int err = host_resolver->Resolve(info, &adrlist, NULL, NULL);
@@ -194,14 +200,16 @@ TEST_F(HostResolverTest, SynchronousLookup) {
EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr);
}
-TEST_F(HostResolverTest, AsynchronousLookup) {
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+TEST_F(HostResolverImplTest, AsynchronousLookup) {
net::AddressList adrlist;
const int kPortnum = 80;
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper();
- mapper->AddRule("just.testing", "192.168.1.42");
- ScopedHostMapper scoped_mapper(mapper.get());
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
+ new RuleBasedHostResolverProc(NULL);
+ resolver_proc->AddRule("just.testing", "192.168.1.42");
+
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::HostResolver::RequestInfo info("just.testing", kPortnum);
int err = host_resolver->Resolve(info, &adrlist, &callback_, NULL);
@@ -222,12 +230,13 @@ TEST_F(HostResolverTest, AsynchronousLookup) {
EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr);
}
-TEST_F(HostResolverTest, CanceledAsynchronousLookup) {
- scoped_refptr<WaitingHostMapper> mapper = new WaitingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, CanceledAsynchronousLookup) {
+ scoped_refptr<WaitingHostResolverProc> resolver_proc =
+ new WaitingHostResolverProc(NULL);
{
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::AddressList adrlist;
const int kPortnum = 80;
@@ -242,19 +251,20 @@ TEST_F(HostResolverTest, CanceledAsynchronousLookup) {
MessageLoop::current()->Run();
}
- mapper->Signal();
+ resolver_proc->Signal();
EXPECT_FALSE(callback_called_);
}
-TEST_F(HostResolverTest, NumericIPv4Address) {
+TEST_F(HostResolverImplTest, NumericIPv4Address) {
// Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in.
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper();
- mapper->AllowDirectLookup("*");
- ScopedHostMapper scoped_mapper(mapper.get());
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
+ new RuleBasedHostResolverProc(NULL);
+ resolver_proc->AllowDirectLookup("*");
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::AddressList adrlist;
const int kPortnum = 5555;
net::HostResolver::RequestInfo info("127.1.2.3", kPortnum);
@@ -271,14 +281,15 @@ TEST_F(HostResolverTest, NumericIPv4Address) {
EXPECT_TRUE(htonl(0x7f010203) == sa_in->sin_addr.s_addr);
}
-TEST_F(HostResolverTest, NumericIPv6Address) {
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper();
- mapper->AllowDirectLookup("*");
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, NumericIPv6Address) {
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
+ new RuleBasedHostResolverProc(NULL);
+ resolver_proc->AllowDirectLookup("*");
// Resolve a plain IPv6 address. Don't worry about [brackets], because
// the caller should have removed them.
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::AddressList adrlist;
const int kPortnum = 5555;
net::HostResolver::RequestInfo info("2001:db8::1", kPortnum);
@@ -307,12 +318,13 @@ TEST_F(HostResolverTest, NumericIPv6Address) {
}
}
-TEST_F(HostResolverTest, EmptyHost) {
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper();
- mapper->AllowDirectLookup("*");
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, EmptyHost) {
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
+ new RuleBasedHostResolverProc(NULL);
+ resolver_proc->AllowDirectLookup("*");
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
net::AddressList adrlist;
const int kPortnum = 5555;
net::HostResolver::RequestInfo info("", kPortnum);
@@ -320,13 +332,13 @@ TEST_F(HostResolverTest, EmptyHost) {
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, err);
}
-// Helper class used by HostResolverTest.DeDupeRequests. It receives request
+// Helper class used by HostResolverImplTest.DeDupeRequests. It receives request
// completion notifications for all the resolves, so it can tally up and
// determine when we are done.
class DeDupeRequestsVerifier : public ResolveRequest::Delegate {
public:
- explicit DeDupeRequestsVerifier(CapturingHostMapper* mapper)
- : count_a_(0), count_b_(0), mapper_(mapper) {}
+ explicit DeDupeRequestsVerifier(CapturingHostResolverProc* resolver_proc)
+ : count_a_(0), count_b_(0), resolver_proc_(resolver_proc) {}
// The test does 5 resolves (which can complete in any order).
virtual void OnCompleted(ResolveRequest* resolve) {
@@ -348,9 +360,9 @@ class DeDupeRequestsVerifier : public ResolveRequest::Delegate {
EXPECT_EQ(2, count_a_);
EXPECT_EQ(3, count_b_);
- // The mapper should have been called only twice -- once with "a", once
- // with "b".
- std::vector<std::string> capture_list = mapper_->GetCaptureList();
+ // The resolver_proc should have been called only twice -- once with "a",
+ // once with "b".
+ std::vector<std::string> capture_list = resolver_proc_->GetCaptureList();
EXPECT_EQ(2U, capture_list.size());
// End this test, we are done.
@@ -361,24 +373,25 @@ class DeDupeRequestsVerifier : public ResolveRequest::Delegate {
private:
int count_a_;
int count_b_;
- CapturingHostMapper* mapper_;
+ CapturingHostResolverProc* resolver_proc_;
DISALLOW_COPY_AND_ASSIGN(DeDupeRequestsVerifier);
};
-TEST_F(HostResolverTest, DeDupeRequests) {
- // Use a capturing mapper, since the verifier needs to know what calls
- // reached Map(). Also, the capturing mapper is initially blocked.
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, DeDupeRequests) {
+ // Use a capturing resolver_proc, since the verifier needs to know what calls
+ // reached Resolve(). Also, the capturing resolver_proc is initially blocked.
+ scoped_refptr<CapturingHostResolverProc> resolver_proc =
+ new CapturingHostResolverProc(NULL);
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
- DeDupeRequestsVerifier verifier(mapper.get());
+ DeDupeRequestsVerifier verifier(resolver_proc.get());
- // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is
+ // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is
// blocked, these should all pile up until we signal it.
ResolveRequest req1(host_resolver, "a", 80, &verifier);
@@ -388,13 +401,13 @@ TEST_F(HostResolverTest, DeDupeRequests) {
ResolveRequest req5(host_resolver, "b", 83, &verifier);
// Ready, Set, GO!!!
- mapper->Signal();
+ resolver_proc->Signal();
// |verifier| will send quit message once all the requests have finished.
MessageLoop::current()->Run();
}
-// Helper class used by HostResolverTest.CancelMultipleRequests.
+// Helper class used by HostResolverImplTest.CancelMultipleRequests.
class CancelMultipleRequestsVerifier : public ResolveRequest::Delegate {
public:
CancelMultipleRequestsVerifier() {}
@@ -415,19 +428,21 @@ class CancelMultipleRequestsVerifier : public ResolveRequest::Delegate {
DISALLOW_COPY_AND_ASSIGN(CancelMultipleRequestsVerifier);
};
-TEST_F(HostResolverTest, CancelMultipleRequests) {
- // Use a capturing mapper, since the verifier needs to know what calls
- // reached Map(). Also, the capturing mapper is initially blocked.
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, CancelMultipleRequests) {
+ // Use a capturing resolver_proc, since the verifier needs to know what calls
+ // reached Resolver(). Also, the capturing resolver_proc is initially
+ // blocked.
+ scoped_refptr<CapturingHostResolverProc> resolver_proc =
+ new CapturingHostResolverProc(NULL);
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
CancelMultipleRequestsVerifier verifier;
- // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is
+ // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is
// blocked, these should all pile up until we signal it.
ResolveRequest req1(host_resolver, "a", 80, &verifier);
@@ -443,13 +458,13 @@ TEST_F(HostResolverTest, CancelMultipleRequests) {
req5.Cancel();
// Ready, Set, GO!!!
- mapper->Signal();
+ resolver_proc->Signal();
// |verifier| will send quit message once all the requests have finished.
MessageLoop::current()->Run();
}
-// Helper class used by HostResolverTest.CancelWithinCallback.
+// Helper class used by HostResolverImplTest.CancelWithinCallback.
class CancelWithinCallbackVerifier : public ResolveRequest::Delegate {
public:
CancelWithinCallbackVerifier()
@@ -500,19 +515,21 @@ class CancelWithinCallbackVerifier : public ResolveRequest::Delegate {
DISALLOW_COPY_AND_ASSIGN(CancelWithinCallbackVerifier);
};
-TEST_F(HostResolverTest, CancelWithinCallback) {
- // Use a capturing mapper, since the verifier needs to know what calls
- // reached Map(). Also, the capturing mapper is initially blocked.
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, CancelWithinCallback) {
+ // Use a capturing resolver_proc, since the verifier needs to know what calls
+ // reached Resolver(). Also, the capturing resolver_proc is initially
+ // blocked.
+ scoped_refptr<CapturingHostResolverProc> resolver_proc =
+ new CapturingHostResolverProc(NULL);
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
CancelWithinCallbackVerifier verifier;
- // Start 4 requests, duplicating hosts "a". Since the mapper is
+ // Start 4 requests, duplicating hosts "a". Since the resolver_proc is
// blocked, these should all pile up until we signal it.
ResolveRequest req1(host_resolver, "a", 80, &verifier);
@@ -524,13 +541,13 @@ TEST_F(HostResolverTest, CancelWithinCallback) {
verifier.SetRequestsToCancel(&req2, &req3);
// Ready, Set, GO!!!
- mapper->Signal();
+ resolver_proc->Signal();
// |verifier| will send quit message once all the requests have finished.
MessageLoop::current()->Run();
}
-// Helper class used by HostResolverTest.DeleteWithinCallback.
+// Helper class used by HostResolverImplTest.DeleteWithinCallback.
class DeleteWithinCallbackVerifier : public ResolveRequest::Delegate {
public:
// |host_resolver| is the resolver that the the resolve requests were started
@@ -556,19 +573,21 @@ class DeleteWithinCallbackVerifier : public ResolveRequest::Delegate {
DISALLOW_COPY_AND_ASSIGN(DeleteWithinCallbackVerifier);
};
-TEST_F(HostResolverTest, DeleteWithinCallback) {
- // Use a capturing mapper, since the verifier needs to know what calls
- // reached Map(). Also, the capturing mapper is initially blocked.
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, DeleteWithinCallback) {
+ // Use a capturing resolver_proc, since the verifier needs to know what calls
+ // reached Resolver(). Also, the capturing resolver_proc is initially
+ // blocked.
+ scoped_refptr<CapturingHostResolverProc> resolver_proc =
+ new CapturingHostResolverProc(NULL);
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened. Note that the verifier holds the
// only reference to |host_resolver|, so it can delete it within callback.
- net::HostResolver* host_resolver = new net::HostResolver;
+ net::HostResolver* host_resolver =
+ new HostResolverImpl(resolver_proc, kMaxCacheEntries, kMaxCacheAgeMs);
DeleteWithinCallbackVerifier verifier(host_resolver);
- // Start 4 requests, duplicating hosts "a". Since the mapper is
+ // Start 4 requests, duplicating hosts "a". Since the resolver_proc is
// blocked, these should all pile up until we signal it.
ResolveRequest req1(host_resolver, "a", 80, &verifier);
@@ -577,13 +596,13 @@ TEST_F(HostResolverTest, DeleteWithinCallback) {
ResolveRequest req4(host_resolver, "a", 83, &verifier);
// Ready, Set, GO!!!
- mapper->Signal();
+ resolver_proc->Signal();
// |verifier| will send quit message once all the requests have finished.
MessageLoop::current()->Run();
}
-// Helper class used by HostResolverTest.StartWithinCallback.
+// Helper class used by HostResolverImplTest.StartWithinCallback.
class StartWithinCallbackVerifier : public ResolveRequest::Delegate {
public:
StartWithinCallbackVerifier() : num_requests_(0) {}
@@ -609,20 +628,22 @@ class StartWithinCallbackVerifier : public ResolveRequest::Delegate {
DISALLOW_COPY_AND_ASSIGN(StartWithinCallbackVerifier);
};
-TEST_F(HostResolverTest, StartWithinCallback) {
- // Use a capturing mapper, since the verifier needs to know what calls
- // reached Map(). Also, the capturing mapper is initially blocked.
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper();
- ScopedHostMapper scoped_mapper(mapper.get());
+TEST_F(HostResolverImplTest, StartWithinCallback) {
+ // Use a capturing resolver_proc, since the verifier needs to know what calls
+ // reached Resolver(). Also, the capturing resolver_proc is initially
+ // blocked.
+ scoped_refptr<CapturingHostResolverProc> resolver_proc =
+ new CapturingHostResolverProc(NULL);
// Turn off caching for this host resolver.
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver(0, 0));
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(resolver_proc, 0, 0));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
StartWithinCallbackVerifier verifier;
- // Start 4 requests, duplicating hosts "a". Since the mapper is
+ // Start 4 requests, duplicating hosts "a". Since the resolver_proc is
// blocked, these should all pile up until we signal it.
ResolveRequest req1(host_resolver, "a", 80, &verifier);
@@ -631,13 +652,13 @@ TEST_F(HostResolverTest, StartWithinCallback) {
ResolveRequest req4(host_resolver, "a", 83, &verifier);
// Ready, Set, GO!!!
- mapper->Signal();
+ resolver_proc->Signal();
// |verifier| will send quit message once all the requests have finished.
MessageLoop::current()->Run();
}
-// Helper class used by HostResolverTest.BypassCache.
+// Helper class used by HostResolverImplTest.BypassCache.
class BypassCacheVerifier : public ResolveRequest::Delegate {
public:
BypassCacheVerifier() {}
@@ -679,8 +700,9 @@ class BypassCacheVerifier : public ResolveRequest::Delegate {
DISALLOW_COPY_AND_ASSIGN(BypassCacheVerifier);
};
-TEST_F(HostResolverTest, BypassCache) {
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+TEST_F(HostResolverImplTest, BypassCache) {
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(NULL, kMaxCacheEntries, kMaxCacheAgeMs));
// The class will receive callbacks for when each resolve completes. It
// checks that the right things happened.
@@ -762,8 +784,9 @@ class CapturingObserver : public net::HostResolver::Observer {
// Test that registering, unregistering, and notifying of observers works.
// Does not test the cancellation notification since all resolves are
// synchronous.
-TEST_F(HostResolverTest, Observers) {
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+TEST_F(HostResolverImplTest, Observers) {
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(NULL, kMaxCacheEntries, kMaxCacheAgeMs));
CapturingObserver observer;
@@ -829,11 +852,12 @@ TEST_F(HostResolverTest, Observers) {
// cancelled. There are two ways to cancel a request:
// (1) Delete the HostResolver while job is outstanding.
// (2) Call HostResolver::CancelRequest() while a request is outstanding.
-TEST_F(HostResolverTest, CancellationObserver) {
+TEST_F(HostResolverImplTest, CancellationObserver) {
CapturingObserver observer;
{
// Create a host resolver and attach an observer.
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ new HostResolverImpl(NULL, kMaxCacheEntries, kMaxCacheAgeMs));
host_resolver->AddObserver(&observer);
TestCompletionCallback callback;
@@ -844,7 +868,7 @@ TEST_F(HostResolverTest, CancellationObserver) {
// Start an async resolve for (host1:70).
net::HostResolver::RequestInfo info1("host1", 70);
- net::HostResolver::Request* req = NULL;
+ net::HostResolver::RequestHandle req = NULL;
net::AddressList addrlist;
int rv = host_resolver->Resolve(info1, &addrlist, &callback, &req);
EXPECT_EQ(net::ERR_IO_PENDING, rv);
@@ -857,7 +881,7 @@ TEST_F(HostResolverTest, CancellationObserver) {
EXPECT_TRUE(observer.start_log[0] ==
CapturingObserver::StartOrCancelEntry(0, info1));
- // Cancel the request (host mapper is blocked so it cant be finished yet).
+ // Cancel the request.
host_resolver->CancelRequest(req);
EXPECT_EQ(1U, observer.start_log.size());
diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc
new file mode 100644
index 0000000..585a33e
--- /dev/null
+++ b/net/base/host_resolver_proc.cc
@@ -0,0 +1,180 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/host_resolver_proc.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <ws2tcpip.h>
+#include <wspiapi.h> // Needed for Win2k compat.
+#elif defined(OS_POSIX)
+#include <netdb.h>
+#include <sys/socket.h>
+#endif
+#if defined(OS_LINUX)
+#include <resolv.h>
+#endif
+
+#include "base/logging.h"
+#include "base/time.h"
+#include "net/base/address_list.h"
+#include "net/base/net_errors.h"
+
+#if defined(OS_LINUX)
+#include "base/singleton.h"
+#include "base/thread_local_storage.h"
+#endif
+
+namespace net {
+
+HostResolverProc* HostResolverProc::default_proc_ = NULL;
+
+HostResolverProc::HostResolverProc(HostResolverProc* previous) {
+ set_previous_proc(previous);
+
+ // Implicitly fall-back to the global default procedure.
+ if (!previous)
+ set_previous_proc(default_proc_);
+}
+
+// static
+HostResolverProc* HostResolverProc::SetDefault(HostResolverProc* proc) {
+ HostResolverProc* old = default_proc_;
+ default_proc_ = proc;
+ return old;
+}
+
+// static
+HostResolverProc* HostResolverProc::GetDefault() {
+ return default_proc_;
+}
+
+int HostResolverProc::ResolveUsingPrevious(const std::string& host,
+ AddressList* addrlist) {
+ if (previous_proc_)
+ return previous_proc_->Resolve(host, addrlist);
+
+ // Final fallback is the system resolver.
+ return SystemHostResolverProc(host, addrlist);
+}
+
+#if defined(OS_LINUX)
+// On Linux changes to /etc/resolv.conf can go unnoticed thus resulting in
+// DNS queries failing either because nameservers are unknown on startup
+// or because nameserver info has changed as a result of e.g. connecting to
+// a new network. Some distributions patch glibc to stat /etc/resolv.conf
+// to try to automatically detect such changes but these patches are not
+// universal and even patched systems such as Jaunty appear to need calls
+// to res_ninit to reload the nameserver information in different threads.
+//
+// We adopt the Mozilla solution here which is to call res_ninit when
+// lookups fail and to rate limit the reloading to once per second per
+// thread.
+
+// Keep a timer per calling thread to rate limit the calling of res_ninit.
+class DnsReloadTimer {
+ public:
+ DnsReloadTimer() {
+ tls_index_.Initialize(SlotReturnFunction);
+ }
+
+ ~DnsReloadTimer() { }
+
+ // Check if the timer for the calling thread has expired. When no
+ // timer exists for the calling thread, create one.
+ bool Expired() {
+ const base::TimeDelta kRetryTime = base::TimeDelta::FromSeconds(1);
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks* timer_ptr =
+ static_cast<base::TimeTicks*>(tls_index_.Get());
+
+ if (!timer_ptr) {
+ timer_ptr = new base::TimeTicks();
+ *timer_ptr = base::TimeTicks::Now();
+ tls_index_.Set(timer_ptr);
+ // Return true to reload dns info on the first call for each thread.
+ return true;
+ } else if (now - *timer_ptr > kRetryTime) {
+ *timer_ptr = now;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // Free the allocated timer.
+ static void SlotReturnFunction(void* data) {
+ base::TimeTicks* tls_data = static_cast<base::TimeTicks*>(data);
+ delete tls_data;
+ }
+
+ private:
+ // We use thread local storage to identify which base::TimeTicks to
+ // interact with.
+ static ThreadLocalStorage::Slot tls_index_ ;
+
+ DISALLOW_COPY_AND_ASSIGN(DnsReloadTimer);
+};
+
+// A TLS slot to the TimeTicks for the current thread.
+// static
+ThreadLocalStorage::Slot DnsReloadTimer::tls_index_(base::LINKER_INITIALIZED);
+
+#endif // defined(OS_LINUX)
+
+int SystemHostResolverProc(const std::string& host, AddressList* addrlist) {
+ struct addrinfo* ai = NULL;
+ struct addrinfo hints = {0};
+ hints.ai_family = AF_UNSPEC;
+
+#if defined(OS_WIN)
+ // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
+ //
+ // The following comment in <winsock2.h> is the best documentation I found
+ // on AI_ADDRCONFIG for Windows:
+ // Flags used in "hints" argument to getaddrinfo()
+ // - AI_ADDRCONFIG is supported starting with Vista
+ // - default is AI_ADDRCONFIG ON whether the flag is set or not
+ // because the performance penalty in not having ADDRCONFIG in
+ // the multi-protocol stack environment is severe;
+ // this defaulting may be disabled by specifying the AI_ALL flag,
+ // in that case AI_ADDRCONFIG must be EXPLICITLY specified to
+ // enable ADDRCONFIG behavior
+ //
+ // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
+ // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
+ // to fail with WSANO_DATA (11004) for "localhost", probably because of the
+ // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
+ // The IPv4 or IPv6 loopback address is not considered a valid global
+ // address.
+ // See http://crbug.com/5234.
+ hints.ai_flags = 0;
+#else
+ hints.ai_flags = AI_ADDRCONFIG;
+#endif
+
+ // Restrict result set to only this socket type to avoid duplicates.
+ hints.ai_socktype = SOCK_STREAM;
+
+ int err = getaddrinfo(host.c_str(), NULL, &hints, &ai);
+#if defined(OS_LINUX)
+ net::DnsReloadTimer* dns_timer = Singleton<net::DnsReloadTimer>::get();
+ // If we fail, re-initialise the resolver just in case there have been any
+ // changes to /etc/resolv.conf and retry. See http://crbug.com/11380 for info.
+ if (err && dns_timer->Expired()) {
+ res_nclose(&_res);
+ if (!res_ninit(&_res))
+ err = getaddrinfo(host.c_str(), NULL, &hints, &ai);
+ }
+#endif
+
+ if (err)
+ return ERR_NAME_NOT_RESOLVED;
+
+ addrlist->Adopt(ai);
+ return OK;
+}
+
+} // namespace net
diff --git a/net/base/host_resolver_proc.h b/net/base/host_resolver_proc.h
new file mode 100644
index 0000000..2690987
--- /dev/null
+++ b/net/base/host_resolver_proc.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_HOST_RESOLVER_PROC_H_
+#define NET_BASE_HOST_RESOLVER_PROC_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+
+namespace net {
+
+class AddressList;
+
+// Interface for a getaddrinfo()-like procedure. This is used by unit-tests
+// to control the underlying resolutions in HostResolverImpl. HostResolverProcs
+// can be chained together; they fallback to the next procedure in the chain
+// by calling ResolveUsingPrevious().
+//
+// Note that implementations of HostResolverProc *MUST BE THREADSAFE*, since
+// the HostResolver implementation using them can be multi-threaded.
+class HostResolverProc : public base::RefCountedThreadSafe<HostResolverProc> {
+ public:
+ explicit HostResolverProc(HostResolverProc* previous);
+ virtual ~HostResolverProc() {}
+
+ // Resolves |host| to an address list. If successful returns OK and fills
+ // |addrlist| with a list of socket addresses. Otherwise returns a
+ // network error code.
+ virtual int Resolve(const std::string& host, AddressList* addrlist) = 0;
+
+ protected:
+ // Asks the fallback procedure (if set) to do the resolve.
+ int ResolveUsingPrevious(const std::string& host, AddressList* addrlist);
+
+ private:
+ friend class HostResolverImpl;
+ friend class MockHostResolver;
+ friend class ScopedDefaultHostResolverProc;
+
+ // Sets the previous procedure in the chain.
+ void set_previous_proc(HostResolverProc* proc) {
+ previous_proc_ = proc;
+ }
+
+ // Sets the default host resolver procedure that is used by HostResolverImpl.
+ // This can be used through ScopedDefaultHostResolverProc to set a catch-all
+ // DNS block in unit-tests (individual tests should use MockHostResolver to
+ // prevent hitting the network).
+ static HostResolverProc* SetDefault(HostResolverProc* proc);
+ static HostResolverProc* GetDefault();
+
+ private:
+ scoped_refptr<HostResolverProc> previous_proc_;
+ static HostResolverProc* default_proc_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostResolverProc);
+};
+
+// Resolves |host| to an address list, using the system's default host resolver.
+// (i.e. this calls out to getaddrinfo()). If successful returns OK and fills
+// |addrlist| with a list of socket addresses. Otherwise returns a
+// network error code.
+int SystemHostResolverProc(const std::string& host, AddressList* addrlist);
+
+} // namespace net
+
+#endif // NET_BASE_HOST_RESOLVER_PROC_H_
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc
new file mode 100644
index 0000000..58ad552
--- /dev/null
+++ b/net/base/mock_host_resolver.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/mock_host_resolver.h"
+
+#include "base/string_util.h"
+#include "base/platform_thread.h"
+#include "base/ref_counted.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+MockHostResolver::MockHostResolver() {
+ Reset(NULL, 0, 0);
+}
+
+int MockHostResolver::Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req) {
+ return impl_->Resolve(info, addresses, callback, out_req);
+}
+
+void MockHostResolver::CancelRequest(RequestHandle req) {
+ impl_->CancelRequest(req);
+}
+
+void MockHostResolver::AddObserver(Observer* observer) {
+ impl_->AddObserver(observer);
+}
+
+void MockHostResolver::RemoveObserver(Observer* observer) {
+ impl_->RemoveObserver(observer);
+}
+
+void MockHostResolver::Shutdown() {
+ impl_->Shutdown();
+}
+
+void MockHostResolver::Reset(HostResolverProc* interceptor,
+ int max_cache_entries,
+ int max_cache_age_ms) {
+ // At the root of the chain, map everything to localhost.
+ scoped_refptr<RuleBasedHostResolverProc> catchall =
+ new RuleBasedHostResolverProc(NULL);
+ catchall->AddRule("*", "127.0.0.1");
+
+ // Next add a rules-based layer the use controls.
+ rules_ = new RuleBasedHostResolverProc(catchall);
+
+ HostResolverProc* proc = rules_;
+
+ // Lastly add the provided interceptor to the front of the chain.
+ if (interceptor) {
+ interceptor->set_previous_proc(proc);
+ proc = interceptor;
+ }
+
+ impl_ = new HostResolverImpl(proc, max_cache_entries, max_cache_age_ms);
+}
+
+//-----------------------------------------------------------------------------
+
+struct RuleBasedHostResolverProc::Rule {
+ std::string host_pattern;
+ std::string replacement;
+ int latency_ms; // In milliseconds.
+ bool direct; // if true, don't mangle hostname and ignore replacement
+ Rule(const std::string& host_pattern, const std::string& replacement)
+ : host_pattern(host_pattern),
+ replacement(replacement),
+ latency_ms(0),
+ direct(false) {}
+ Rule(const std::string& host_pattern, const std::string& replacement,
+ const int latency_ms)
+ : host_pattern(host_pattern),
+ replacement(replacement),
+ latency_ms(latency_ms),
+ direct(false) {}
+ Rule(const std::string& host_pattern, const std::string& replacement,
+ const bool direct)
+ : host_pattern(host_pattern),
+ replacement(replacement),
+ latency_ms(0),
+ direct(direct) {}
+};
+
+RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
+ : HostResolverProc(previous) {
+}
+
+RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
+}
+
+void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
+ const std::string& replacement) {
+ rules_.push_back(Rule(host_pattern, replacement));
+}
+
+void RuleBasedHostResolverProc::AddRuleWithLatency(
+ const std::string& host_pattern,
+ const std::string& replacement, int latency_ms) {
+ rules_.push_back(Rule(host_pattern, replacement, latency_ms));
+}
+
+void RuleBasedHostResolverProc::AllowDirectLookup(const std::string& host) {
+ rules_.push_back(Rule(host, "", true));
+}
+
+void RuleBasedHostResolverProc::AddSimulatedFailure(const std::string& host) {
+ AddRule(host, "");
+}
+
+int RuleBasedHostResolverProc::Resolve(const std::string& host,
+ AddressList* addrlist) {
+ RuleList::iterator r;
+ for (r = rules_.begin(); r != rules_.end(); ++r) {
+ if (MatchPattern(host, r->host_pattern)) {
+ if (r->latency_ms != 0) {
+ PlatformThread::Sleep(r->latency_ms);
+ // Hmm, this seems unecessary.
+ r->latency_ms = 1;
+ }
+ const std::string& effective_host = r->direct ? host : r->replacement;
+ if (effective_host.empty())
+ return ERR_NAME_NOT_RESOLVED;
+ return SystemHostResolverProc(effective_host, addrlist);
+ }
+ }
+ return ResolveUsingPrevious(host, addrlist);
+}
+
+//-----------------------------------------------------------------------------
+
+ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
+ HostResolverProc* proc) : current_proc_(proc) {
+ previous_proc_ = HostResolverProc::SetDefault(current_proc_);
+ current_proc_->set_previous_proc(previous_proc_);
+}
+
+ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
+ HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_);
+ // The lifetimes of multiple instances must be nested.
+ CHECK(old_proc == current_proc_);
+}
+
+void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
+ current_proc_ = proc;
+ previous_proc_ = HostResolverProc::SetDefault(current_proc_);
+ current_proc_->set_previous_proc(previous_proc_);
+}
+
+} // namespace net
diff --git a/net/base/mock_host_resolver.h b/net/base/mock_host_resolver.h
new file mode 100644
index 0000000..ee83105
--- /dev/null
+++ b/net/base/mock_host_resolver.h
@@ -0,0 +1,143 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_MOCK_HOST_RESOLVER_H_
+#define NET_BASE_MOCK_HOST_RESOLVER_H_
+
+#include <list>
+
+#include "base/waitable_event.h"
+#include "net/base/host_resolver_impl.h"
+#include "net/base/host_resolver_proc.h"
+
+namespace net {
+
+class RuleBasedHostResolverProc;
+
+// In most cases, it is important that unit tests avoid making actual DNS
+// queries since the resulting tests can be flaky, especially if the network is
+// unreliable for some reason. To simplify writing tests that avoid making
+// actual DNS queries, pass a MockHostResolver as the HostResolver dependency.
+// The socket addresses returned can be configured using the
+// RuleBasedHostResolverProc:
+//
+// host_resolver->rules()->AddRule("foo.com", "1.2.3.4");
+// host_resolver->rules()->AddRule("bar.com", "2.3.4.5");
+//
+// The above rules define a static mapping from hostnames to IP address
+// literals. The first parameter to AddRule specifies a host pattern to match
+// against, and the second parameter indicates what value should be used to
+// replace the given hostname. So, the following is also supported:
+//
+// host_mapper->AddRule("*.com", "127.0.0.1");
+//
+// Replacement doesn't have to be string representing an IP address. It can
+// re-map one hostname to another as well.
+class MockHostResolver : public HostResolver {
+ public:
+ // Creates a MockHostResolver that does NOT cache entries
+ // (the HostResolverProc will be called for every lookup). If you need
+ // caching behavior, call Reset() with non-zero cache size.
+ MockHostResolver();
+
+ virtual ~MockHostResolver() {}
+
+ // HostResolver methods:
+ virtual int Resolve(const RequestInfo& info, AddressList* addresses,
+ CompletionCallback* callback, RequestHandle* out_req);
+ virtual void CancelRequest(RequestHandle req);
+ virtual void AddObserver(Observer* observer);
+ virtual void RemoveObserver(Observer* observer);
+ // TODO(eroman): temp hack for http://crbug.com/15513
+ virtual void Shutdown();
+
+ RuleBasedHostResolverProc* rules() { return rules_; }
+
+ // Resets the mock.
+ void Reset(HostResolverProc* interceptor,
+ int max_cache_entries,
+ int max_cache_age_ms);
+
+ private:
+ scoped_refptr<HostResolverImpl> impl_;
+ scoped_refptr<RuleBasedHostResolverProc> rules_;
+};
+
+// RuleBasedHostResolverProc applies a set of rules to map a host string to
+// a replacement host string. It then uses the system host resolver to return
+// a socket address. Generally the replacement should be an IPv4 literal so
+// there is no network dependency.
+class RuleBasedHostResolverProc : public HostResolverProc {
+ public:
+ explicit RuleBasedHostResolverProc(HostResolverProc* previous);
+ ~RuleBasedHostResolverProc();
+
+ // Any hostname matching the given pattern will be replaced with the given
+ // replacement value. Usually, replacement should be an IP address literal.
+ void AddRule(const std::string& host_pattern,
+ const std::string& replacement);
+
+ void AddRuleWithLatency(const std::string& host_pattern,
+ const std::string& replacement,
+ int latency_ms);
+
+ // Make sure that |host| will not be re-mapped or even processed by underlying
+ // host resolver procedures. It can also be a pattern.
+ void AllowDirectLookup(const std::string& host);
+
+ // Simulate a lookup failure for |host| (it also can be a pattern).
+ void AddSimulatedFailure(const std::string& host);
+
+ // HostResolverProc methods:
+ virtual int Resolve(const std::string& host, AddressList* addrlist);
+
+ private:
+ struct Rule;
+ typedef std::list<Rule> RuleList;
+ RuleList rules_;
+};
+
+// Using WaitingHostResolverProc you can simulate very long lookups.
+class WaitingHostResolverProc : public HostResolverProc {
+ public:
+ explicit WaitingHostResolverProc(HostResolverProc* previous)
+ : HostResolverProc(previous), event_(false, false) {}
+
+ void Signal() {
+ event_.Signal();
+ }
+
+ // HostResolverProc methods:
+ virtual int Resolve(const std::string& host, AddressList* addrlist) {
+ event_.Wait();
+ return ResolveUsingPrevious(host, addrlist);
+ }
+
+ base::WaitableEvent event_;
+};
+
+// This class sets the HostResolverProc for a particular scope. If there are
+// multiple ScopedDefaultHostResolverProc in existence, then the last one
+// allocated will be used. However, if it does not provide a matching rule,
+// then it should delegate to the previously set HostResolverProc.
+//
+// NOTE: Only use this as a catch-all safety net. Individual tests should use
+// MockHostResolver.
+class ScopedDefaultHostResolverProc {
+ public:
+ ScopedDefaultHostResolverProc() {}
+ explicit ScopedDefaultHostResolverProc(HostResolverProc* proc);
+
+ ~ScopedDefaultHostResolverProc();
+
+ void Init(HostResolverProc* proc);
+
+ private:
+ scoped_refptr<HostResolverProc> current_proc_;
+ scoped_refptr<HostResolverProc> previous_proc_;
+};
+
+} // namespace net
+
+#endif // NET_BASE_MOCK_HOST_RESOLVER_H_
diff --git a/net/base/run_all_unittests.cc b/net/base/run_all_unittests.cc
index 6c60e2d..c4c4df7 100644
--- a/net/base/run_all_unittests.cc
+++ b/net/base/run_all_unittests.cc
@@ -30,7 +30,7 @@
#include "base/message_loop.h"
#include "base/ref_counted.h"
#include "base/test_suite.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
class NetTestSuite : public TestSuite {
public:
@@ -40,12 +40,12 @@ class NetTestSuite : public TestSuite {
virtual void Initialize() {
TestSuite::Initialize();
- host_mapper_ = new net::RuleBasedHostMapper();
- scoped_host_mapper_.Init(host_mapper_.get());
+ host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL);
+ scoped_host_resolver_proc_.Init(host_resolver_proc_.get());
// In case any attempts are made to resolve host names, force them all to
// be mapped to localhost. This prevents DNS queries from being sent in
// the process of running these unit tests.
- host_mapper_->AddRule("*", "127.0.0.1");
+ host_resolver_proc_->AddRule("*", "127.0.0.1");
message_loop_.reset(new MessageLoopForIO());
}
@@ -60,8 +60,8 @@ class NetTestSuite : public TestSuite {
private:
scoped_ptr<MessageLoop> message_loop_;
- scoped_refptr<net::RuleBasedHostMapper> host_mapper_;
- net::ScopedHostMapper scoped_host_mapper_;
+ scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_;
+ net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_;
};
int main(int argc, char** argv) {
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index c81fc0f..d549b2f 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -5,9 +5,8 @@
#include "net/ftp/ftp_network_transaction.h"
#include "base/ref_counted.h"
-#include "net/base/host_resolver.h"
-#include "net/base/host_resolver_unittest.h"
#include "net/base/io_buffer.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/test_completion_callback.h"
#include "net/ftp/ftp_network_session.h"
#include "net/ftp/ftp_request_info.h"
@@ -237,7 +236,8 @@ class FtpMockControlSocketFileDownloadRetrFail
class FtpNetworkTransactionTest : public PlatformTest {
public:
FtpNetworkTransactionTest()
- : session_(new FtpNetworkSession(new HostResolver)),
+ : host_resolver_(new MockHostResolver),
+ session_(new FtpNetworkSession(host_resolver_)),
transaction_(session_.get(), &mock_socket_factory_) {
}
@@ -286,6 +286,7 @@ class FtpNetworkTransactionTest : public PlatformTest {
ExecuteTransaction(ctrl_socket, request, expected_result);
}
+ scoped_refptr<MockHostResolver> host_resolver_;
scoped_refptr<FtpNetworkSession> session_;
MockClientSocketFactory mock_socket_factory_;
FtpNetworkTransaction transaction_;
@@ -294,9 +295,7 @@ class FtpNetworkTransactionTest : public PlatformTest {
TEST_F(FtpNetworkTransactionTest, FailedLookup) {
FtpRequestInfo request_info = GetRequestInfo("ftp://badhost");
- scoped_refptr<RuleBasedHostMapper> mapper(new RuleBasedHostMapper());
- mapper->AddSimulatedFailure("badhost");
- ScopedHostMapper scoped_mapper(mapper.get());
+ host_resolver_->rules()->AddSimulatedFailure("badhost");
ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_));
EXPECT_EQ(ERR_FAILED, callback_.WaitForResult());
}
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 9fd35ea..b61ca3d 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/host_resolver.h"
+#include "net/base/mock_host_resolver.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_transaction_unittest.h"
#include "net/proxy/proxy_service.h"
@@ -16,7 +16,7 @@ class HttpNetworkLayerTest : public PlatformTest {
TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
scoped_ptr<net::ProxyService> proxy_service(net::ProxyService::CreateNull());
net::HttpNetworkLayer factory(
- NULL, new net::HostResolver, proxy_service.get());
+ NULL, new net::MockHostResolver, proxy_service.get());
scoped_ptr<net::HttpTransaction> trans(factory.CreateTransaction());
}
@@ -24,7 +24,7 @@ TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
TEST_F(HttpNetworkLayerTest, Suspend) {
scoped_ptr<net::ProxyService> proxy_service(net::ProxyService::CreateNull());
net::HttpNetworkLayer factory(
- NULL, new net::HostResolver, proxy_service.get());
+ NULL, new net::MockHostResolver, proxy_service.get());
scoped_ptr<net::HttpTransaction> trans(factory.CreateTransaction());
trans.reset();
@@ -56,7 +56,7 @@ TEST_F(HttpNetworkLayerTest, GET) {
mock_socket_factory.AddMockSocket(&data);
scoped_ptr<net::ProxyService> proxy_service(net::ProxyService::CreateNull());
- net::HttpNetworkLayer factory(&mock_socket_factory, new net::HostResolver,
+ net::HttpNetworkLayer factory(&mock_socket_factory, new net::MockHostResolver,
proxy_service.get());
TestCompletionCallback callback;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 74764a5..c1510a1 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -6,7 +6,7 @@
#include "base/compiler_specific.h"
#include "net/base/completion_callback.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/ssl_info.h"
#include "net/base/test_completion_callback.h"
#include "net/base/upload_data.h"
@@ -35,14 +35,14 @@ ProxyService* CreateNullProxyService() {
class SessionDependencies {
public:
// Default set of dependencies -- "null" proxy service.
- SessionDependencies() : host_resolver(new HostResolver),
+ SessionDependencies() : host_resolver(new MockHostResolver),
proxy_service(CreateNullProxyService()) {}
// Custom proxy service dependency.
explicit SessionDependencies(ProxyService* proxy_service)
- : host_resolver(new HostResolver), proxy_service(proxy_service) {}
+ : host_resolver(new MockHostResolver), proxy_service(proxy_service) {}
- scoped_refptr<HostResolver> host_resolver;
+ scoped_refptr<MockHostResolver> host_resolver;
scoped_ptr<ProxyService> proxy_service;
MockClientSocketFactory socket_factory;
};
@@ -3351,12 +3351,11 @@ TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
}
TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
- scoped_refptr<RuleBasedHostMapper> host_mapper(new RuleBasedHostMapper());
- ScopedHostMapper scoped_host_mapper(host_mapper.get());
- host_mapper->AddSimulatedFailure("*");
-
SessionDependencies session_deps(
CreateFixedProxyService("myproxy:70;foobar:80"));
+
+ session_deps.host_resolver->rules()->AddSimulatedFailure("*");
+
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(
CreateSession(&session_deps),
@@ -3457,6 +3456,10 @@ TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
// host cache is bypassed.
TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
SessionDependencies session_deps;
+
+ // Enable caching in the mock host resolver (it is off by default).
+ session_deps.host_resolver->Reset(NULL, 100, 60000);
+
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
CreateSession(&session_deps), &session_deps.socket_factory));
@@ -3473,14 +3476,12 @@ TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
rv = session_deps.host_resolver->Resolve(
HostResolver::RequestInfo("www.google.com", 80), &addrlist,
&resolve_callback, NULL);
- EXPECT_EQ(OK, rv);
+ ASSERT_EQ(OK, rv);
// Inject a failure the next time that "www.google.com" is resolved. This way
// we can tell if the next lookup hit the cache, or the "network".
// (cache --> success, "network" --> failure).
- scoped_refptr<RuleBasedHostMapper> host_mapper(new RuleBasedHostMapper());
- ScopedHostMapper scoped_host_mapper(host_mapper.get());
- host_mapper->AddSimulatedFailure("www.google.com");
+ session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
// Connect up a mock socket which will fail with ERR_UNEXPECTED during the
// first read -- this won't be reached as the host resolution will fail first.
diff --git a/net/net.gyp b/net/net.gyp
index 82b2e63..4f97ec9 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -75,6 +75,10 @@
'base/host_cache.h',
'base/host_resolver.cc',
'base/host_resolver.h',
+ 'base/host_resolver_impl.cc',
+ 'base/host_resolver_impl.h',
+ 'base/host_resolver_proc.cc',
+ 'base/host_resolver_proc.h',
'base/io_buffer.cc',
'base/io_buffer.h',
'base/listen_socket.cc',
@@ -85,6 +89,9 @@
'base/mime_sniffer.h',
'base/mime_util.cc',
'base/mime_util.h',
+ # TODO(eroman): move this into its own test-support target.
+ 'base/mock_host_resolver.cc',
+ 'base/mock_host_resolver.h',
'base/net_error_list.h',
'base/net_errors.cc',
'base/net_errors.h',
@@ -434,8 +441,7 @@
'base/force_tls_state_unittest.cc',
'base/gzip_filter_unittest.cc',
'base/host_cache_unittest.cc',
- 'base/host_resolver_unittest.cc',
- 'base/host_resolver_unittest.h',
+ 'base/host_resolver_impl_unittest.cc',
'base/listen_socket_unittest.cc',
'base/listen_socket_unittest.h',
'base/mime_sniffer_unittest.cc',
diff --git a/net/proxy/proxy_resolver_perftest.cc b/net/proxy/proxy_resolver_perftest.cc
index 22f2350..7c74e72 100644
--- a/net/proxy/proxy_resolver_perftest.cc
+++ b/net/proxy/proxy_resolver_perftest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/perftimer.h"
+#include "net/base/mock_host_resolver.h"
#include "net/proxy/proxy_resolver_v8.h"
#include "net/url_request/url_request_unittest.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -186,7 +187,8 @@ TEST(ProxyResolverPerfTest, ProxyResolverMac) {
TEST(ProxyResolverPerfTest, ProxyResolverV8) {
net::ProxyResolverV8::JSBindings* js_bindings =
- net::ProxyResolverV8::CreateDefaultBindings(new net::HostResolver, NULL);
+ net::ProxyResolverV8::CreateDefaultBindings(
+ new net::MockHostResolver, NULL);
net::ProxyResolverV8 resolver(js_bindings);
PacPerfSuiteRunner runner(&resolver, "ProxyResolverV8");
diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h
index 3bf2bec..6fbc968 100644
--- a/net/proxy/proxy_resolver_v8.h
+++ b/net/proxy/proxy_resolver_v8.h
@@ -56,7 +56,7 @@ class ProxyResolverV8 : public ProxyResolver {
// Creates a default javascript bindings implementation that will:
// - Send script error messages to LOG(INFO)
// - Send script alert()s to LOG(INFO)
- // - Use the provided host mapper to service dnsResolve().
+ // - Use the provided host resolver to service dnsResolve().
//
// For clients that need more control (for example, sending the script output
// to a UI widget), use the ProxyResolverV8(JSBindings*) and specify your
diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc
index 7fab7d7..86544d5 100644
--- a/net/proxy/proxy_resolver_v8_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_unittest.cc
@@ -6,7 +6,7 @@
#include "base/string_util.h"
#include "base/path_service.h"
#include "googleurl/src/gurl.h"
-#include "net/base/host_resolver.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_resolver_v8.h"
#include "net/proxy/proxy_info.h"
@@ -379,7 +379,8 @@ TEST(ProxyResolverV8Test, V8Bindings) {
TEST(ProxyResolverV8DefaultBindingsTest, DnsResolve) {
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<net::ProxyResolverV8::JSBindings> bindings(
- net::ProxyResolverV8::CreateDefaultBindings(new net::HostResolver, NULL));
+ net::ProxyResolverV8::CreateDefaultBindings(
+ new net::MockHostResolver, NULL));
// Considered an error.
EXPECT_EQ("", bindings->DnsResolve(""));
@@ -411,7 +412,7 @@ TEST(ProxyResolverV8DefaultBindingsTest, DnsResolve) {
// THIS TEST IS CURRENTLY FLAWED.
//
// Since we are running in unit-test mode, the HostResolve is using a
- // mock HostMapper, which will always return 127.0.0.1, without going
+ // mock HostResolverProc, which will always return 127.0.0.1, without going
// through the real codepaths.
//
// It is important that these tests be run with the real thing, since we
@@ -430,10 +431,11 @@ TEST(ProxyResolverV8DefaultBindingsTest, DnsResolve) {
TEST(ProxyResolverV8DefaultBindingsTest, MyIpAddress) {
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<net::ProxyResolverV8::JSBindings> bindings(
- net::ProxyResolverV8::CreateDefaultBindings(new net::HostResolver, NULL));
+ net::ProxyResolverV8::CreateDefaultBindings(
+ new net::MockHostResolver, NULL));
- // Our ip address is always going to be 127.0.0.1, since we are using a
- // mock host mapper when running in unit-test mode.
+ // Our IP address is always going to be 127.0.0.1, since we are using a
+ // mock host resolver.
std::string my_ip_address = bindings->MyIpAddress();
EXPECT_EQ("127.0.0.1", my_ip_address);
diff --git a/net/proxy/proxy_script_fetcher_unittest.cc b/net/proxy/proxy_script_fetcher_unittest.cc
index 8a7cfb5..8a8030b 100644
--- a/net/proxy/proxy_script_fetcher_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_unittest.cc
@@ -30,7 +30,7 @@ class RequestContext : public URLRequestContext {
public:
RequestContext() {
net::ProxyConfig no_proxy;
- host_resolver_ = new net::HostResolver;
+ host_resolver_ = net::CreateSystemHostResolver();
proxy_service_ = net::ProxyService::CreateFixed(no_proxy);
http_transaction_factory_ =
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 8874686..e4faf5b 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -7,7 +7,6 @@
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "base/scoped_vector.h"
-#include "net/base/host_resolver_unittest.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/client_socket.h"
@@ -793,7 +792,7 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
ClientSocketPoolBase::EnableLateBindingOfSockets(false);
// Start job 1 (async OK)
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
TestSocketRequest req1(pool_.get(), &request_order_);
int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
@@ -1135,7 +1134,7 @@ TEST_F(ClientSocketPoolBaseTest_LateBinding, ReleaseSockets) {
CreatePool(kDefaultMaxSocketsPerGroup);
// Start job 1 (async OK)
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
TestSocketRequest req1(pool_.get(), &request_order_);
int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
@@ -1178,7 +1177,7 @@ TEST_F(ClientSocketPoolBaseTest_LateBinding, ReleaseSockets) {
TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingJobCompletionOrder) {
CreatePool(kDefaultMaxSocketsPerGroup);
// First two jobs are async.
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockPendingFailingJob);
TestSocketRequest req1(pool_.get(), &request_order_);
int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
@@ -1189,7 +1188,7 @@ TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingJobCompletionOrder) {
EXPECT_EQ(ERR_IO_PENDING, rv);
// The pending job is sync.
- connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
+ connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
TestSocketRequest req3(pool_.get(), &request_order_);
rv = req3.handle.Init("a", ignored_request_info_, 5, &req3);
@@ -1208,7 +1207,7 @@ TEST_F(ClientSocketPoolBaseTest_LateBinding, PendingJobCompletionOrder) {
TEST_F(ClientSocketPoolBaseTest_LateBinding, LoadState) {
CreatePool(kDefaultMaxSocketsPerGroup);
connect_job_factory_->set_job_type(
- TestConnectJob::kMockAdvancingLoadStateJob);
+ TestConnectJob::kMockAdvancingLoadStateJob);
TestSocketRequest req1(pool_.get(), &request_order_);
int rv = req1.handle.Init("a", ignored_request_info_, 5, &req1);
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index 8f763c4..b225887 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -12,7 +12,7 @@
#include <netdb.h>
#endif
#include "net/base/address_list.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/test_completion_callback.h"
#include "net/base/winsock_init.h"
#include "net/socket/client_socket_factory.h"
@@ -41,10 +41,8 @@ class SOCKS5ClientSocketTest : public PlatformTest {
scoped_ptr<SOCKS5ClientSocket> user_sock_;
AddressList address_list_;
ClientSocket* tcp_sock_;
- ScopedHostMapper host_mapper_;
TestCompletionCallback callback_;
- scoped_refptr<RuleBasedHostMapper> mapper_;
- scoped_refptr<HostResolver> host_resolver_;
+ scoped_refptr<MockHostResolver> host_resolver_;
scoped_ptr<MockSocket> mock_socket_;
private:
@@ -52,7 +50,7 @@ class SOCKS5ClientSocketTest : public PlatformTest {
};
SOCKS5ClientSocketTest::SOCKS5ClientSocketTest()
- : kNwPort(htons(80)), host_resolver_(new HostResolver(0, 0)) {
+ : kNwPort(htons(80)), host_resolver_(new MockHostResolver) {
}
// Set up platform before every test case
@@ -60,14 +58,9 @@ void SOCKS5ClientSocketTest::SetUp() {
PlatformTest::SetUp();
// Resolve the "localhost" AddressList used by the TCP connection to connect.
- scoped_refptr<HostResolver> resolver = new HostResolver();
HostResolver::RequestInfo info("www.socks-proxy.com", 1080);
- int rv = resolver->Resolve(info, &address_list_, NULL, NULL);
+ int rv = host_resolver_->Resolve(info, &address_list_, NULL, NULL);
ASSERT_EQ(OK, rv);
-
- // Create a new host mapping for the duration of this test case only.
- mapper_ = new RuleBasedHostMapper();
- host_mapper_.Init(mapper_);
}
SOCKS5ClientSocket* SOCKS5ClientSocketTest::BuildMockSocket(
@@ -153,7 +146,7 @@ TEST_F(SOCKS5ClientSocketTest, FailedDNS) {
const std::string hostname = "unresolved.ipv4.address";
const char kSOCKS5DomainRequest[] = { 0x05, 0x01, 0x00, 0x03 };
- mapper_->AddSimulatedFailure(hostname.c_str());
+ host_resolver_->rules()->AddSimulatedFailure(hostname.c_str());
std::string request(kSOCKS5DomainRequest,
arraysize(kSOCKS5DomainRequest));
@@ -186,12 +179,11 @@ TEST_F(SOCKS5ClientSocketTest, IPv6Domain) {
const uint8 ipv6_addr[] = { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90,
0x00, 0x00, 0x00, 0x00, 0x00, 0x000, 0x00, 0x12 };
- mapper_->AddRule(hostname.c_str(), "2001:db8:8714:3a90::12");
+ host_resolver_->rules()->AddRule(hostname, "2001:db8:8714:3a90::12");
AddressList address_list;
- scoped_refptr<HostResolver> resolver = new HostResolver();
HostResolver::RequestInfo info(hostname, 80);
- int rv = resolver->Resolve(info, &address_list, NULL, NULL);
+ int rv = host_resolver_->Resolve(info, &address_list, NULL, NULL);
if (rv != OK || !address_list.head()) {
// This machine does not support IPv6. We skip this test altogether.
// TODO(arindam): create a MockIPv6HostResolver to manually
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index b2e6627..3d7fa85 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -5,8 +5,8 @@
#include "net/socket/socks_client_socket.h"
#include "net/base/address_list.h"
-#include "net/base/host_resolver_unittest.h"
#include "net/base/listen_socket.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/test_completion_callback.h"
#include "net/base/winsock_init.h"
#include "net/socket/client_socket_factory.h"
@@ -36,10 +36,8 @@ class SOCKSClientSocketTest : public PlatformTest {
scoped_ptr<SOCKSClientSocket> user_sock_;
AddressList address_list_;
ClientSocket* tcp_sock_;
- ScopedHostMapper host_mapper_;
TestCompletionCallback callback_;
- scoped_refptr<RuleBasedHostMapper> mapper_;
- scoped_refptr<HostResolver> host_resolver_;
+ scoped_refptr<MockHostResolver> host_resolver_;
scoped_ptr<MockSocket> mock_socket_;
private:
@@ -47,23 +45,12 @@ class SOCKSClientSocketTest : public PlatformTest {
};
SOCKSClientSocketTest::SOCKSClientSocketTest()
- : host_resolver_(new HostResolver(0, 0)) {
+ : host_resolver_(new MockHostResolver) {
}
// Set up platform before every test case
void SOCKSClientSocketTest::SetUp() {
PlatformTest::SetUp();
-
- // Resolve the "localhost" AddressList used by the tcp_connection to connect.
- scoped_refptr<HostResolver> resolver = new HostResolver();
- HostResolver::RequestInfo info("localhost", 1080);
- int rv = resolver->Resolve(info, &address_list_, NULL, NULL);
- ASSERT_EQ(OK, rv);
-
- // Create a new host mapping for the duration of this test case only.
- mapper_ = new RuleBasedHostMapper();
- host_mapper_.Init(mapper_);
- mapper_->AddRule("www.google.com", "127.0.0.1");
}
SOCKSClientSocket* SOCKSClientSocketTest::BuildMockSocket(
@@ -240,7 +227,7 @@ TEST_F(SOCKSClientSocketTest, FailedSocketRead) {
TEST_F(SOCKSClientSocketTest, SOCKS4AFailedDNS) {
const char hostname[] = "unresolved.ipv4.address";
- mapper_->AddSimulatedFailure(hostname);
+ host_resolver_->rules()->AddSimulatedFailure(hostname);
std::string request(kSOCKS4aInitialRequest,
arraysize(kSOCKS4aInitialRequest));
@@ -266,7 +253,7 @@ TEST_F(SOCKSClientSocketTest, SOCKS4AFailedDNS) {
TEST_F(SOCKSClientSocketTest, SOCKS4AIfDomainInIPv6) {
const char hostname[] = "an.ipv6.address";
- mapper_->AddRule(hostname, "2001:db8:8714:3a90::12");
+ host_resolver_->rules()->AddRule(hostname, "2001:db8:8714:3a90::12");
std::string request(kSOCKS4aInitialRequest,
arraysize(kSOCKS4aInitialRequest));
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 1d68bd1..e0520e5 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -23,7 +23,8 @@ const net::SSLConfig kDefaultSSLConfig;
class SSLClientSocketTest : public PlatformTest {
public:
SSLClientSocketTest()
- : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
+ : resolver_(net::CreateSystemHostResolver()),
+ socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
}
void StartOKServer() {
@@ -48,6 +49,7 @@ class SSLClientSocketTest : public PlatformTest {
}
protected:
+ scoped_refptr<net::HostResolver> resolver_;
net::ClientSocketFactory* socket_factory_;
net::TestServerLauncher server_;
};
@@ -86,11 +88,10 @@ TEST_F(SSLClientSocketTest, MAYBE_Connect) {
StartOKServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
- int rv = resolver->Resolve(info, &addr, NULL, NULL);
+ int rv = resolver_->Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -124,11 +125,10 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectExpired) {
StartExpiredServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kHostName, server_.kBadHTTPSPort);
- int rv = resolver->Resolve(info, &addr, NULL, NULL);
+ int rv = resolver_->Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -161,12 +161,11 @@ TEST_F(SSLClientSocketTest, MAYBE_ConnectMismatched) {
StartMismatchedServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kMismatchedHostName,
server_.kOKHTTPSPort);
- int rv = resolver->Resolve(info, &addr, NULL, NULL);
+ int rv = resolver_->Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -204,11 +203,10 @@ TEST_F(SSLClientSocketTest, MAYBE_Read) {
StartOKServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
- int rv = resolver->Resolve(info, &addr, &callback, NULL);
+ int rv = resolver_->Resolve(info, &addr, &callback, NULL);
EXPECT_EQ(net::ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
@@ -265,11 +263,10 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_SmallChunks) {
StartOKServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
- int rv = resolver->Resolve(info, &addr, NULL, NULL);
+ int rv = resolver_->Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
@@ -321,11 +318,10 @@ TEST_F(SSLClientSocketTest, MAYBE_Read_Interrupted) {
StartOKServer();
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
TestCompletionCallback callback;
net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
- int rv = resolver->Resolve(info, &addr, NULL, NULL);
+ int rv = resolver_->Resolve(info, &addr, NULL, NULL);
EXPECT_EQ(net::OK, rv);
net::ClientSocket *transport = new net::TCPClientSocket(addr);
diff --git a/net/socket/ssl_test_util.cc b/net/socket/ssl_test_util.cc
index 0f012f5..1acc0b5 100644
--- a/net/socket/ssl_test_util.cc
+++ b/net/socket/ssl_test_util.cc
@@ -246,7 +246,7 @@ bool TestServerLauncher::WaitToStart(const std::string& host_name, int port) {
// Verify that the webserver is actually started.
// Otherwise tests can fail if they run faster than Python can start.
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> resolver(net::CreateSystemHostResolver());
net::HostResolver::RequestInfo info(host_name, port);
int rv = resolver->Resolve(info, &addr, NULL, NULL);
if (rv != net::OK)
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index 5d9e630..b5cce2c 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -6,7 +6,7 @@
#include "base/compiler_specific.h"
#include "base/message_loop.h"
-#include "net/base/host_resolver_unittest.h"
+#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/client_socket.h"
@@ -224,14 +224,16 @@ int TestSocketRequest::completion_count = 0;
class TCPClientSocketPoolTest : public testing::Test {
protected:
TCPClientSocketPoolTest()
- : pool_(new TCPClientSocketPool(kMaxSocketsPerGroup,
- new HostResolver,
- &client_socket_factory_)) {}
+ : host_resolver_(new MockHostResolver),
+ pool_(new TCPClientSocketPool(kMaxSocketsPerGroup,
+ host_resolver_,
+ &client_socket_factory_)) {
+ // We enable caching on the mock host-resolver (it is off by default),
+ // because some of the tests in this file expect it.
+ host_resolver_->Reset(NULL, 100, 60000);
+ }
virtual void SetUp() {
- RuleBasedHostMapper *host_mapper = new RuleBasedHostMapper();
- host_mapper->AddRule("*", "127.0.0.1");
- scoped_host_mapper_.Init(host_mapper);
TestSocketRequest::completion_count = 0;
}
@@ -241,7 +243,7 @@ class TCPClientSocketPoolTest : public testing::Test {
MessageLoop::current()->RunAllPending();
}
- ScopedHostMapper scoped_host_mapper_;
+ scoped_refptr<MockHostResolver> host_resolver_;
MockClientSocketFactory client_socket_factory_;
scoped_refptr<ClientSocketPool> pool_;
std::vector<TestSocketRequest*> request_order_;
@@ -264,9 +266,7 @@ TEST_F(TCPClientSocketPoolTest, Basic) {
}
TEST_F(TCPClientSocketPoolTest, InitHostResolutionFailure) {
- RuleBasedHostMapper* host_mapper = new RuleBasedHostMapper;
- host_mapper->AddSimulatedFailure("unresolvable.host.name");
- ScopedHostMapper scoped_host_mapper(host_mapper);
+ host_resolver_->rules()->AddSimulatedFailure("unresolvable.host.name");
TestSocketRequest req(pool_.get(), &request_order_);
HostResolver::RequestInfo info("unresolvable.host.name", 80);
EXPECT_EQ(ERR_IO_PENDING, req.handle.Init("a", info, 5, &req));
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index 91b0e57..6d14694 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -86,7 +86,7 @@ void TCPClientSocketTest::SetUp() {
listen_port_ = port;
AddressList addr;
- scoped_refptr<HostResolver> resolver(new HostResolver);
+ scoped_refptr<HostResolver> resolver(CreateSystemHostResolver());
HostResolver::RequestInfo info("localhost", listen_port_);
int rv = resolver->Resolve(info, &addr, NULL, NULL);
CHECK(rv == OK);
diff --git a/net/socket/tcp_pinger_unittest.cc b/net/socket/tcp_pinger_unittest.cc
index c807007..b1e678f 100644
--- a/net/socket/tcp_pinger_unittest.cc
+++ b/net/socket/tcp_pinger_unittest.cc
@@ -65,7 +65,7 @@ void TCPPingerTest::SetUp() {
TEST_F(TCPPingerTest, Ping) {
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> resolver(net::CreateSystemHostResolver());
net::HostResolver::RequestInfo info("localhost", listen_port_);
int rv = resolver->Resolve(info, &addr, NULL, NULL);
@@ -78,7 +78,7 @@ TEST_F(TCPPingerTest, Ping) {
TEST_F(TCPPingerTest, PingFail) {
net::AddressList addr;
- scoped_refptr<net::HostResolver> resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> resolver(net::CreateSystemHostResolver());
// "Kill" "server"
listen_sock_ = NULL;
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
index 783c91d..63083c4 100644
--- a/net/tools/fetch/fetch_client.cc
+++ b/net/tools/fetch/fetch_client.cc
@@ -127,7 +127,9 @@ int main(int argc, char**argv) {
// Do work here.
MessageLoop loop;
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver);
+ scoped_refptr<net::HostResolver> host_resolver(
+ net::CreateSystemHostResolver());
+
scoped_ptr<net::ProxyService> proxy_service(net::ProxyService::CreateNull());
net::HttpTransactionFactory* factory = NULL;
if (use_cache) {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 220d7e0..2aaac0a 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -45,7 +45,7 @@ namespace {
class URLRequestHttpCacheContext : public URLRequestContext {
public:
URLRequestHttpCacheContext() {
- host_resolver_ = new net::HostResolver;
+ host_resolver_ = net::CreateSystemHostResolver();
proxy_service_ = net::ProxyService::CreateNull();
http_transaction_factory_ =
new net::HttpCache(
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
index a08d776..61a1712 100644
--- a/net/url_request/url_request_unittest.h
+++ b/net/url_request/url_request_unittest.h
@@ -43,7 +43,7 @@ using base::TimeDelta;
class TestURLRequestContext : public URLRequestContext {
public:
TestURLRequestContext() {
- host_resolver_ = new net::HostResolver;
+ host_resolver_ = net::CreateSystemHostResolver();
proxy_service_ = net::ProxyService::CreateNull();
http_transaction_factory_ =
net::HttpNetworkLayer::CreateFactory(host_resolver_,
@@ -51,7 +51,7 @@ class TestURLRequestContext : public URLRequestContext {
}
explicit TestURLRequestContext(const std::string& proxy) {
- host_resolver_ = new net::HostResolver;
+ host_resolver_ = net::CreateSystemHostResolver();
net::ProxyConfig proxy_config;
proxy_config.proxy_rules.ParseFromString(proxy);
proxy_service_ = net::ProxyService::CreateFixed(proxy_config);
diff --git a/webkit/tools/test_shell/test_shell_request_context.cc b/webkit/tools/test_shell/test_shell_request_context.cc
index cd0f31a..1d1c11c 100644
--- a/webkit/tools/test_shell/test_shell_request_context.cc
+++ b/webkit/tools/test_shell/test_shell_request_context.cc
@@ -45,7 +45,7 @@ void TestShellRequestContext::Init(
// issues.
no_proxy = true;
#endif
- host_resolver_ = new net::HostResolver();
+ host_resolver_ = net::CreateSystemHostResolver();
proxy_service_ = net::ProxyService::Create(no_proxy ? &proxy_config : NULL,
false, NULL, NULL);